IR: use super qualifier in Java field accesses

This commit is contained in:
Georgy Bronnikov
2020-06-13 00:04:33 +03:00
parent 36f22dafc5
commit 1bb3f60bad
5 changed files with 50 additions and 19 deletions
@@ -540,11 +540,23 @@ class ExpressionCodegen(
val fieldName = realField.name.asString()
val isStatic = expression.receiver == null
expression.markLineNumber(startOffset = true)
val ownerName = expression.receiver?.let { receiver ->
val ownerType = typeMapper.mapTypeAsDeclaration(receiver.type)
val ownerType = when {
expression.superQualifierSymbol != null -> {
typeMapper.mapClass(expression.superQualifierSymbol!!.owner)
}
expression.receiver != null -> {
typeMapper.mapTypeAsDeclaration(expression.receiver!!.type)
}
else -> typeMapper.mapClass(callee.parentAsClass)
}
val ownerName = ownerType.internalName
expression.receiver?.let { receiver ->
receiver.accept(this, data).materializeAt(ownerType, receiver.type)
ownerType.internalName
} ?: typeMapper.mapClass(callee.parentAsClass).internalName
}
return if (expression is IrSetField) {
val value = expression.value.accept(this, data)
@@ -77,6 +77,18 @@ val PropertyDescriptor.unwrappedGetMethod: FunctionDescriptor?
val PropertyDescriptor.unwrappedSetMethod: FunctionDescriptor?
get() = if (this is SyntheticPropertyDescriptor) this.setMethod else setter
// Only works for descriptors of Java fields.
internal fun PropertyDescriptor.resolveFakeOverride(): PropertyDescriptor {
assert(getter == null)
// Fields can only be inherited from objects, so there will be at most one overridden descriptor at each step.
var current = this
while (current.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
current = current.overriddenDescriptors.singleOrNull()
?: error("Descriptor of Java field $current should have exactly one overridden descriptor, have ${current.overriddenDescriptors}")
}
return current
}
val KtPureElement?.pureStartOffsetOrUndefined get() = this?.psiOrParent?.startOffsetSkippingComments ?: UNDEFINED_OFFSET
val KtPureElement?.pureEndOffsetOrUndefined get() = this?.psiOrParent?.endOffset ?: UNDEFINED_OFFSET
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.psi2ir.intermediate.*
import org.jetbrains.kotlin.psi2ir.resolveFakeOverride
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
import org.jetbrains.kotlin.psi2ir.unwrappedSetMethod
import org.jetbrains.kotlin.resolve.BindingContext
@@ -309,7 +310,6 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
origin: IrStatementOrigin?,
superQualifier: ClassDescriptor?
): PropertyLValueBase {
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
val unwrappedPropertyDescriptor = descriptor.unwrapPropertyDescriptor()
val getterDescriptor = unwrappedPropertyDescriptor.unwrappedGetMethod
@@ -320,6 +320,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
val propertyIrType = descriptor.type.toIrType()
return if (getterSymbol != null || setterSymbol != null) {
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
val typeArgumentsList =
typeArgumentsMap?.let { typeArguments ->
descriptor.original.typeParameters.map { typeArguments[it]!!.toIrType() }
@@ -341,17 +342,20 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
propertyReceiver,
superQualifierSymbol
)
} else
} else {
val superQualifierSymbol = (superQualifier
?: unwrappedPropertyDescriptor.containingDeclaration as? ClassDescriptor)?.let { context.symbolTable.referenceClass(it) }
FieldPropertyLValue(
context,
scope,
ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin,
context.symbolTable.referenceField(unwrappedPropertyDescriptor.original),
context.symbolTable.referenceField(unwrappedPropertyDescriptor.resolveFakeOverride().original),
unwrappedPropertyDescriptor,
propertyIrType,
propertyReceiver,
superQualifierSymbol
)
}
}
private fun generateArrayAccessAssignmentReceiver(
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.psi2ir.intermediate.*
import org.jetbrains.kotlin.psi2ir.resolveFakeOverride
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
@@ -174,11 +175,13 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
call: CallBuilder
): IrExpression {
val getMethodDescriptor = descriptor.unwrappedGetMethod
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
val irType = descriptor.type.toIrType()
return if (getMethodDescriptor == null) {
call.callReceiver.call { dispatchReceiverValue, _ ->
val superQualifierSymbol = (call.superQualifier ?: descriptor.containingDeclaration as? ClassDescriptor)?.let {
context.symbolTable.referenceClass(it)
}
val fieldSymbol = context.symbolTable.referenceField(descriptor.resolveFakeOverride().original)
IrGetFieldImpl(
startOffset, endOffset,
@@ -190,6 +193,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
).also { context.callToSubstitutedDescriptorMap[it] = descriptor }
}
} else {
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
call.callReceiver.adjustForCallee(getMethodDescriptor).call { dispatchReceiverValue, extensionReceiverValue ->
if (descriptor.isDynamic()) {
val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, descriptor)
@@ -416,14 +420,3 @@ fun CallGenerator.generateCall(ktElement: KtElement, call: CallBuilder, origin:
fun CallGenerator.generateCall(irExpression: IrExpression, call: CallBuilder, origin: IrStatementOrigin? = null) =
generateCall(irExpression.startOffset, irExpression.endOffset, call, origin)
// Only works for descriptors of Java fields.
private fun PropertyDescriptor.resolveFakeOverride(): PropertyDescriptor {
assert(getter == null)
// Fields can only be inherited from objects, so there will be at most one overridden descriptor at each step.
var current = this
while (current.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
current = current.overriddenDescriptors.single()
}
return current
}
+10
View File
@@ -20,25 +20,35 @@ class Parent {
fun test() {
Parent.a
Parent.a = 11
Parent.b
Parent.b = 22
Parent.foo()
Parent.baz()
Child.a
Child.a = 33
Child.b
Child.b = 44
Child.c
Child.c = 55
Child.foo()
Child.bar()
Child.baz()
}
// 1 GETSTATIC Parent.a : I
// 1 PUTSTATIC Parent.a : I
// 1 GETSTATIC Parent.b : I
// 1 PUTSTATIC Parent.b : I
// 1 INVOKESTATIC Parent.foo()
// 1 INVOKESTATIC Parent.baz()
// 1 GETSTATIC Child.a : I
// 1 PUTSTATIC Child.a : I
// 1 GETSTATIC Child.b : I
// 1 PUTSTATIC Child.b : I
// 1 GETSTATIC Child.c : I
// 1 PUTSTATIC Child.c : I
// 1 INVOKESTATIC Child.foo()
// 1 INVOKESTATIC Child.bar()
// 1 INVOKESTATIC Child.baz()