IR: introduce IrConstructorCall / IrConstructorCallImpl

This commit is contained in:
Dmitry Petrov
2019-03-25 16:51:58 +03:00
parent 023306b1b3
commit 37b1c175ce
53 changed files with 457 additions and 162 deletions
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.util.referenceFunction
import org.jetbrains.kotlin.ir.util.render
@@ -34,7 +35,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
@@ -50,6 +50,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
return when (descriptor) {
is PropertyDescriptor ->
generatePropertyGetterCall(descriptor, startOffset, endOffset, call)
is ClassConstructorDescriptor ->
generateConstructorCall(descriptor, startOffset, endOffset, origin, call)
is FunctionDescriptor ->
generateFunctionCall(descriptor, startOffset, endOffset, origin, call)
else ->
@@ -143,7 +145,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
this.dispatchReceiver = dispatchReceiver?.load()
this.extensionReceiver = extensionReceiver?.load()
}
addParametersToCall(startOffset, endOffset, call, irCall, descriptor.builtIns.unitType)
addParametersToCall(startOffset, endOffset, call, irCall, context.irBuiltIns.unitType)
}
fun generateEnumConstructorSuperCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression {
@@ -156,8 +158,9 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
if (dispatchReceiver != null) throw AssertionError("Dispatch receiver should be null: $dispatchReceiver")
if (extensionReceiver != null) throw AssertionError("Extension receiver should be null: $extensionReceiver")
val constructorSymbol = context.symbolTable.referenceConstructor(constructorDescriptor.original)
val irCall = IrEnumConstructorCallImpl(startOffset, endOffset, constructorDescriptor.returnType.toIrType(), constructorSymbol)
addParametersToCall(startOffset, endOffset, call, irCall, constructorDescriptor.returnType)
val irResultType = constructorDescriptor.returnType.toIrType()
val irCall = IrEnumConstructorCallImpl(startOffset, endOffset, irResultType, constructorSymbol)
addParametersToCall(startOffset, endOffset, call, irCall, irResultType)
}
}
@@ -234,6 +237,35 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
return dispatchReceiver
}
private fun generateConstructorCall(
constructorDescriptor: ClassConstructorDescriptor,
startOffset: Int,
endOffset: Int,
origin: IrStatementOrigin?,
call: CallBuilder
): IrExpression =
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
val irType = constructorDescriptor.returnType.toIrType()
val classTypeParametersCount = constructorDescriptor.constructedClass.original.declaredTypeParameters.size
val totalTypeParametersCount = constructorDescriptor.typeParameters.size
IrConstructorCallImpl(
startOffset, endOffset,
irType,
context.symbolTable.referenceConstructor(constructorDescriptor.original),
constructorDescriptor,
typeArgumentsCount = totalTypeParametersCount,
constructorTypeArgumentsCount = totalTypeParametersCount - classTypeParametersCount,
valueArgumentsCount = constructorDescriptor.valueParameters.size,
origin = origin
).run {
putTypeArguments(call.typeArguments) { it.toIrType() }
dispatchReceiver = dispatchReceiverValue?.load()
extensionReceiver = extensionReceiverValue?.load()
addParametersToCall(startOffset, endOffset, call, this, irType)
}
}
private fun generateFunctionCall(
functionDescriptor: FunctionDescriptor,
startOffset: Int,
@@ -242,8 +274,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
call: CallBuilder
): IrExpression =
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
val returnType = functionDescriptor.returnType!!
val irType = returnType.toIrType()
val irType = functionDescriptor.returnType!!.toIrType()
if (functionDescriptor.isDynamic()) {
fun makeDynamicOperatorExpression(operator: IrDynamicOperator) =
@@ -294,21 +325,19 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
)
}
} else {
val functionSymbol = context.symbolTable.referenceFunction(functionDescriptor.original)
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
val irCall = IrCallImpl(
IrCallImpl(
startOffset, endOffset,
irType,
functionSymbol,
context.symbolTable.referenceFunction(functionDescriptor.original),
functionDescriptor,
origin,
superQualifierSymbol
).apply {
call.superQualifier?.let { context.symbolTable.referenceClass(it) }
).run {
putTypeArguments(call.typeArguments) { it.toIrType() }
this.dispatchReceiver = dispatchReceiverValue?.load()
this.extensionReceiver = extensionReceiverValue?.load()
dispatchReceiver = dispatchReceiverValue?.load()
extensionReceiver = extensionReceiverValue?.load()
addParametersToCall(startOffset, endOffset, call, this, irType)
}
addParametersToCall(startOffset, endOffset, call, irCall, returnType)
}
}
@@ -317,10 +346,10 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
endOffset: Int,
call: CallBuilder,
irCall: IrFunctionAccessExpression,
returnType: KotlinType
irResultType: IrType
): IrExpression =
if (call.isValueArgumentReorderingRequired()) {
generateCallWithArgumentReordering(irCall, startOffset, endOffset, call, returnType)
generateCallWithArgumentReordering(irCall, startOffset, endOffset, call, irResultType)
} else {
val valueArguments = call.getValueArgumentsInParameterOrder()
for ((index, valueArgument) in valueArguments.withIndex()) {
@@ -334,14 +363,14 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
startOffset: Int,
endOffset: Int,
call: CallBuilder,
resultType: KotlinType
irResultType: IrType
): IrExpression {
val resolvedCall = call.original
val valueArgumentsInEvaluationOrder = resolvedCall.valueArguments.values
val valueParameters = resolvedCall.resultingDescriptor.valueParameters
val irBlock = IrBlockImpl(startOffset, endOffset, resultType.toIrType(), IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL)
val irBlock = IrBlockImpl(startOffset, endOffset, irResultType, IrStatementOrigin.ARGUMENTS_REORDERING_FOR_CALL)
val valueArgumentsToValueParameters = HashMap<ResolvedValueArgument, ValueParameterDescriptor>()
for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) {
@@ -0,0 +1,81 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.types.IrType
interface IrConstructorCall : IrFunctionAccessExpression {
override val descriptor: ClassConstructorDescriptor
override val symbol: IrConstructorSymbol
val constructorTypeArgumentsCount: Int
class ConstructorTypeArguments(internal val irConstructorCall: IrConstructorCall) : AbstractList<IrType?>() {
override val size: Int
get() = irConstructorCall.constructorTypeArgumentsCount
override fun get(index: Int): IrType? =
if (index >= size)
throw IndexOutOfBoundsException("index: $index, size: $size")
else
irConstructorCall.getConstructorTypeArgument(index)
}
class ClassTypeArguments(internal val irConstructorCall: IrConstructorCall) : AbstractList<IrType?>() {
override val size: Int
get() = irConstructorCall.classTypeArgumentsCount
override fun get(index: Int): IrType? =
if (index >= size)
throw IndexOutOfBoundsException("index: $index, size: $size")
else
irConstructorCall.getTypeArgument(index)
}
}
fun IrConstructorCall.getConstructorTypeArgumentIndex(constructorTypeArgumentIndex: Int) =
typeArgumentsCount - constructorTypeArgumentsCount + constructorTypeArgumentIndex
fun IrConstructorCall.getConstructorTypeArgument(index: Int): IrType? =
getTypeArgument(getConstructorTypeArgumentIndex(index))
fun IrConstructorCall.putConstructorTypeArgument(index: Int, type: IrType?) {
putTypeArgument(getConstructorTypeArgumentIndex(index), type)
}
operator fun IrConstructorCall.ConstructorTypeArguments.set(index: Int, type: IrType?) {
if (index >= size) throw IndexOutOfBoundsException("index: $index, size: $size")
irConstructorCall.putConstructorTypeArgument(index, type)
}
val IrConstructorCall.classTypeArgumentsCount: Int
get() = typeArgumentsCount - constructorTypeArgumentsCount
fun IrConstructorCall.getClassTypeArgument(index: Int): IrType? =
getTypeArgument(index)
fun IrConstructorCall.putClassTypeArgument(index: Int, type: IrType?) {
putTypeArgument(index, type)
}
operator fun IrConstructorCall.ClassTypeArguments.set(index: Int, type: IrType?) {
if (index >= size) throw IndexOutOfBoundsException("index: $index, size: $size")
irConstructorCall.putClassTypeArgument(index, type)
}
fun IrConstructorCall.getConstructorTypeArguments() =
IrConstructorCall.ConstructorTypeArguments(this)
fun IrConstructorCall.getClassTypeArguments() =
IrConstructorCall.ClassTypeArguments(this)
var IrConstructorCall.outerClassReceiver: IrExpression?
get() = dispatchReceiver
set(value) {
dispatchReceiver = value
}
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.expressions.impl
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
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.visitors.IrElementVisitor
class IrConstructorCallImpl(
startOffset: Int,
endOffset: Int,
type: IrType,
override val symbol: IrConstructorSymbol,
override val descriptor: ClassConstructorDescriptor,
typeArgumentsCount: Int,
override val constructorTypeArgumentsCount: Int,
valueArgumentsCount: Int,
origin: IrStatementOrigin? = null
) :
IrCallWithIndexedArgumentsBase(startOffset, endOffset, type, typeArgumentsCount, valueArgumentsCount, origin),
IrConstructorCall {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitConstructorCall(this, data)
}
@@ -457,6 +457,23 @@ open class DeepCopyIrTreeWithSymbols(
transformValueArguments(expression)
}
override fun visitConstructorCall(expression: IrConstructorCall): IrConstructorCall {
val constructorSymbol = symbolRemapper.getReferencedConstructor(expression.symbol)
return IrConstructorCallImpl(
expression.startOffset, expression.endOffset,
expression.type.remapType(),
constructorSymbol,
constructorSymbol.descriptor,
expression.typeArgumentsCount,
expression.constructorTypeArgumentsCount,
expression.valueArgumentsCount,
mapStatementOrigin(expression.origin)
).apply {
copyRemappedTypeArgumentsFrom(expression)
transformValueArguments(expression)
}
}
private fun IrMemberAccessExpression.copyRemappedTypeArgumentsFrom(other: IrMemberAccessExpression) {
assert(typeArgumentsCount == other.typeArgumentsCount) {
"Mismatching type arguments: $typeArgumentsCount vs ${other.typeArgumentsCount} "
@@ -171,12 +171,34 @@ class DumpIrTreeVisitor(
}
}
override fun visitConstructorCall(expression: IrConstructorCall, data: String) {
expression.dumpLabeledElementWith(data) {
dumpTypeArguments(expression)
expression.outerClassReceiver?.accept(this, "\$outer")
val valueParameterNames = expression.getValueParameterNames(expression.valueArgumentsCount)
for (index in 0 until expression.valueArgumentsCount) {
expression.getValueArgument(index)?.accept(this, valueParameterNames[index])
}
}
}
private fun dumpTypeArguments(expression: IrMemberAccessExpression) {
val typeParameterNames = expression.getTypeParameterNames(expression.typeArgumentsCount)
for (index in 0 until expression.typeArgumentsCount) {
printer.println(
"<${typeParameterNames[index]}>: ${expression.renderTypeArgument(index)}"
)
printer.println("<${typeParameterNames[index]}>: ${expression.renderTypeArgument(index)}")
}
}
private fun dumpTypeArguments(expression: IrConstructorCall) {
val typeParameterNames = expression.getTypeParameterNames(expression.typeArgumentsCount)
for (index in 0 until expression.typeArgumentsCount) {
val typeParameterName = typeParameterNames[index]
val parameterLabel =
if (index < expression.classTypeArgumentsCount)
"class: $typeParameterName"
else
typeParameterName
printer.println("<$parameterLabel>: ${expression.renderTypeArgument(index)}")
}
}
@@ -220,31 +242,13 @@ class DumpIrTreeVisitor(
getPlaceholderParameterNames(expectedCount)
}
private fun IrConstructor.getFullTypeParametersList(): List<IrTypeParameter> =
getConstructedClassTypeParameters().apply { addAll(typeParameters) }
private fun IrConstructor.getConstructedClassTypeParameters(): MutableList<IrTypeParameter> {
val typeParameters = ArrayList<IrTypeParameter>()
private fun IrConstructor.getFullTypeParametersList(): List<IrTypeParameter> {
val parentClass = try {
parent as? IrClass ?: return typeParameters
} catch (e: Exception) {
return typeParameters
}
parentClass.collectClassTypeParameters(typeParameters)
return typeParameters
}
private fun IrClass.collectClassTypeParameters(typeParameters: MutableList<IrTypeParameter>) {
var currentClass = this
while (true) {
typeParameters.addAll(currentClass.typeParameters)
if (!currentClass.isInner) return
currentClass = try {
currentClass.parent as? IrClass ?: return
} catch (e: Exception) {
return
}
}
return parentClass.typeParameters + typeParameters
}
private fun IrMemberAccessExpression.renderTypeArgument(index: Int): String =
@@ -39,6 +39,9 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
fun renderSymbolReference(symbol: IrSymbol) = symbol.renderReference()
private inline fun buildTrimEnd(fn: StringBuilder.() -> Unit): String =
buildString(fn).trimEnd()
private fun IrType.render() =
"${renderTypeAnnotations(annotations)}${renderTypeInner()}"
@@ -48,7 +51,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
is IrErrorType -> "IrErrorType"
is IrSimpleType -> buildString {
is IrSimpleType -> buildTrimEnd {
append(classifier.renderClassifierFqn())
if (arguments.isNotEmpty()) {
append(
@@ -69,7 +72,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
when (this) {
is IrStarProjection -> "*"
is IrTypeProjection -> buildString {
is IrTypeProjection -> buildTrimEnd {
append(variance.label)
if (variance != Variance.INVARIANT) append(' ')
append(type.render())
@@ -100,7 +103,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
element.accept(this@RenderIrElementVisitor, null)
override fun visitVariable(declaration: IrVariable, data: Nothing?) =
buildString {
buildTrimEnd {
if (declaration.isVar) append("var ") else append("val ")
append(declaration.name.asString())
@@ -114,7 +117,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
}
override fun visitValueParameter(declaration: IrValueParameter, data: Nothing?) =
buildString {
buildTrimEnd {
append(declaration.name.asString())
append(": ")
append(declaration.type.render())
@@ -126,7 +129,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
}
override fun visitFunction(declaration: IrFunction, data: Nothing?) =
buildString {
buildTrimEnd {
append(declaration.visibility)
append(' ')
@@ -184,7 +187,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
}
override fun visitProperty(declaration: IrProperty, data: Nothing?) =
buildString {
buildTrimEnd {
append(declaration.visibility)
append(' ')
append(declaration.modality.toString().toLowerCase())
@@ -203,7 +206,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
}
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty, data: Nothing?): String =
buildString {
buildTrimEnd {
if (declaration.isVar) append("var ") else append("val ")
append(declaration.name.asString())
append(": ")
@@ -459,6 +462,9 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
private fun IrCall.renderSuperQualifier(): String =
superQualifierSymbol?.let { "superQualifier='${it.renderReference()}' " } ?: ""
override fun visitConstructorCall(expression: IrConstructorCall, data: Nothing?): String =
"CONSTRUCTOR_CALL '${expression.symbol.renderReference()}' type=${expression.type.render()} origin=${expression.origin}"
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Nothing?): String =
"DELEGATING_CONSTRUCTOR_CALL '${expression.symbol.renderReference()}'"
@@ -517,7 +523,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
"FUNCTION_REFERENCE '${expression.symbol.renderReference()}' type=${expression.type.render()} origin=${expression.origin}"
override fun visitPropertyReference(expression: IrPropertyReference, data: Nothing?): String =
buildString {
buildTrimEnd {
append("PROPERTY_REFERENCE ")
append("'${expression.symbol.renderReference()}' ")
appendNullableAttribute("field=", expression.field) { "'${it.renderReference()}'" }
@@ -538,7 +544,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
}
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference, data: Nothing?): String =
buildString {
buildTrimEnd {
append("LOCAL_DELEGATED_PROPERTY_REFERENCE ")
append("'${expression.symbol.renderReference()}' ")
append("delegate='${expression.delegate.renderReference()}' ")
@@ -87,6 +87,7 @@ interface IrElementTransformer<in D> : IrElementVisitor<IrElement, D> {
override fun visitMemberAccess(expression: IrMemberAccessExpression, data: D): IrElement = visitExpression(expression, data)
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: D): IrElement = visitMemberAccess(expression, data)
override fun visitCall(expression: IrCall, data: D) = visitFunctionAccess(expression, data)
override fun visitConstructorCall(expression: IrConstructorCall, data: D): IrElement = visitFunctionAccess(expression, data)
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: D) = visitFunctionAccess(expression, data)
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: D) = visitFunctionAccess(expression, data)
override fun visitGetClass(expression: IrGetClass, data: D) = visitExpression(expression, data)
@@ -166,6 +166,9 @@ abstract class IrElementTransformerVoid : IrElementTransformer<Nothing?> {
open fun visitCall(expression: IrCall) = visitFunctionAccess(expression)
final override fun visitCall(expression: IrCall, data: Nothing?) = visitCall(expression)
open fun visitConstructorCall(expression: IrConstructorCall) = visitFunctionAccess(expression)
final override fun visitConstructorCall(expression: IrConstructorCall, data: Nothing?) = visitConstructorCall(expression)
open fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) = visitFunctionAccess(expression)
final override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Nothing?) =
visitDelegatingConstructorCall(expression)
@@ -73,6 +73,7 @@ interface IrElementVisitor<out R, in D> {
fun visitMemberAccess(expression: IrMemberAccessExpression, data: D) = visitExpression(expression, data)
fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: D) = visitMemberAccess(expression, data)
fun visitCall(expression: IrCall, data: D) = visitFunctionAccess(expression, data)
fun visitConstructorCall(expression: IrConstructorCall, data: D) = visitFunctionAccess(expression, data)
fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: D) = visitFunctionAccess(expression, data)
fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: D) = visitFunctionAccess(expression, data)
fun visitGetClass(expression: IrGetClass, data: D) = visitExpression(expression, data)
@@ -158,6 +158,9 @@ interface IrElementVisitorVoid : IrElementVisitor<Unit, Nothing?> {
fun visitCall(expression: IrCall) = visitFunctionAccess(expression)
override fun visitCall(expression: IrCall, data: Nothing?) = visitCall(expression)
fun visitConstructorCall(expression: IrConstructorCall) = visitFunctionAccess(expression)
override fun visitConstructorCall(expression: IrConstructorCall, data: Nothing?) = visitConstructorCall(expression)
fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) = visitFunctionAccess(expression)
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Nothing?) =
visitDelegatingConstructorCall(expression)