[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.ir.getSuperInterfaces
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.isVoidAsReturnType
|
import org.jetbrains.kotlin.backend.konan.llvm.isVoidAsReturnType
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.longName
|
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.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
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.expressions.IrConstructorCall
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||||
@@ -150,21 +150,14 @@ private fun IrFunction.bridgeDirectionToAt(overriddenFunction: IrFunction, index
|
|||||||
return if (otherKind == kind)
|
return if (otherKind == kind)
|
||||||
BridgeDirection.NONE
|
BridgeDirection.NONE
|
||||||
else when (kind) {
|
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(
|
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)
|
BridgeDirectionKind.BOX)
|
||||||
TypeKind.ABSENT -> error("TypeKind.ABSENT should be on both sides")
|
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>) {
|
internal class BridgeDirections(private val array: Array<BridgeDirection>) {
|
||||||
constructor(irFunction: IrSimpleFunction, overriddenFunction: IrSimpleFunction)
|
constructor(irFunction: IrSimpleFunction, overriddenFunction: IrSimpleFunction)
|
||||||
: this(Array<BridgeDirection>(ParameterIndex.allParametersCount(irFunction)) {
|
: 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 {
|
private fun evaluateCast(value: IrTypeOperatorCall): LLVMValueRef {
|
||||||
context.log{"evaluateCast : ${ir2string(value)}"}
|
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)
|
val srcArg = evaluateExpression(value.argument)
|
||||||
assert(srcArg.type == codegen.kObjHeaderPtr)
|
assert(srcArg.type == codegen.kObjHeaderPtr)
|
||||||
|
|||||||
+1
-1
@@ -211,7 +211,7 @@ private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
|
|||||||
if (!typeSafeBarrierDescription.checkParameter(i))
|
if (!typeSafeBarrierDescription.checkParameter(i))
|
||||||
continue
|
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.
|
// 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.
|
// 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.
|
// But let's keep it simple here for now; JVM backend doesn't do this anyway.
|
||||||
|
|||||||
+2
-3
@@ -111,7 +111,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
return super.visitTypeOperator(expression)
|
return super.visitTypeOperator(expression)
|
||||||
}
|
}
|
||||||
reference.transformChildrenVoid()
|
reference.transformChildrenVoid()
|
||||||
return transformFunctionReference(reference, expression.typeOperand)
|
return transformFunctionReference(reference, expression.typeOperand.erasure())
|
||||||
}
|
}
|
||||||
return super.visitTypeOperator(expression)
|
return super.visitTypeOperator(expression)
|
||||||
}
|
}
|
||||||
@@ -377,8 +377,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
|
|||||||
val adaptedParameter = adaptedParameters[index]
|
val adaptedParameter = adaptedParameters[index]
|
||||||
if (originalParameter.defaultValue != null) return false
|
if (originalParameter.defaultValue != null) return false
|
||||||
if (originalParameter.isVararg) {
|
if (originalParameter.isVararg) {
|
||||||
if (originalParameter.varargElementType!!.erasureForTypeOperation()
|
if (originalParameter.varargElementType!!.erasure() == adaptedParameter.type.erasure())
|
||||||
== adaptedParameter.type.erasureForTypeOperation())
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
++index
|
++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.expressions.IrTypeOperatorCall
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
|
||||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
|
||||||
import org.jetbrains.kotlin.ir.util.irCall
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
import org.jetbrains.kotlin.ir.util.isSimpleTypeWithQuestionMark
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
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
|
if (this !is IrSimpleType) return this
|
||||||
|
|
||||||
return when (val classifier = classifier) {
|
val upperBound = when (val classifier = classifier) {
|
||||||
is IrClassSymbol -> this
|
is IrClassSymbol -> classifier.defaultType
|
||||||
is IrTypeParameterSymbol -> {
|
is IrTypeParameterSymbol -> {
|
||||||
val upperBound = classifier.owner.superTypes.firstOrNull()
|
// Pick the (necessarily unique) non-interface upper bound if it exists
|
||||||
?: TODO("${classifier.descriptor} : ${classifier.descriptor.upperBounds}")
|
classifier.owner.superTypes.firstOrNull {
|
||||||
|
it.classOrNull?.owner?.isInterface == false
|
||||||
if (this.hasQuestionMark) {
|
} ?:
|
||||||
// `T?`
|
// Otherwise, choose either the first IrClass supertype or recurse.
|
||||||
upperBound.erasureForTypeOperation().makeNullable()
|
// In the first case, all supertypes are interface types and the choice was arbitrary.
|
||||||
} else {
|
// In the second case, there is only a single supertype.
|
||||||
upperBound.erasureForTypeOperation()
|
classifier.owner.superTypes.first().erasure()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> TODO(classifier.toString())
|
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) {
|
internal class TypeOperatorLowering(val context: CommonBackendContext) : FileLoweringPass, IrBuildingTransformer(context) {
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildren(this, null)
|
irFile.transformChildren(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrType.erasure(): IrType = this.erasureForTypeOperation()
|
|
||||||
|
|
||||||
private fun lowerCast(expression: IrTypeOperatorCall): IrExpression {
|
private fun lowerCast(expression: IrTypeOperatorCall): IrExpression {
|
||||||
builder.at(expression)
|
builder.at(expression)
|
||||||
val typeOperand = expression.typeOperand.erasure()
|
val typeOperand = expression.typeOperand.erasure()
|
||||||
|
|||||||
+10
-31
@@ -5,18 +5,21 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.optimizations
|
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.allParameters
|
||||||
import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole
|
import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole
|
||||||
import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
|
import org.jetbrains.kotlin.backend.common.ir.simpleFunctions
|
||||||
import org.jetbrains.kotlin.backend.common.peek
|
import org.jetbrains.kotlin.backend.common.peek
|
||||||
import org.jetbrains.kotlin.backend.common.pop
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
|
import org.jetbrains.kotlin.backend.konan.getInlinedClassNative
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
import org.jetbrains.kotlin.backend.konan.ir.actualCallee
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.computeFunctionName
|
import org.jetbrains.kotlin.backend.konan.ir.isAny
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.localHash
|
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.IrElement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
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.symbols.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
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.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
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 expressionToEdge(expression: IrExpression) = expressionToScopedEdge(expression).value
|
||||||
|
|
||||||
private fun expressionToScopedEdge(expression: IrExpression) =
|
private fun expressionToScopedEdge(expression: IrExpression) =
|
||||||
@@ -595,7 +574,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
Scoped(
|
Scoped(
|
||||||
DataFlowIR.Edge(
|
DataFlowIR.Edge(
|
||||||
it.value,
|
it.value,
|
||||||
symbolTable.mapClassReferenceType(expression.typeOperand.erasure().getClass()!!)
|
symbolTable.mapClassReferenceType(expression.typeOperand.erasedUpperBound)
|
||||||
), it.scope)
|
), it.scope)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
Reference in New Issue
Block a user