Aligned SAM conversion lowering with the JVM's one
Also refactored other places with erasure
This commit is contained in:
Igor Chevdar
2021-09-08 23:55:11 +05:00
parent 72752473bf
commit 8464b15d27
6 changed files with 40 additions and 66 deletions
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.konan.ir.getSuperClassNotAny
import org.jetbrains.kotlin.backend.konan.ir.getSuperInterfaces
import org.jetbrains.kotlin.backend.konan.llvm.isVoidAsReturnType
import org.jetbrains.kotlin.backend.konan.llvm.longName
import org.jetbrains.kotlin.backend.konan.lower.erasedUpperBound
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.ir.IrBuiltIns
@@ -19,7 +20,6 @@ import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.resolve.annotations.argumentValue
import org.jetbrains.kotlin.resolve.constants.StringValue
@@ -150,21 +150,14 @@ private fun IrFunction.bridgeDirectionToAt(overriddenFunction: IrFunction, index
return if (otherKind == kind)
BridgeDirection.NONE
else when (kind) {
TypeKind.VOID, TypeKind.REFERENCE -> BridgeDirection(irClass?.erasure(), BridgeDirectionKind.UNBOX)
TypeKind.VOID, TypeKind.REFERENCE -> BridgeDirection(irClass?.erasedUpperBound, BridgeDirectionKind.UNBOX)
TypeKind.VALUE_TYPE -> BridgeDirection(
irClass?.erasure().takeIf { otherKind == TypeKind.VOID } /* Otherwise erase to [Any?] */,
irClass?.erasedUpperBound.takeIf { otherKind == TypeKind.VOID } /* Otherwise erase to [Any?] */,
BridgeDirectionKind.BOX)
TypeKind.ABSENT -> error("TypeKind.ABSENT should be on both sides")
}
}
private tailrec fun IrType.erasure(): IrClass =
when (val classifier = classifierOrFail) {
is IrClassSymbol -> classifier.owner
is IrTypeParameterSymbol -> classifier.owner.superTypes.first().erasure()
else -> error(classifier)
}
internal class BridgeDirections(private val array: Array<BridgeDirection>) {
constructor(irFunction: IrSimpleFunction, overriddenFunction: IrSimpleFunction)
: this(Array<BridgeDirection>(ParameterIndex.allParametersCount(irFunction)) {
@@ -1519,7 +1519,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
private fun evaluateCast(value: IrTypeOperatorCall): LLVMValueRef {
context.log{"evaluateCast : ${ir2string(value)}"}
val dstClass = value.typeOperand.getClass()!!
val dstClass = value.typeOperand.getClass()
?: error("No class for ${value.typeOperand.render()} from \n${functionGenerationContext.irFunction?.render()}")
val srcArg = evaluateExpression(value.argument)
assert(srcArg.type == codegen.kObjHeaderPtr)
@@ -211,7 +211,7 @@ private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
if (!typeSafeBarrierDescription.checkParameter(i))
continue
val type = originalValueParameters[i].type.erasureForTypeOperation()
val type = originalValueParameters[i].type.erasure()
// Note: erasing to single type is not entirely correct if type parameter has multiple upper bounds.
// In this case the compiler could generate multiple type checks, one for each upper bound.
// But let's keep it simple here for now; JVM backend doesn't do this anyway.
@@ -264,4 +264,4 @@ private fun Context.buildBridge(startOffset: Int, endOffset: Int,
+irReturn(delegatingCall)
}
return bridge
}
}
@@ -111,7 +111,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
return super.visitTypeOperator(expression)
}
reference.transformChildrenVoid()
return transformFunctionReference(reference, expression.typeOperand)
return transformFunctionReference(reference, expression.typeOperand.erasure())
}
return super.visitTypeOperator(expression)
}
@@ -377,8 +377,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
val adaptedParameter = adaptedParameters[index]
if (originalParameter.defaultValue != null) return false
if (originalParameter.isVararg) {
if (originalParameter.varargElementType!!.erasureForTypeOperation()
== adaptedParameter.type.erasureForTypeOperation())
if (originalParameter.varargElementType!!.erasure() == adaptedParameter.type.erasure())
return true
}
++index
@@ -17,42 +17,44 @@ import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
internal fun IrType.erasureForTypeOperation(): IrType {
// TODO: Similar to IrType.erasedUpperBound from jvm.ir
internal fun IrType.erasure(): IrType {
if (this !is IrSimpleType) return this
return when (val classifier = classifier) {
is IrClassSymbol -> this
val upperBound = when (val classifier = classifier) {
is IrClassSymbol -> classifier.defaultType
is IrTypeParameterSymbol -> {
val upperBound = classifier.owner.superTypes.firstOrNull()
?: TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}")
if (this.hasQuestionMark) {
// `T?`
upperBound.erasureForTypeOperation().makeNullable()
} else {
upperBound.erasureForTypeOperation()
}
// Pick the (necessarily unique) non-interface upper bound if it exists
classifier.owner.superTypes.firstOrNull {
it.classOrNull?.owner?.isInterface == false
} ?:
// Otherwise, choose either the first IrClass supertype or recurse.
// In the first case, all supertypes are interface types and the choice was arbitrary.
// In the second case, there is only a single supertype.
classifier.owner.superTypes.first().erasure()
}
else -> TODO(classifier.toString())
}
return if (this.hasQuestionMark)
upperBound.makeNullable()
else
upperBound
}
internal val IrType.erasedUpperBound get() = this.erasure().getClass() ?: error(this.render())
internal class TypeOperatorLowering(val context: CommonBackendContext) : FileLoweringPass, IrBuildingTransformer(context) {
override fun lower(irFile: IrFile) {
irFile.transformChildren(this, null)
}
private fun IrType.erasure(): IrType = this.erasureForTypeOperation()
private fun lowerCast(expression: IrTypeOperatorCall): IrExpression {
builder.at(expression)
val typeOperand = expression.typeOperand.erasure()
@@ -5,18 +5,21 @@
package org.jetbrains.kotlin.backend.konan.optimizations
import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.common.ir.allParameters
import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole
import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
import org.jetbrains.kotlin.backend.common.peek
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.llvm.computeFunctionName
import org.jetbrains.kotlin.backend.konan.llvm.localHash
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.getInlinedClassNative
import org.jetbrains.kotlin.backend.konan.ir.actualCallee
import org.jetbrains.kotlin.backend.konan.ir.isAny
import org.jetbrains.kotlin.backend.konan.ir.isObjCObjectType
import org.jetbrains.kotlin.backend.konan.ir.isVirtualCall
import org.jetbrains.kotlin.backend.konan.isNonGeneratedAnnotation
import org.jetbrains.kotlin.backend.konan.logMultiple
import org.jetbrains.kotlin.backend.konan.lower.erasedUpperBound
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
@@ -28,9 +31,6 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.getArguments
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
@@ -566,27 +566,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
)
}
private fun IrType.erasure(): IrType {
if (this !is IrSimpleType) return this
val classifier = this.classifier
return when (classifier) {
is IrClassSymbol -> this
is IrTypeParameterSymbol -> {
val upperBound = classifier.owner.superTypes.singleOrNull() ?:
TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}")
if (this.hasQuestionMark) {
// `T?`
upperBound.erasure().makeNullable()
} else {
upperBound.erasure()
}
}
else -> TODO(classifier.toString())
}
}
private fun expressionToEdge(expression: IrExpression) = expressionToScopedEdge(expression).value
private fun expressionToScopedEdge(expression: IrExpression) =
@@ -595,7 +574,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
Scoped(
DataFlowIR.Edge(
it.value,
symbolTable.mapClassReferenceType(expression.typeOperand.erasure().getClass()!!)
symbolTable.mapClassReferenceType(expression.typeOperand.erasedUpperBound)
), it.scope)
}
else {