Implemented class delegation lowering
This commit is contained in:
+9
-8
@@ -37,18 +37,19 @@ internal class SpecialDescriptorsFactory(val context: Context) {
|
||||
false, false, false, false, false, false).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver)
|
||||
}
|
||||
|
||||
fun getBridgeDescriptor(descriptor: OverriddenFunctionDescriptor): FunctionDescriptor {
|
||||
val bridgeDirections = descriptor.bridgeDirections
|
||||
assert(descriptor.needBridge,
|
||||
{ "Function ${descriptor.descriptor} is not needed in a bridge to call overridden function ${descriptor.overriddenDescriptor}" })
|
||||
return bridgesDescriptors.getOrPut(descriptor.descriptor to bridgeDirections) {
|
||||
fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): FunctionDescriptor {
|
||||
val descriptor = overriddenFunctionDescriptor.descriptor.original
|
||||
assert(overriddenFunctionDescriptor.needBridge,
|
||||
{ "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor}" })
|
||||
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
||||
return bridgesDescriptors.getOrPut(descriptor to bridgeDirections) {
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
descriptor.descriptor.containingDeclaration,
|
||||
descriptor.containingDeclaration,
|
||||
Annotations.EMPTY,
|
||||
("<bridge-" + bridgeDirections.toString() + ">" + descriptor.descriptor.functionName).synthesizedName,
|
||||
("<bridge-" + bridgeDirections.toString() + ">" + descriptor.functionName).synthesizedName,
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
SourceElement.NO_SOURCE).apply {
|
||||
initializeBridgeDescriptor(this, descriptor.descriptor, bridgeDirections.array)
|
||||
initializeBridgeDescriptor(this, descriptor, bridgeDirections.array)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-1
@@ -55,8 +55,14 @@ internal class KonanLower(val context: Context) {
|
||||
phaser.phase(KonanPhase.LOWER_VARARG) {
|
||||
VarargInjectionLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_DELEGATION) {
|
||||
DelegationLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
|
||||
BridgesBuilding(context).lower(irFile)
|
||||
BridgesBuilding(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_DIRECT_BRIDGES_CALLS) {
|
||||
DirectBridgesCallsLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.AUTOBOX) {
|
||||
Autoboxing(context).lower(irFile)
|
||||
|
||||
+2
@@ -25,6 +25,8 @@ enum class KonanPhase(val description: String,
|
||||
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
|
||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering"),
|
||||
/* ... ... */ BRIDGES_BUILDING("Bridges building"),
|
||||
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
||||
/* ... ... */ LOWER_DIRECT_BRIDGES_CALLS("Direct bridges calls lowering"),
|
||||
/* ... */ BITCODE("LLVM BitCode Generation"),
|
||||
/* ... ... */ RTTI("RTTI Generation"),
|
||||
/* ... ... */ CODEGEN("Code Generation"),
|
||||
|
||||
+9
-18
@@ -16,22 +16,16 @@ internal class OverriddenFunctionDescriptor(val descriptor: FunctionDescriptor,
|
||||
get() {
|
||||
if (descriptor.modality == Modality.ABSTRACT) return false
|
||||
return descriptor.kind == CallableMemberDescriptor.Kind.DELEGATION
|
||||
//|| descriptor.needBridgeTo(overriddenDescriptor)
|
||||
|| descriptor.target.needBridgeTo(overriddenDescriptor)
|
||||
}
|
||||
|
||||
fun trivialOverride() = descriptor.original == overriddenDescriptor
|
||||
|
||||
val bridgeDirections: BridgeDirections
|
||||
get() {
|
||||
// if (descriptor.needBridgeTo(overriddenDescriptor))
|
||||
// return descriptor.bridgeDirectionsTo(overriddenDescriptor)
|
||||
return descriptor.target.bridgeDirectionsTo(overriddenDescriptor)
|
||||
}
|
||||
get() = descriptor.target.bridgeDirectionsTo(overriddenDescriptor)
|
||||
|
||||
val canBeCalledVirtually
|
||||
val canBeCalledVirtually: Boolean
|
||||
// We check that either method is open, or one of declarations it overrides is open.
|
||||
get() = overriddenDescriptor.isOverridable || DescriptorUtils.getAllOverriddenDeclarations(overriddenDescriptor).any { it.isOverridable }
|
||||
get() = overriddenDescriptor.isOverridable
|
||||
|| DescriptorUtils.getAllOverriddenDeclarations(overriddenDescriptor).any { it.isOverridable }
|
||||
|
||||
|
||||
override fun toString(): String {
|
||||
@@ -76,9 +70,8 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con
|
||||
if (overridingMethod == null) {
|
||||
superMethod
|
||||
} else {
|
||||
if (!superMethod.trivialOverride())
|
||||
newVtableSlots.add(OverriddenFunctionDescriptor(overridingMethod, superMethod.descriptor))
|
||||
// Overriding method is defined in the current class and is not inherited - take it as is.
|
||||
// Add all possible (descriptor, overriddenDescriptor) edges for now, redundant will be removed later.
|
||||
newVtableSlots.add(OverriddenFunctionDescriptor(overridingMethod, superMethod.descriptor))
|
||||
newVtableSlots.add(OverriddenFunctionDescriptor(overridingMethod, overridingMethod))
|
||||
OverriddenFunctionDescriptor(overridingMethod, superMethod.overriddenDescriptor)
|
||||
}
|
||||
@@ -94,15 +87,13 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con
|
||||
}
|
||||
println()
|
||||
|
||||
// TODO: why put all pairs <descriptor, overriddenDescriptor>?
|
||||
val zzz = inheritedVtableSlots.map { it.descriptor to it.bridgeDirections }.toSet()
|
||||
|
||||
methods// Find newly defined methods.
|
||||
// TODO: Select target because method might be taken from default implementation of interface.
|
||||
.mapTo(newVtableSlots) { OverriddenFunctionDescriptor(it, it) }
|
||||
methods.mapTo(newVtableSlots) { OverriddenFunctionDescriptor(it, it) }
|
||||
|
||||
|
||||
val filteredNewVtableSlots = newVtableSlots
|
||||
.filter { (it.descriptor.kind.isReal || it.needBridge) && !zzz.contains(it.descriptor to it.bridgeDirections) }
|
||||
.filter { !zzz.contains(it.descriptor to it.bridgeDirections) }
|
||||
.distinctBy { it.descriptor to it.bridgeDirections }
|
||||
.filter { it.descriptor.isOverridable }
|
||||
println("VTABLE_ENTRIES new vtable:")
|
||||
|
||||
+73
-7
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
internal class DirectBridgesCallsLowering(val context: Context) : BodyLoweringPass {
|
||||
@@ -33,11 +32,14 @@ internal class DirectBridgesCallsLowering(val context: Context) : BodyLoweringPa
|
||||
}
|
||||
|
||||
val target = descriptor.target
|
||||
if (descriptor.kind != CallableMemberDescriptor.Kind.DELEGATION && !descriptor.original.needBridgeTo(target))
|
||||
val needBridge = descriptor.original.needBridgeTo(target)
|
||||
if (descriptor.kind != CallableMemberDescriptor.Kind.DELEGATION && !needBridge)
|
||||
return expression
|
||||
|
||||
val toCall = if (needBridge) target else context.specialDescriptorsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(descriptor, target))
|
||||
|
||||
return IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
target, remapTypeArguments(expression, target)).apply {
|
||||
toCall, remapTypeArguments(expression, toCall)).apply {
|
||||
dispatchReceiver = expression.dispatchReceiver
|
||||
extensionReceiver = expression.extensionReceiver
|
||||
mapValueParameters { expression.getValueArgument(it)!! }
|
||||
@@ -59,6 +61,73 @@ internal class DirectBridgesCallsLowering(val context: Context) : BodyLoweringPa
|
||||
}
|
||||
}
|
||||
|
||||
private object DECLARATION_ORIGIN_BRIDGE_METHOD :
|
||||
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
||||
|
||||
internal class DelegationLowering(val context: Context) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
irClass.declarations.transformFlat {
|
||||
when (it) {
|
||||
is IrFunction -> {
|
||||
val transformedFun = transformBridgeToDelegatedMethod(irClass, it)
|
||||
if (transformedFun == null) null
|
||||
else listOf(transformedFun)
|
||||
}
|
||||
is IrProperty -> {
|
||||
val getter = transformBridgeToDelegatedMethod(irClass, it.getter)
|
||||
val setter = transformBridgeToDelegatedMethod(irClass, it.setter)
|
||||
if (getter != null || setter != null) {
|
||||
it.getter = getter
|
||||
it.setter = setter
|
||||
}
|
||||
null
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: hack because of broken IR for synthesized delegated members.
|
||||
private fun transformBridgeToDelegatedMethod(irClass: IrClass, irFunction: IrFunction?): IrFunction? {
|
||||
if (irFunction == null || irFunction.descriptor.kind != CallableMemberDescriptor.Kind.DELEGATION) return null
|
||||
|
||||
val body = irFunction.body as? IrBlockBody
|
||||
?: throw AssertionError("Unexpected method body: ${irFunction.body}")
|
||||
val statement = body.statements.single()
|
||||
val delegatedCall = ((statement as? IrReturn)?.value ?: statement) as? IrCall
|
||||
?: throw AssertionError("Unexpected method body: $statement")
|
||||
val propertyGetter = delegatedCall.dispatchReceiver as? IrGetValue
|
||||
?: throw AssertionError("Unexpected dispatch receiver: ${delegatedCall.dispatchReceiver}")
|
||||
val propertyDescriptor = propertyGetter.descriptor as? PropertyDescriptor
|
||||
?: throw AssertionError("Unexpected dispatch receiver descriptor: ${propertyGetter.descriptor}")
|
||||
val delegated = context.specialDescriptorsFactory.getBridgeDescriptor(
|
||||
OverriddenFunctionDescriptor(irFunction.descriptor, delegatedCall.descriptor as FunctionDescriptor))
|
||||
val newFunction = IrFunctionImpl(irFunction.startOffset, irFunction.endOffset, DECLARATION_ORIGIN_BRIDGE_METHOD, delegated)
|
||||
|
||||
val irBlockBody = IrBlockBodyImpl(irFunction.startOffset, irFunction.endOffset)
|
||||
val returnType = delegatedCall.descriptor.returnType!!
|
||||
val irCall = IrCallImpl(irFunction.startOffset, irFunction.endOffset, returnType, delegatedCall.descriptor, null)
|
||||
val receiver = IrGetValueImpl(irFunction.startOffset, irFunction.endOffset, irClass.descriptor.thisAsReceiverParameter)
|
||||
irCall.dispatchReceiver = IrGetFieldImpl(irFunction.startOffset, irFunction.endOffset, propertyDescriptor, receiver)
|
||||
irCall.extensionReceiver = delegated.extensionReceiverParameter?.let { extensionReceiver ->
|
||||
IrGetValueImpl(irFunction.startOffset, irFunction.endOffset, extensionReceiver)
|
||||
}
|
||||
irCall.mapValueParameters { overriddenValueParameter ->
|
||||
val delegatedValueParameter = delegated.valueParameters[overriddenValueParameter.index]
|
||||
IrGetValueImpl(irFunction.startOffset, irFunction.endOffset, delegatedValueParameter)
|
||||
}
|
||||
if (KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType)) {
|
||||
irBlockBody.statements.add(irCall)
|
||||
} else {
|
||||
val irReturn = IrReturnImpl(irFunction.startOffset, irFunction.endOffset, context.builtIns.nothingType, delegated, irCall)
|
||||
irBlockBody.statements.add(irReturn)
|
||||
}
|
||||
|
||||
newFunction.body = irBlockBody
|
||||
return newFunction
|
||||
}
|
||||
}
|
||||
|
||||
internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
val functions = mutableSetOf<FunctionDescriptor?>()
|
||||
@@ -78,7 +147,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
it?.let { function ->
|
||||
function.allOverriddenDescriptors
|
||||
.map { OverriddenFunctionDescriptor(function, it) }
|
||||
.filter { it.needBridge }
|
||||
.filter { !it.bridgeDirections.allNotNeeded() }
|
||||
.filter { it.canBeCalledVirtually }
|
||||
.distinctBy { it.bridgeDirections }
|
||||
.forEach { buildBridge(it, irClass)
|
||||
@@ -87,9 +156,6 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
private object DECLARATION_ORIGIN_BRIDGE_METHOD :
|
||||
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
||||
|
||||
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
|
||||
|
||||
println("BUILD_BRIDGE fun: ${descriptor.descriptor}")
|
||||
|
||||
Reference in New Issue
Block a user