SyntheticAccessorLowering refactoring

This commit is contained in:
Mikhael Bogdanov
2017-11-22 13:26:08 +01:00
parent 7da847e943
commit 5cbfdf6024
@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import kotlin.properties.Delegates
interface StubContext { interface StubContext {
val irClassContext: IrClassContext val irClassContext: IrClassContext
@@ -117,11 +116,11 @@ class SyntheticAccessorLowering(val state: GenerationState) : FileLoweringPass,
override fun visitClass(declaration: IrClass, data: IrClassContext?): IrStatement { override fun visitClass(declaration: IrClass, data: IrClassContext?): IrStatement {
val classContext = (declaration.descriptor.codegenContext as StubContext).irClassContext val classContext = (declaration.descriptor.codegenContext as StubContext).irClassContext
return super.visitClass(declaration, classContext).apply { return super.visitClass(declaration, classContext).apply {
lower(this as IrClass, classContext) lower(classContext)
} }
} }
fun lower(irCLass: IrClass, data: IrClassContext) { fun lower(data: IrClassContext) {
val codegenContext = data.codegenContext val codegenContext = data.codegenContext
val accessors = codegenContext.accessors val accessors = codegenContext.accessors
val allAccessors = val allAccessors =
@@ -131,70 +130,83 @@ class SyntheticAccessorLowering(val state: GenerationState) : FileLoweringPass,
listOf(if (it.isWithSyntheticGetterAccessor) it.getter else null, if (it.isWithSyntheticSetterAccessor) it.setter else null).filterNotNull() listOf(if (it.isWithSyntheticGetterAccessor) it.getter else null, if (it.isWithSyntheticSetterAccessor) it.setter else null).filterNotNull()
} }
).filterIsInstance<AccessorForCallableDescriptor<*>>() ).filterIsInstance<AccessorForCallableDescriptor<*>>()
val irClassToAddAccessor = data.irClass
allAccessors.forEach { accessor -> allAccessors.forEach { accessor ->
val accessorOwner = (accessor as FunctionDescriptor).containingDeclaration as ClassOrPackageFragmentDescriptor addAccessorToClass(accessor, irClassToAddAccessor, state.typeMapper)
val body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
val accessorDescriptor = accessor.toStatic(accessorOwner, Name.identifier(state.typeMapper.mapAsmMethod(accessor).name))
val syntheticFunction = IrFunctionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
accessorDescriptor, body
)
val calleeDescriptor = accessor.calleeDescriptor as FunctionDescriptor
val returnExpr = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, calleeDescriptor)
copyAllArgsToValueParams(returnExpr, accessorDescriptor)
body.statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor, returnExpr))
data.irClass.declarations.add(syntheticFunction)
} }
} }
override fun visitMemberAccess(expression: IrMemberAccessExpression, data: IrClassContext?): IrElement { override fun visitMemberAccess(expression: IrMemberAccessExpression, data: IrClassContext?): IrElement {
val superResult = super.visitMemberAccess(expression, data) val superResult = super.visitMemberAccess(expression, data)
val descriptor = expression.descriptor return createSyntheticAccessorCallForFunction(superResult, expression, data?.codegenContext, state.typeMapper)
if (descriptor is FunctionDescriptor) { }
val directAccessor = data!!.codegenContext.accessibleDescriptor(JvmCodegenUtil.getDirectMember(descriptor), (expression as? IrCall)?.superQualifier)
val accessor = actualAccessor(descriptor, directAccessor)
if (accessor is AccessorForCallableDescriptor<*> && descriptor !is AccessorForCallableDescriptor<*>) { companion object {
val accessorOwner = accessor.containingDeclaration as ClassOrPackageFragmentDescriptor fun createSyntheticAccessorCallForFunction(superResult: IrElement, expression: IrMemberAccessExpression, codegenContext: CodegenContext<*>?, typeMapper: KotlinTypeMapper): IrElement {
val staticAccessor = descriptor.toStatic(accessorOwner, Name.identifier(state.typeMapper.mapAsmMethod(accessor as FunctionDescriptor).name)) //TODO change call
val call = IrCallImpl(expression.startOffset, expression.endOffset, staticAccessor, emptyMap(), expression.origin/*TODO super*/) val descriptor = expression.descriptor
//copyAllArgsToValueParams(call, expression) if (descriptor is FunctionDescriptor) {
expression.receiverAndArgs().forEachIndexed { i, irExpression -> val directAccessor = codegenContext!!.accessibleDescriptor(JvmCodegenUtil.getDirectMember(descriptor), (expression as? IrCall)?.superQualifier)
call.putValueArgument(i, irExpression) val accessor = Companion.actualAccessor(descriptor, directAccessor)
if (accessor is AccessorForCallableDescriptor<*> && descriptor !is AccessorForCallableDescriptor<*>) {
val accessorOwner = accessor.containingDeclaration as ClassOrPackageFragmentDescriptor
val staticAccessor = descriptor.toStatic(accessorOwner, Name.identifier(typeMapper.mapAsmMethod(accessor as FunctionDescriptor).name)) //TODO change call
val call = IrCallImpl(expression.startOffset, expression.endOffset, staticAccessor, emptyMap(), expression.origin/*TODO super*/)
//copyAllArgsToValueParams(call, expression)
expression.receiverAndArgs().forEachIndexed { i, irExpression ->
call.putValueArgument(i, irExpression)
}
return call
} }
return call
} }
return superResult
} }
return superResult
}
private fun actualAccessor(descriptor: FunctionDescriptor, calculatedAccessor: CallableMemberDescriptor): CallableMemberDescriptor { fun addAccessorToClass(accessor: AccessorForCallableDescriptor<*>, irClassToAddAccessor: IrClass, typeMapper: KotlinTypeMapper) {
if (calculatedAccessor is AccessorForPropertyDescriptor) { val accessorOwner = (accessor as FunctionDescriptor).containingDeclaration as ClassOrPackageFragmentDescriptor
val isGetter = descriptor is PropertyGetterDescriptor val body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
val propertyAccessor = if (isGetter) calculatedAccessor.getter!! else calculatedAccessor.setter!! val accessorDescriptor = accessor.toStatic(accessorOwner, Name.identifier(typeMapper.mapAsmMethod(accessor).name))
if (isGetter && calculatedAccessor.isWithSyntheticGetterAccessor || !isGetter && calculatedAccessor.isWithSyntheticSetterAccessor) { val syntheticFunction = IrFunctionImpl(
return propertyAccessor UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
accessorDescriptor, body
)
val calleeDescriptor = accessor.calleeDescriptor as FunctionDescriptor
val returnExpr = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, calleeDescriptor)
Companion.copyAllArgsToValueParams(returnExpr, accessorDescriptor)
body.statements.add(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor, returnExpr))
irClassToAddAccessor.declarations.add(syntheticFunction)
}
private fun actualAccessor(descriptor: FunctionDescriptor, calculatedAccessor: CallableMemberDescriptor): CallableMemberDescriptor {
if (calculatedAccessor is AccessorForPropertyDescriptor) {
val isGetter = descriptor is PropertyGetterDescriptor
val propertyAccessor = if (isGetter) calculatedAccessor.getter!! else calculatedAccessor.setter!!
if (isGetter && calculatedAccessor.isWithSyntheticGetterAccessor || !isGetter && calculatedAccessor.isWithSyntheticSetterAccessor) {
return propertyAccessor
}
return descriptor
} }
return descriptor return calculatedAccessor
}
return calculatedAccessor
}
private fun copyAllArgsToValueParams(call: IrCallImpl, fromDescriptor: CallableMemberDescriptor) {
var offset = 0
val newDescriptor = call.descriptor
newDescriptor.dispatchReceiverParameter?.let {
call.dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fromDescriptor.valueParameters[offset++])
} }
newDescriptor.extensionReceiverParameter?.let { private fun copyAllArgsToValueParams(call: IrCallImpl, fromDescriptor: CallableMemberDescriptor) {
call.extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fromDescriptor.valueParameters[offset++]) var offset = 0
} val newDescriptor = call.descriptor
newDescriptor.dispatchReceiverParameter?.let {
call.dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fromDescriptor.valueParameters[offset++])
}
call.descriptor.valueParameters.forEachIndexed { i, _ -> newDescriptor.extensionReceiverParameter?.let {
call.putValueArgument(i, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fromDescriptor.valueParameters[i + offset])) call.extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fromDescriptor.valueParameters[offset++])
}
call.descriptor.valueParameters.forEachIndexed { i, _ ->
call.putValueArgument(i, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fromDescriptor.valueParameters[i + offset]))
}
} }
} }
} }