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 fieldName = realField.name.asString()
|
||||||
val isStatic = expression.receiver == null
|
val isStatic = expression.receiver == null
|
||||||
expression.markLineNumber(startOffset = true)
|
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)
|
receiver.accept(this, data).materializeAt(ownerType, receiver.type)
|
||||||
ownerType.internalName
|
}
|
||||||
} ?: typeMapper.mapClass(callee.parentAsClass).internalName
|
|
||||||
return if (expression is IrSetField) {
|
return if (expression is IrSetField) {
|
||||||
val value = expression.value.accept(this, data)
|
val value = expression.value.accept(this, data)
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,18 @@ val PropertyDescriptor.unwrappedGetMethod: FunctionDescriptor?
|
|||||||
val PropertyDescriptor.unwrappedSetMethod: FunctionDescriptor?
|
val PropertyDescriptor.unwrappedSetMethod: FunctionDescriptor?
|
||||||
get() = if (this is SyntheticPropertyDescriptor) this.setMethod else setter
|
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?.pureStartOffsetOrUndefined get() = this?.psiOrParent?.startOffsetSkippingComments ?: UNDEFINED_OFFSET
|
||||||
val KtPureElement?.pureEndOffsetOrUndefined get() = this?.psiOrParent?.endOffset ?: 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.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
||||||
|
import org.jetbrains.kotlin.psi2ir.resolveFakeOverride
|
||||||
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
|
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
|
||||||
import org.jetbrains.kotlin.psi2ir.unwrappedSetMethod
|
import org.jetbrains.kotlin.psi2ir.unwrappedSetMethod
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -309,7 +310,6 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
origin: IrStatementOrigin?,
|
origin: IrStatementOrigin?,
|
||||||
superQualifier: ClassDescriptor?
|
superQualifier: ClassDescriptor?
|
||||||
): PropertyLValueBase {
|
): PropertyLValueBase {
|
||||||
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
|
|
||||||
|
|
||||||
val unwrappedPropertyDescriptor = descriptor.unwrapPropertyDescriptor()
|
val unwrappedPropertyDescriptor = descriptor.unwrapPropertyDescriptor()
|
||||||
val getterDescriptor = unwrappedPropertyDescriptor.unwrappedGetMethod
|
val getterDescriptor = unwrappedPropertyDescriptor.unwrappedGetMethod
|
||||||
@@ -320,6 +320,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
|
|
||||||
val propertyIrType = descriptor.type.toIrType()
|
val propertyIrType = descriptor.type.toIrType()
|
||||||
return if (getterSymbol != null || setterSymbol != null) {
|
return if (getterSymbol != null || setterSymbol != null) {
|
||||||
|
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||||
val typeArgumentsList =
|
val typeArgumentsList =
|
||||||
typeArgumentsMap?.let { typeArguments ->
|
typeArgumentsMap?.let { typeArguments ->
|
||||||
descriptor.original.typeParameters.map { typeArguments[it]!!.toIrType() }
|
descriptor.original.typeParameters.map { typeArguments[it]!!.toIrType() }
|
||||||
@@ -341,17 +342,20 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
propertyReceiver,
|
propertyReceiver,
|
||||||
superQualifierSymbol
|
superQualifierSymbol
|
||||||
)
|
)
|
||||||
} else
|
} else {
|
||||||
|
val superQualifierSymbol = (superQualifier
|
||||||
|
?: unwrappedPropertyDescriptor.containingDeclaration as? ClassDescriptor)?.let { context.symbolTable.referenceClass(it) }
|
||||||
FieldPropertyLValue(
|
FieldPropertyLValue(
|
||||||
context,
|
context,
|
||||||
scope,
|
scope,
|
||||||
ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin,
|
ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin,
|
||||||
context.symbolTable.referenceField(unwrappedPropertyDescriptor.original),
|
context.symbolTable.referenceField(unwrappedPropertyDescriptor.resolveFakeOverride().original),
|
||||||
unwrappedPropertyDescriptor,
|
unwrappedPropertyDescriptor,
|
||||||
propertyIrType,
|
propertyIrType,
|
||||||
propertyReceiver,
|
propertyReceiver,
|
||||||
superQualifierSymbol
|
superQualifierSymbol
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateArrayAccessAssignmentReceiver(
|
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.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
||||||
|
import org.jetbrains.kotlin.psi2ir.resolveFakeOverride
|
||||||
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
|
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||||
@@ -174,11 +175,13 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
call: CallBuilder
|
call: CallBuilder
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
val getMethodDescriptor = descriptor.unwrappedGetMethod
|
val getMethodDescriptor = descriptor.unwrappedGetMethod
|
||||||
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
|
||||||
val irType = descriptor.type.toIrType()
|
val irType = descriptor.type.toIrType()
|
||||||
|
|
||||||
return if (getMethodDescriptor == null) {
|
return if (getMethodDescriptor == null) {
|
||||||
call.callReceiver.call { dispatchReceiverValue, _ ->
|
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)
|
val fieldSymbol = context.symbolTable.referenceField(descriptor.resolveFakeOverride().original)
|
||||||
IrGetFieldImpl(
|
IrGetFieldImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
@@ -190,6 +193,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
).also { context.callToSubstitutedDescriptorMap[it] = descriptor }
|
).also { context.callToSubstitutedDescriptorMap[it] = descriptor }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||||
call.callReceiver.adjustForCallee(getMethodDescriptor).call { dispatchReceiverValue, extensionReceiverValue ->
|
call.callReceiver.adjustForCallee(getMethodDescriptor).call { dispatchReceiverValue, extensionReceiverValue ->
|
||||||
if (descriptor.isDynamic()) {
|
if (descriptor.isDynamic()) {
|
||||||
val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, descriptor)
|
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) =
|
fun CallGenerator.generateCall(irExpression: IrExpression, call: CallBuilder, origin: IrStatementOrigin? = null) =
|
||||||
generateCall(irExpression.startOffset, irExpression.endOffset, call, origin)
|
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() {
|
fun test() {
|
||||||
Parent.a
|
Parent.a
|
||||||
|
Parent.a = 11
|
||||||
Parent.b
|
Parent.b
|
||||||
|
Parent.b = 22
|
||||||
Parent.foo()
|
Parent.foo()
|
||||||
Parent.baz()
|
Parent.baz()
|
||||||
|
|
||||||
Child.a
|
Child.a
|
||||||
|
Child.a = 33
|
||||||
Child.b
|
Child.b
|
||||||
|
Child.b = 44
|
||||||
Child.c
|
Child.c
|
||||||
|
Child.c = 55
|
||||||
Child.foo()
|
Child.foo()
|
||||||
Child.bar()
|
Child.bar()
|
||||||
Child.baz()
|
Child.baz()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1 GETSTATIC Parent.a : I
|
// 1 GETSTATIC Parent.a : I
|
||||||
|
// 1 PUTSTATIC Parent.a : I
|
||||||
// 1 GETSTATIC Parent.b : I
|
// 1 GETSTATIC Parent.b : I
|
||||||
|
// 1 PUTSTATIC Parent.b : I
|
||||||
// 1 INVOKESTATIC Parent.foo()
|
// 1 INVOKESTATIC Parent.foo()
|
||||||
// 1 INVOKESTATIC Parent.baz()
|
// 1 INVOKESTATIC Parent.baz()
|
||||||
// 1 GETSTATIC Child.a : I
|
// 1 GETSTATIC Child.a : I
|
||||||
|
// 1 PUTSTATIC Child.a : I
|
||||||
// 1 GETSTATIC Child.b : I
|
// 1 GETSTATIC Child.b : I
|
||||||
|
// 1 PUTSTATIC Child.b : I
|
||||||
// 1 GETSTATIC Child.c : I
|
// 1 GETSTATIC Child.c : I
|
||||||
|
// 1 PUTSTATIC Child.c : I
|
||||||
// 1 INVOKESTATIC Child.foo()
|
// 1 INVOKESTATIC Child.foo()
|
||||||
// 1 INVOKESTATIC Child.bar()
|
// 1 INVOKESTATIC Child.bar()
|
||||||
// 1 INVOKESTATIC Child.baz()
|
// 1 INVOKESTATIC Child.baz()
|
||||||
|
|||||||
Reference in New Issue
Block a user