IrConstructorCall support in JVM_IR, JS_IR, and FIR2IR

This commit is contained in:
Dmitry Petrov
2019-03-26 17:25:00 +03:00
parent 82128800c5
commit b78d1bb2b9
287 changed files with 9008 additions and 8128 deletions
@@ -184,6 +184,11 @@ class ClosureAnnotator(declaration: IrDeclaration) {
processMemberAccess(expression.symbol.owner)
}
override fun visitConstructorCall(expression: IrConstructorCall) {
expression.acceptChildrenVoid(this)
processMemberAccess(expression.symbol.owner)
}
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) {
expression.acceptChildrenVoid(this)
processMemberAccess(expression.symbol.owner)
@@ -135,19 +135,17 @@ val innerClassConstructorCallsPhase = makeIrFilePhase(
class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLoweringPass {
override fun lower(irBody: IrBody) {
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
expression.transformChildrenVoid(this)
val dispatchReceiver = expression.dispatchReceiver ?: return expression
val callee = expression.symbol as? IrConstructorSymbol ?: return expression
val parent = callee.owner.parent as? IrClass ?: return expression
val callee = expression.symbol
val parent = callee.owner.parentAsClass
if (!parent.isInner) return expression
val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(callee.owner)
val newCall = IrCallImpl(
expression.startOffset, expression.endOffset, expression.type, newCallee.symbol, newCallee.descriptor,
0, // TODO type arguments map
expression.origin
val newCall = IrConstructorCallImpl.fromSymbolOwner(
expression.startOffset, expression.endOffset, expression.type, newCallee.symbol, expression.origin
)
newCall.putValueArgument(0, dispatchReceiver)
@@ -163,7 +161,7 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val dispatchReceiver = expression.dispatchReceiver ?: return expression
val classConstructor = expression.symbol.owner
if (!(classConstructor.parent as IrClass).isInner) return expression
if (!classConstructor.parentAsClass.isInner) return expression
val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(classConstructor)
val newCall = IrDelegatingConstructorCallImpl(
@@ -289,7 +289,16 @@ class LocalDeclarationsLowering(
expression.transformChildrenVoid(this)
val oldCallee = expression.symbol.owner
val newCallee = oldCallee.transformed ?: return expression
val newCallee = (oldCallee.transformed ?: return expression) as IrSimpleFunction
return createNewCall(expression, newCallee).fillArguments2(expression, newCallee)
}
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
expression.transformChildrenVoid(this)
val oldCallee = expression.symbol.owner
val newCallee = (oldCallee.transformed ?: return expression) as IrConstructor
return createNewCall(expression, newCallee).fillArguments2(expression, newCallee)
}
@@ -470,6 +479,16 @@ class LocalDeclarationsLowering(
it.copyTypeArgumentsFrom(oldCall)
}
private fun createNewCall(oldCall: IrConstructorCall, newCallee: IrConstructor) =
IrConstructorCallImpl.fromSymbolOwner(
oldCall.startOffset, oldCall.endOffset,
newCallee.returnType,
newCallee.symbol,
oldCall.origin
).also {
it.copyTypeArgumentsFrom(oldCall)
}
private fun transformDeclarations() {
localFunctions.values.forEach {
createLiftedDeclaration(it)
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
@@ -168,7 +169,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(
kotlinType = null
classifier = symbolRemapper.getReferencedClassifier(type.classifier)
arguments = remapTypeArguments(type.arguments)
annotations = type.annotations.map { it.transform(copier, null) as IrCall }
annotations = type.annotations.map { it.transform(copier, null) as IrConstructorCall }
}
}
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.util.getAnnotation
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.name.FqName
@@ -22,7 +23,7 @@ object JsAnnotations {
}
@Suppress("UNCHECKED_CAST")
private fun IrCall.getSingleConstStringArgument() =
private fun IrConstructorCall.getSingleConstStringArgument() =
(getValueArgument(0) as IrConst<String>).value
fun IrAnnotationContainer.getJsModule(): String? =
@@ -146,7 +146,7 @@ class AnnotationCodegen(
visitor.visitEnd()
}
private fun genAnnotation(annotation: IrCall): String? {
private fun genAnnotation(annotation: IrConstructorCall): String? {
val annotationClass = annotation.annotationClass
val rp = getRetentionPolicy(annotationClass)
if (rp == RetentionPolicy.SOURCE && !typeMapper.classBuilderMode.generateSourceRetentionAnnotations) {
@@ -164,7 +164,7 @@ class AnnotationCodegen(
return asmTypeDescriptor
}
private fun genAnnotationArguments(annotation: IrCall, annotationVisitor: AnnotationVisitor) {
private fun genAnnotationArguments(annotation: IrConstructorCall, annotationVisitor: AnnotationVisitor) {
val annotationClass = annotation.annotationClass
for (param in annotation.symbol.owner.valueParameters) {
val value = annotation.getValueArgument(param.index)
@@ -200,10 +200,10 @@ class AnnotationCodegen(
when (value) {
is IrConst<*> -> annotationVisitor.visit(name, value.value)
is IrCall -> {
is IrConstructorCall -> {
val callee = value.symbol.owner
when {
callee is IrConstructor && callee.parentAsClass.isAnnotationClass -> {
callee.parentAsClass.isAnnotationClass -> {
val internalAnnName = typeMapper.mapType(callee.returnType.toKotlinType()).descriptor
val visitor = annotationVisitor.visitAnnotation(name, internalAnnName)
genAnnotationArguments(value, visitor)
@@ -268,10 +268,10 @@ class AnnotationCodegen(
}
/* Temporary? */
fun IrCall.applicableTargetSet() =
fun IrConstructorCall.applicableTargetSet() =
annotationClass.applicableTargetSet() ?: KotlinTarget.DEFAULT_TARGET_SET
val IrCall.annotationClass get() = symbol.owner.parentAsClass
val IrConstructorCall.annotationClass get() = symbol.owner.parentAsClass
}
}
@@ -294,7 +294,7 @@ private fun IrClass.getAnnotationRetention(): KotlinRetention? {
}
// To be generalized to IrMemberAccessExpression as soon as properties get symbols.
private fun IrCall.getValueArgument(name: Name): IrExpression? {
private fun IrConstructorCall.getValueArgument(name: Name): IrExpression? {
val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null
return getValueArgument(index)
}
@@ -308,7 +308,7 @@ private fun IrClass.applicableTargetSet(): Set<KotlinTarget>? {
return loadAnnotationTargets(targetEntry)
}
private fun loadAnnotationTargets(targetEntry: IrCall): Set<KotlinTarget>? {
private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTarget>? {
val valueArgument = targetEntry.getValueArgument(TARGET_ALLOWED_TARGETS)
as? IrVararg ?: return null
return valueArgument.elements.filterIsInstance<IrGetEnumValue>().mapNotNull {
@@ -268,6 +268,9 @@ class ExpressionCodegen(
override fun visitCall(expression: IrCall, data: BlockInfo): PromisedValue {
expression.markLineNumber(startOffset = true)
if (expression.descriptor is ConstructorDescriptor) {
throw AssertionError("IrCall with ConstructorDescriptor: ${expression.javaClass.simpleName}")
}
return generateCall(expression, expression.superQualifier, data)
}
@@ -318,7 +321,8 @@ class ExpressionCodegen(
receiver?.apply {
callGenerator.genValueAndPut(
null, this,
if (isSuperCall) receiver.asmType else callable.dispatchReceiverType!!,
if (isSuperCall) receiver.asmType else callable.dispatchReceiverType
?: throw AssertionError("No dispatch receiver type: ${expression.render()}"),
-1, this@ExpressionCodegen, data
)
}
@@ -1045,8 +1049,7 @@ class ExpressionCodegen(
private fun resolveToCallable(irCall: IrMemberAccessExpression, isSuper: Boolean): Callable {
var descriptor = irCall.descriptor
if (descriptor is TypeAliasConstructorDescriptor) {
//TODO where is best to unwrap?
descriptor = descriptor.underlyingConstructorDescriptor
throw AssertionError("TypeAliasConstructorDescriptor should be unwrapped in psi2ir: $descriptor")
}
if (descriptor is PropertyDescriptor) {
descriptor = descriptor.getter!!
@@ -168,14 +168,11 @@ class JvmSharedVariablesManager(
val provider = getProvider(valueType)
val refType = provider.getRefType(valueType)
val refConstructor = provider.refConstructor
val typeArgumentsCount = refConstructor.parentAsClass.typeParameters.count()
val refConstructorCall = IrCallImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset,
val refConstructorCall = IrConstructorCallImpl.fromSymbolOwner(
refType,
refConstructor.symbol, refConstructor.descriptor,
typeArgumentsCount = typeArgumentsCount,
origin = SHARED_VARIABLE_CONSTRUCTOR_CALL_ORIGIN
refConstructor.symbol,
SHARED_VARIABLE_CONSTRUCTOR_CALL_ORIGIN
).apply {
List(refConstructor.parentAsClass.typeParameters.size) { i ->
putTypeArgument(i, valueType)
@@ -24,11 +24,11 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrEnumEntryImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
import org.jetbrains.kotlin.ir.expressions.IrVararg
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrEnumEntrySymbolImpl
@@ -142,7 +142,7 @@ private class AdditionalClassAnnotationLowering(private val context: JvmBackendC
}
irClass.annotations.add(
IrCallImpl(
IrConstructorCallImpl.fromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, documentedConstructor.returnType, documentedConstructor.symbol
)
)
@@ -160,7 +160,7 @@ private class AdditionalClassAnnotationLowering(private val context: JvmBackendC
val javaRetentionPolicy = annotationRetentionMap[kotlinRetentionPolicy] ?: rpRuntime
irClass.annotations.add(
IrCallImpl(
IrConstructorCallImpl.fromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, retentionConstructor.returnType, retentionConstructor.symbol
).apply {
putValueArgument(
@@ -228,7 +228,7 @@ private class AdditionalClassAnnotationLowering(private val context: JvmBackendC
}
irClass.annotations.add(
IrCallImpl(
IrConstructorCallImpl.fromSymbolOwner(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol
).apply {
putValueArgument(0, vararg)
@@ -239,7 +239,7 @@ private class AdditionalClassAnnotationLowering(private val context: JvmBackendC
}
// To be generalized to IrMemberAccessExpression as soon as properties get symbols.
private fun IrCall.getValueArgument(name: Name): IrExpression? {
private fun IrConstructorCall.getValueArgument(name: Name): IrExpression? {
val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null
return getValueArgument(index)
}
@@ -253,7 +253,7 @@ private fun IrClass.applicableTargetSet(): Set<KotlinTarget>? {
return loadAnnotationTargets(targetEntry)
}
private fun loadAnnotationTargets(targetEntry: IrCall): Set<KotlinTarget>? {
private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTarget>? {
val valueArgument = targetEntry.getValueArgument(TARGET_ALLOWED_TARGETS)
as? IrVararg ?: return null
return valueArgument.elements.filterIsInstance<IrGetEnumValue>().mapNotNull {
@@ -399,7 +399,7 @@ private class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringP
private inner class InEnumEntryInitializer(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructor) =
IrCallImpl(
IrConstructorCallImpl.fromSymbolDescriptor(
startOffset,
endOffset,
loweredConstructor.symbol.owner.parentAsClass.defaultType,
@@ -260,7 +260,14 @@ private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElem
accessorSymbol as IrConstructorSymbol, accessorSymbol.descriptor,
oldExpression.typeArgumentsCount
)
else -> error("Need IrCall or IrDelegatingConstructor call, got $oldExpression")
is IrConstructorCall ->
IrConstructorCallImpl.fromSymbolDescriptor(
oldExpression.startOffset, oldExpression.endOffset,
oldExpression.type,
accessorSymbol as IrConstructorSymbol
)
else ->
error("Unexpected IrFunctionAccessExpression: $oldExpression")
}
newExpression.copyTypeArgumentsFrom(oldExpression)
val receiverAndArgs = oldExpression.receiverAndArgs()
@@ -246,10 +246,11 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
): IrExpression =
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
val irType = constructorDescriptor.returnType.toIrType()
IrConstructorCallImpl.fromSymbolDescriptor(
IrConstructorCallImpl.fromSubstitutedDescriptor(
startOffset, endOffset,
irType,
context.symbolTable.referenceConstructor(constructorDescriptor.original),
constructorDescriptor,
origin
).run {
putTypeArguments(call.typeArguments) { it.toIrType() }
@@ -235,13 +235,17 @@ fun IrBuilderWithScope.irCall(
}
}
fun IrBuilderWithScope.irCallConstructor(callee: IrConstructorSymbol, typeArguments: List<IrType>): IrCall =
TODO("IrConstructorCall")
// IrCallImpl(startOffset, endOffset, callee.owner.returnType, callee, callee.descriptor, typeArguments.size, callee.owner.valueParameters.size).apply {
// typeArguments.forEachIndexed { index, irType ->
// this.putTypeArgument(index, irType)
// }
// }
fun IrBuilderWithScope.irCallConstructor(callee: IrConstructorSymbol, typeArguments: List<IrType>): IrConstructorCall =
IrConstructorCallImpl.fromSymbolOwner(
startOffset,
endOffset,
callee.owner.returnType,
callee
).apply {
typeArguments.forEachIndexed { index, irType ->
this.putTypeArgument(index, irType)
}
}
fun IrBuilderWithScope.irCall(callee: IrSimpleFunctionSymbol, type: IrType): IrCall =
IrCallImpl(startOffset, endOffset, type, callee, callee.descriptor)
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
class IrConstructorCallImpl(
@@ -31,14 +32,14 @@ class IrConstructorCallImpl(
visitor.visitConstructorCall(this, data)
companion object {
fun fromSymbolDescriptor(
fun fromSubstitutedDescriptor(
startOffset: Int,
endOffset: Int,
type: IrType,
constructorSymbol: IrConstructorSymbol,
constructorDescriptor: ClassConstructorDescriptor,
origin: IrStatementOrigin? = null
): IrConstructorCallImpl {
val constructorDescriptor = constructorSymbol.descriptor
val classTypeParametersCount = constructorDescriptor.constructedClass.original.declaredTypeParameters.size
val totalTypeParametersCount = constructorDescriptor.typeParameters.size
val valueParametersCount = constructorDescriptor.valueParameters.size
@@ -56,25 +57,46 @@ class IrConstructorCallImpl(
}
fun fromSymbolDescriptor(
startOffset: Int,
endOffset: Int,
type: IrType,
constructorSymbol: IrConstructorSymbol,
origin: IrStatementOrigin? = null
): IrConstructorCallImpl =
fromSubstitutedDescriptor(startOffset, endOffset, type, constructorSymbol, constructorSymbol.descriptor, origin)
fun fromSymbolOwner(
startOffset: Int,
endOffset: Int,
type: IrType,
constructorSymbol: IrConstructorSymbol,
origin: IrStatementOrigin? = null
): IrConstructorCallImpl {
val constructorDescriptor = constructorSymbol.descriptor
val classTypeParametersCount = constructorDescriptor.constructedClass.original.declaredTypeParameters.size
val totalTypeParametersCount = constructorDescriptor.typeParameters.size
val valueParametersCount = constructorDescriptor.valueParameters.size
val constructor = constructorSymbol.owner
val constructedClass = constructor.parentAsClass
val classTypeParametersCount = constructedClass.typeParameters.size
val constructorTypeParametersCount = constructor.typeParameters.size
val totalTypeParametersCount = classTypeParametersCount + constructorTypeParametersCount
val valueParametersCount = constructor.valueParameters.size
return IrConstructorCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
startOffset, endOffset,
type,
constructorSymbol, constructorDescriptor,
constructorSymbol,
constructorSymbol.descriptor,
totalTypeParametersCount,
totalTypeParametersCount - classTypeParametersCount,
constructorTypeParametersCount,
valueParametersCount,
origin
)
}
fun fromSymbolOwner(
type: IrType,
constructorSymbol: IrConstructorSymbol,
origin: IrStatementOrigin? = null
) =
fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, constructorSymbol, origin)
}
}
@@ -44,7 +44,7 @@ class IrSimpleTypeBuilder {
var classifier: IrClassifierSymbol? = null
var hasQuestionMark = false
var arguments: List<IrTypeArgument> = emptyList()
var annotations: List<IrCall> = emptyList()
var annotations: List<IrConstructorCall> = emptyList()
var variance = Variance.INVARIANT
}