[K/N][IR] Fix for https://youtrack.jetbrains.com/issue/KT-48559
Aligned SAM conversion lowering with the JVM's one Also refactored other places with erasure
This commit is contained in:
+3
-10
@@ -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)) {
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+2
-2
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -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
|
||||
|
||||
+21
-19
@@ -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()
|
||||
|
||||
+10
-31
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user