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)
|
false, false, false, false, false, false).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBridgeDescriptor(descriptor: OverriddenFunctionDescriptor): FunctionDescriptor {
|
fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): FunctionDescriptor {
|
||||||
val bridgeDirections = descriptor.bridgeDirections
|
val descriptor = overriddenFunctionDescriptor.descriptor.original
|
||||||
assert(descriptor.needBridge,
|
assert(overriddenFunctionDescriptor.needBridge,
|
||||||
{ "Function ${descriptor.descriptor} is not needed in a bridge to call overridden function ${descriptor.overriddenDescriptor}" })
|
{ "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor}" })
|
||||||
return bridgesDescriptors.getOrPut(descriptor.descriptor to bridgeDirections) {
|
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
|
||||||
|
return bridgesDescriptors.getOrPut(descriptor to bridgeDirections) {
|
||||||
SimpleFunctionDescriptorImpl.create(
|
SimpleFunctionDescriptorImpl.create(
|
||||||
descriptor.descriptor.containingDeclaration,
|
descriptor.containingDeclaration,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
("<bridge-" + bridgeDirections.toString() + ">" + descriptor.descriptor.functionName).synthesizedName,
|
("<bridge-" + bridgeDirections.toString() + ">" + descriptor.functionName).synthesizedName,
|
||||||
CallableMemberDescriptor.Kind.DECLARATION,
|
CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
SourceElement.NO_SOURCE).apply {
|
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) {
|
phaser.phase(KonanPhase.LOWER_VARARG) {
|
||||||
VarargInjectionLowering(context).runOnFilePostfix(irFile)
|
VarargInjectionLowering(context).runOnFilePostfix(irFile)
|
||||||
}
|
}
|
||||||
|
phaser.phase(KonanPhase.LOWER_DELEGATION) {
|
||||||
|
DelegationLowering(context).runOnFilePostfix(irFile)
|
||||||
|
}
|
||||||
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
|
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) {
|
phaser.phase(KonanPhase.AUTOBOX) {
|
||||||
Autoboxing(context).lower(irFile)
|
Autoboxing(context).lower(irFile)
|
||||||
|
|||||||
+2
@@ -25,6 +25,8 @@ enum class KonanPhase(val description: String,
|
|||||||
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
|
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
|
||||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering"),
|
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering"),
|
||||||
/* ... ... */ BRIDGES_BUILDING("Bridges building"),
|
/* ... ... */ BRIDGES_BUILDING("Bridges building"),
|
||||||
|
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
||||||
|
/* ... ... */ LOWER_DIRECT_BRIDGES_CALLS("Direct bridges calls lowering"),
|
||||||
/* ... */ BITCODE("LLVM BitCode Generation"),
|
/* ... */ BITCODE("LLVM BitCode Generation"),
|
||||||
/* ... ... */ RTTI("RTTI Generation"),
|
/* ... ... */ RTTI("RTTI Generation"),
|
||||||
/* ... ... */ CODEGEN("Code Generation"),
|
/* ... ... */ CODEGEN("Code Generation"),
|
||||||
|
|||||||
+9
-18
@@ -16,22 +16,16 @@ internal class OverriddenFunctionDescriptor(val descriptor: FunctionDescriptor,
|
|||||||
get() {
|
get() {
|
||||||
if (descriptor.modality == Modality.ABSTRACT) return false
|
if (descriptor.modality == Modality.ABSTRACT) return false
|
||||||
return descriptor.kind == CallableMemberDescriptor.Kind.DELEGATION
|
return descriptor.kind == CallableMemberDescriptor.Kind.DELEGATION
|
||||||
//|| descriptor.needBridgeTo(overriddenDescriptor)
|
|
||||||
|| descriptor.target.needBridgeTo(overriddenDescriptor)
|
|| descriptor.target.needBridgeTo(overriddenDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun trivialOverride() = descriptor.original == overriddenDescriptor
|
|
||||||
|
|
||||||
val bridgeDirections: BridgeDirections
|
val bridgeDirections: BridgeDirections
|
||||||
get() {
|
get() = descriptor.target.bridgeDirectionsTo(overriddenDescriptor)
|
||||||
// if (descriptor.needBridgeTo(overriddenDescriptor))
|
|
||||||
// return descriptor.bridgeDirectionsTo(overriddenDescriptor)
|
|
||||||
return descriptor.target.bridgeDirectionsTo(overriddenDescriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
val canBeCalledVirtually
|
val canBeCalledVirtually: Boolean
|
||||||
// We check that either method is open, or one of declarations it overrides is open.
|
// 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 {
|
override fun toString(): String {
|
||||||
@@ -76,9 +70,8 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con
|
|||||||
if (overridingMethod == null) {
|
if (overridingMethod == null) {
|
||||||
superMethod
|
superMethod
|
||||||
} else {
|
} else {
|
||||||
if (!superMethod.trivialOverride())
|
// Add all possible (descriptor, overriddenDescriptor) edges for now, redundant will be removed later.
|
||||||
newVtableSlots.add(OverriddenFunctionDescriptor(overridingMethod, superMethod.descriptor))
|
newVtableSlots.add(OverriddenFunctionDescriptor(overridingMethod, superMethod.descriptor))
|
||||||
// Overriding method is defined in the current class and is not inherited - take it as is.
|
|
||||||
newVtableSlots.add(OverriddenFunctionDescriptor(overridingMethod, overridingMethod))
|
newVtableSlots.add(OverriddenFunctionDescriptor(overridingMethod, overridingMethod))
|
||||||
OverriddenFunctionDescriptor(overridingMethod, superMethod.overriddenDescriptor)
|
OverriddenFunctionDescriptor(overridingMethod, superMethod.overriddenDescriptor)
|
||||||
}
|
}
|
||||||
@@ -94,15 +87,13 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con
|
|||||||
}
|
}
|
||||||
println()
|
println()
|
||||||
|
|
||||||
// TODO: why put all pairs <descriptor, overriddenDescriptor>?
|
|
||||||
val zzz = inheritedVtableSlots.map { it.descriptor to it.bridgeDirections }.toSet()
|
val zzz = inheritedVtableSlots.map { it.descriptor to it.bridgeDirections }.toSet()
|
||||||
|
|
||||||
methods// Find newly defined methods.
|
methods.mapTo(newVtableSlots) { OverriddenFunctionDescriptor(it, it) }
|
||||||
// TODO: Select target because method might be taken from default implementation of interface.
|
|
||||||
.mapTo(newVtableSlots) { OverriddenFunctionDescriptor(it, it) }
|
|
||||||
|
|
||||||
val filteredNewVtableSlots = newVtableSlots
|
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 }
|
.distinctBy { it.descriptor to it.bridgeDirections }
|
||||||
.filter { it.descriptor.isOverridable }
|
.filter { it.descriptor.isOverridable }
|
||||||
println("VTABLE_ENTRIES new vtable:")
|
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.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
internal class DirectBridgesCallsLowering(val context: Context) : BodyLoweringPass {
|
internal class DirectBridgesCallsLowering(val context: Context) : BodyLoweringPass {
|
||||||
@@ -33,11 +32,14 @@ internal class DirectBridgesCallsLowering(val context: Context) : BodyLoweringPa
|
|||||||
}
|
}
|
||||||
|
|
||||||
val target = descriptor.target
|
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
|
return expression
|
||||||
|
|
||||||
|
val toCall = if (needBridge) target else context.specialDescriptorsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(descriptor, target))
|
||||||
|
|
||||||
return IrCallImpl(expression.startOffset, expression.endOffset,
|
return IrCallImpl(expression.startOffset, expression.endOffset,
|
||||||
target, remapTypeArguments(expression, target)).apply {
|
toCall, remapTypeArguments(expression, toCall)).apply {
|
||||||
dispatchReceiver = expression.dispatchReceiver
|
dispatchReceiver = expression.dispatchReceiver
|
||||||
extensionReceiver = expression.extensionReceiver
|
extensionReceiver = expression.extensionReceiver
|
||||||
mapValueParameters { expression.getValueArgument(it)!! }
|
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 {
|
internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
val functions = mutableSetOf<FunctionDescriptor?>()
|
val functions = mutableSetOf<FunctionDescriptor?>()
|
||||||
@@ -78,7 +147,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
|||||||
it?.let { function ->
|
it?.let { function ->
|
||||||
function.allOverriddenDescriptors
|
function.allOverriddenDescriptors
|
||||||
.map { OverriddenFunctionDescriptor(function, it) }
|
.map { OverriddenFunctionDescriptor(function, it) }
|
||||||
.filter { it.needBridge }
|
.filter { !it.bridgeDirections.allNotNeeded() }
|
||||||
.filter { it.canBeCalledVirtually }
|
.filter { it.canBeCalledVirtually }
|
||||||
.distinctBy { it.bridgeDirections }
|
.distinctBy { it.bridgeDirections }
|
||||||
.forEach { buildBridge(it, irClass)
|
.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) {
|
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
|
||||||
|
|
||||||
println("BUILD_BRIDGE fun: ${descriptor.descriptor}")
|
println("BUILD_BRIDGE fun: ${descriptor.descriptor}")
|
||||||
|
|||||||
Reference in New Issue
Block a user