IR: use super qualifier in Java field accesses
This commit is contained in:
+16
-4
@@ -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
|
||||
|
||||
|
||||
+7
-3
@@ -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
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user