IrTypes: migrate some code from backend.common

(cherry picked from commit 3788130)
This commit is contained in:
Svyatoslav Scherbina
2018-06-09 10:16:44 +03:00
committed by Dmitry Petrov
parent f1bdb48a76
commit b11abeed6a
21 changed files with 572 additions and 568 deletions
@@ -22,10 +22,11 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.isAnnotationClass import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.makeNullable
typealias ReportError = (element: IrElement, message: String) -> Unit typealias ReportError = (element: IrElement, message: String) -> Unit
@@ -43,8 +44,9 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
} }
private fun IrExpression.ensureTypeIs(expectedType: KotlinType) { private fun IrExpression.ensureTypeIs(expectedType: KotlinType) {
if (expectedType != type) { // TODO: compare IR types instead.
reportError(this, "unexpected expression.type: expected $expectedType, got ${type}") if (expectedType != type.toKotlinType()) {
reportError(this, "unexpected expression.type: expected $expectedType, got ${type.toKotlinType()}")
} }
} }
@@ -154,9 +156,9 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
IrTypeOperator.IMPLICIT_CAST, IrTypeOperator.IMPLICIT_CAST,
IrTypeOperator.IMPLICIT_NOTNULL, IrTypeOperator.IMPLICIT_NOTNULL,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> typeOperand IrTypeOperator.IMPLICIT_INTEGER_COERCION -> typeOperand.toKotlinType()
IrTypeOperator.SAFE_CAST -> typeOperand.makeNullable() IrTypeOperator.SAFE_CAST -> typeOperand.makeNullable().toKotlinType()
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> builtIns.booleanType IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> builtIns.booleanType
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
import org.jetbrains.kotlin.ir.util.DescriptorsRemapper import org.jetbrains.kotlin.ir.util.DescriptorsRemapper
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
@@ -41,8 +42,10 @@ fun <T : IrElement> T.deepCopyWithVariables(): T {
val symbolsRemapper = DeepCopySymbolRemapper(descriptorsRemapper) val symbolsRemapper = DeepCopySymbolRemapper(descriptorsRemapper)
acceptVoid(symbolsRemapper) acceptVoid(symbolsRemapper)
val typesRemapper = DeepCopyTypeRemapper(symbolsRemapper)
return this.transform( return this.transform(
object : DeepCopyIrTreeWithReturnableBlockSymbols(symbolsRemapper) { object : DeepCopyIrTreeWithReturnableBlockSymbols(symbolsRemapper, typesRemapper) {
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop { override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
return irLoop return irLoop
} }
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.renderer.* import org.jetbrains.kotlin.renderer.*
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -285,7 +286,7 @@ class DumpIrTreeWithDescriptorsVisitor(out: Appendable): IrElementVisitor<Unit,
for (typeParameter in expression.descriptor.original.typeParameters) { for (typeParameter in expression.descriptor.original.typeParameters) {
val typeArgument = expression.getTypeArgument(typeParameter) ?: continue val typeArgument = expression.getTypeArgument(typeParameter) ?: continue
val renderedParameter = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(typeParameter) val renderedParameter = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(typeParameter)
val renderedType = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.renderType(typeArgument) val renderedType = typeArgument.render()
printer.println("$renderedParameter: $renderedType") printer.println("$renderedParameter: $renderedType")
} }
} }
@@ -25,10 +25,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.SymbolRemapper import org.jetbrains.kotlin.ir.util.SymbolRemapper
import org.jetbrains.kotlin.ir.util.TypeRemapper
open class DeepCopyIrTreeWithReturnableBlockSymbols( open class DeepCopyIrTreeWithReturnableBlockSymbols(
private val symbolRemapper: SymbolRemapper symbolRemapper: SymbolRemapper,
) : DeepCopyIrTreeWithSymbols(symbolRemapper) { typeRemapper: TypeRemapper
) : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper) {
private inline fun <reified T : IrElement> T.transform() = private inline fun <reified T : IrElement> T.transform() =
transform(this@DeepCopyIrTreeWithReturnableBlockSymbols, null) as T transform(this@DeepCopyIrTreeWithReturnableBlockSymbols, null) as T
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.backend.common.ir package org.jetbrains.kotlin.backend.common.ir
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -26,14 +25,12 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import java.io.StringWriter import java.io.StringWriter
@@ -77,75 +74,62 @@ fun FunctionDescriptor.createOverriddenDescriptor(owner: ClassDescriptor, final:
} }
} }
fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(
superConstructorDescriptor: ClassConstructorDescriptor,
isPrimary: Boolean = false
)
: ClassConstructorDescriptor {
val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
/* containingDeclaration = */ this,
/* annotations = */ Annotations.EMPTY,
/* isPrimary = */ isPrimary,
/* source = */ SourceElement.NO_SOURCE
)
val valueParameters = superConstructorDescriptor.valueParameters.map {
it.copy(constructorDescriptor, it.name, it.index)
}
constructorDescriptor.initialize(valueParameters, superConstructorDescriptor.visibility)
constructorDescriptor.returnType = superConstructorDescriptor.returnType
return constructorDescriptor
}
fun IrClass.addSimpleDelegatingConstructor( fun IrClass.addSimpleDelegatingConstructor(
superConstructorSymbol: IrConstructorSymbol, superConstructor: IrConstructor,
constructorDescriptor: ClassConstructorDescriptor, irBuiltIns: IrBuiltIns,
origin: IrDeclarationOrigin origin: IrDeclarationOrigin,
) isPrimary: Boolean = false
: IrConstructor { ): IrConstructor {
val superConstructorDescriptor = superConstructor.descriptor
val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
/* containingDeclaration = */ this.descriptor,
/* annotations = */ Annotations.EMPTY,
/* isPrimary = */ isPrimary,
/* source = */ SourceElement.NO_SOURCE
)
val valueParameters = superConstructor.valueParameters.map {
val descriptor = it.descriptor as ValueParameterDescriptor
val newDescriptor = descriptor.copy(constructorDescriptor, descriptor.name, descriptor.index)
IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
newDescriptor,
it.type,
it.varargElementType
)
}
constructorDescriptor.initialize(
valueParameters.map { it.descriptor as ValueParameterDescriptor },
superConstructorDescriptor.visibility
)
constructorDescriptor.returnType = superConstructorDescriptor.returnType
return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor -> return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor ->
constructor.createParameterDeclarations()
assert(superConstructor.dispatchReceiverParameter == null) // Inner classes aren't supported.
constructor.valueParameters += valueParameters
constructor.returnType = this.defaultType
constructor.body = IrBlockBodyImpl( constructor.body = IrBlockBodyImpl(
startOffset, endOffset, startOffset, endOffset,
listOf( listOf(
IrDelegatingConstructorCallImpl( IrDelegatingConstructorCallImpl(
startOffset, endOffset, startOffset, endOffset, irBuiltIns.unitType,
superConstructorSymbol, superConstructorSymbol.descriptor superConstructor.symbol, superConstructor.descriptor
).apply { ).apply {
constructor.valueParameters.forEachIndexed { idx, parameter -> constructor.valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.symbol)) putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol))
} }
}, },
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol) IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol, irBuiltIns.unitType)
) )
) )
constructor.parent = this constructor.parent = this
this.declarations.add(constructor) this.declarations.add(constructor)
} }
} }
fun CommonBackendContext.createArrayOfExpression(
arrayElementType: KotlinType,
arrayElements: List<IrExpression>,
startOffset: Int, endOffset: Int
): IrExpression {
val genericArrayOfFunSymbol = ir.symbols.arrayOf
val genericArrayOfFun = genericArrayOfFunSymbol.descriptor
val typeParameter0 = genericArrayOfFun.typeParameters[0]
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!!
val typeArguments = mapOf(typeParameter0 to arrayElementType)
val valueParameter0 = substitutedArrayOfFun.valueParameters[0]
val arg0VarargType = valueParameter0.type
val arg0VarargElementType = valueParameter0.varargElementType!!
val arg0 = IrVarargImpl(startOffset, endOffset, arg0VarargType, arg0VarargElementType, arrayElements)
return IrCallImpl(startOffset, endOffset, genericArrayOfFunSymbol, substitutedArrayOfFun, typeArguments).apply {
putValueArgument(0, arg0)
}
}
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
@@ -33,8 +32,8 @@ import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
@@ -42,18 +41,13 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
import org.jetbrains.kotlin.resolve.calls.components.isVararg import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.builtIns
open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext, private val skipInlineMethods: Boolean = true) : open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext, private val skipInlineMethods: Boolean = true) :
DeclarationContainerLoweringPass { DeclarationContainerLoweringPass {
@@ -82,34 +76,31 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" } log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" }
functionDescriptor.overriddenDescriptors.forEach { context.log { "DEFAULT-REPLACER: $it" } } functionDescriptor.overriddenDescriptors.forEach { context.log { "DEFAULT-REPLACER: $it" } }
if (bodies.isNotEmpty()) { if (bodies.isNotEmpty()) {
val newIrFunction = functionDescriptor.generateDefaultsFunction(context) val newIrFunction = irFunction.generateDefaultsFunction(context)
newIrFunction.parent = irFunction.parent newIrFunction.parent = irFunction.parent
val descriptor = newIrFunction.descriptor val descriptor = newIrFunction.descriptor
log { "$functionDescriptor -> $descriptor" } log { "$functionDescriptor -> $descriptor" }
val builder = context.createIrBuilder(newIrFunction.symbol) val builder = context.createIrBuilder(newIrFunction.symbol)
newIrFunction.body = builder.irBlockBody(newIrFunction) { newIrFunction.body = builder.irBlockBody(newIrFunction) {
val params = mutableListOf<IrVariableSymbol>() val params = mutableListOf<IrVariable>()
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>() val variables = mutableMapOf<ValueDescriptor, IrValueDeclaration>()
irFunction.dispatchReceiverParameter?.let { irFunction.dispatchReceiverParameter?.let {
variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!.symbol variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!
} }
if (descriptor.extensionReceiverParameter != null) { if (descriptor.extensionReceiverParameter != null) {
variables[functionDescriptor.extensionReceiverParameter!!] = variables[functionDescriptor.extensionReceiverParameter!!] =
newIrFunction.extensionReceiverParameter!!.symbol newIrFunction.extensionReceiverParameter!!
} }
for (valueParameter in functionDescriptor.valueParameters) { for (valueParameter in functionDescriptor.valueParameters) {
val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol val parameter = newIrFunction.valueParameters[valueParameter.index]
val temporaryVariableSymbol =
IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor)) val argument = if (valueParameter.hasDefaultValue()) {
params.add(temporaryVariableSymbol) val kIntAnd = symbols.intAnd.owner
variables.put(valueParameter, temporaryVariableSymbol)
if (valueParameter.hasDefaultValue()) {
val kIntAnd = symbols.intAnd
val condition = irNotEquals(irCall(kIntAnd).apply { val condition = irNotEquals(irCall(kIntAnd).apply {
dispatchReceiver = irGet(maskParameterSymbol(newIrFunction, valueParameter.index / 32)) dispatchReceiver = irGet(maskParameter(newIrFunction, valueParameter.index / 32))
putValueArgument(0, irInt(1 shl (valueParameter.index % 32))) putValueArgument(0, irInt(1 shl (valueParameter.index % 32)))
}, irInt(0)) }, irInt(0))
val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter) val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter)
@@ -122,41 +113,40 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
return irGet(valueSymbol) return irGet(valueSymbol)
} }
}) })
val variableInitialization = irIfThenElse( irIfThenElse(
type = temporaryVariableSymbol.descriptor.type, type = parameter.type,
condition = condition, condition = condition,
thenPart = expressionBody.expression, thenPart = expressionBody.expression,
elsePart = irGet(parameterSymbol) elsePart = irGet(parameter)
)
+scope.createTemporaryVariable(
symbol = temporaryVariableSymbol,
initializer = variableInitialization
) )
/* Mapping calculated values with its origin variables. */ /* Mapping calculated values with its origin variables. */
} else { } else {
+scope.createTemporaryVariable( irGet(parameter)
symbol = temporaryVariableSymbol,
initializer = irGet(parameterSymbol)
)
} }
val temporaryVariable = irTemporary(argument, nameHint = parameter.name.asString())
params.add(temporaryVariable)
variables.put(valueParameter, temporaryVariable)
} }
if (irFunction is IrConstructor) { if (irFunction is IrConstructor) {
+IrDelegatingConstructorCallImpl( +IrDelegatingConstructorCallImpl(
startOffset = irFunction.startOffset, startOffset = irFunction.startOffset,
endOffset = irFunction.endOffset, endOffset = irFunction.endOffset,
type = context.irBuiltIns.unitType,
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor
).apply { ).apply {
params.forEachIndexed { i, variable -> params.forEachIndexed { i, variable ->
putValueArgument(i, irGet(variable)) putValueArgument(i, irGet(variable))
} }
if (functionDescriptor.dispatchReceiverParameter != null) { if (functionDescriptor.dispatchReceiverParameter != null) {
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol) dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!)
} }
} }
} else { } else {
+irReturn(irCall(irFunction.symbol).apply { +irReturn(irCall(irFunction).apply {
if (functionDescriptor.dispatchReceiverParameter != null) { if (functionDescriptor.dispatchReceiverParameter != null) {
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol) dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!)
} }
if (functionDescriptor.extensionReceiverParameter != null) { if (functionDescriptor.extensionReceiverParameter != null) {
extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!) extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!)
@@ -181,50 +171,29 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" } private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" }
} }
private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor =
IrTemporaryVariableDescriptorImpl(
containingDeclaration = this.scopeOwner,
name = parameterDescriptor!!.name.asString().synthesizedName,
outType = parameterDescriptor.type,
isMutable = false
)
private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) =
IrVariableImpl(
startOffset = initializer.startOffset,
endOffset = initializer.endOffset,
origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
symbol = symbol
).apply {
this.initializer = initializer
}
private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor): IrExpressionBody { private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor): IrExpressionBody {
return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!") return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!")
} }
private fun maskParameterDescriptor(function: IrFunction, number: Int) = private fun maskParameterDescriptor(function: IrFunction, number: Int) =
maskParameterSymbol(function, number).descriptor as ValueParameterDescriptor maskParameter(function, number).descriptor as ValueParameterDescriptor
private fun maskParameterSymbol(function: IrFunction, number: Int) = private fun maskParameter(function: IrFunction, number: Int) =
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }
private fun markerParameterDescriptor(descriptor: FunctionDescriptor) = private fun markerParameterDescriptor(descriptor: FunctionDescriptor) =
descriptor.valueParameters.single { it.name == kConstructorMarkerName } descriptor.valueParameters.single { it.name == kConstructorMarkerName }
private fun nullConst(expression: IrElement, type: KotlinType): IrExpression? { private fun nullConst(expression: IrElement, type: IrType, context: CommonBackendContext) = when {
when { type.isFloat() -> IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
KotlinBuiltIns.isFloat(type) -> return IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F) type.isDouble() -> IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
KotlinBuiltIns.isDouble(type) -> return IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0) type.isBoolean() -> IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
KotlinBuiltIns.isBoolean(type) -> return IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false) type.isByte() -> IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isByte(type) -> return IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0) type.isChar() -> IrConstImpl.char(expression.startOffset, expression.endOffset, type, 0.toChar())
KotlinBuiltIns.isChar(type) -> return IrConstImpl.char(expression.startOffset, expression.endOffset, type, 0.toChar()) type.isShort() -> IrConstImpl.short(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isShort(type) -> return IrConstImpl.short(expression.startOffset, expression.endOffset, type, 0) type.isInt() -> IrConstImpl.int(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isInt(type) -> return IrConstImpl.int(expression.startOffset, expression.endOffset, type, 0) type.isLong() -> IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isLong(type) -> return IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0) else -> IrConstImpl.constNull(expression.startOffset, expression.endOffset, context.irBuiltIns.nothingNType)
else -> return IrConstImpl.constNull(expression.startOffset, expression.endOffset, type.builtIns.nullableNothingType)
}
} }
class DefaultParameterInjector constructor(val context: CommonBackendContext, private val skipInline: Boolean = true) : BodyLoweringPass { class DefaultParameterInjector constructor(val context: CommonBackendContext, private val skipInline: Boolean = true) : BodyLoweringPass {
@@ -240,10 +209,12 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
if (argumentsCount == descriptor.valueParameters.size) if (argumentsCount == descriptor.valueParameters.size)
return expression return expression
val (symbolForCall, params) = parametersForCall(expression) val (symbolForCall, params) = parametersForCall(expression)
symbolForCall as IrConstructorSymbol
return IrDelegatingConstructorCallImpl( return IrDelegatingConstructorCallImpl(
startOffset = expression.startOffset, startOffset = expression.startOffset,
endOffset = expression.endOffset, endOffset = expression.endOffset,
symbol = symbolForCall as IrConstructorSymbol, type = context.irBuiltIns.unitType,
symbol = symbolForCall,
descriptor = symbolForCall.descriptor descriptor = symbolForCall.descriptor
) )
.apply { .apply {
@@ -273,13 +244,14 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
return IrCallImpl( return IrCallImpl(
startOffset = expression.startOffset, startOffset = expression.startOffset,
endOffset = expression.endOffset, endOffset = expression.endOffset,
type = symbol.owner.returnType,
symbol = symbol, symbol = symbol,
descriptor = descriptor, descriptor = descriptor,
typeArguments = expression.descriptor.typeParameters.map { typeArgumentsCount = expression.typeArgumentsCount
it to (expression.getTypeArgument(it) ?: it.defaultType)
}.toMap()
) )
.apply { .apply {
this.copyTypeArgumentsFrom(expression)
params.forEach { params.forEach {
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
putValueArgument(it.first.index, it.second) putValueArgument(it.first.index, it.second)
@@ -310,8 +282,7 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
private fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> { private fun parametersForCall(expression: IrFunctionAccessExpression): Pair<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> {
val descriptor = expression.descriptor val descriptor = expression.descriptor
val keyFunction = expression.symbol.owner.findSuperMethodWithDefaultArguments()!! val keyFunction = expression.symbol.owner.findSuperMethodWithDefaultArguments()!!
val keyDescriptor = keyFunction.descriptor val realFunction = keyFunction.generateDefaultsFunction(context)
val realFunction = keyDescriptor.generateDefaultsFunction(context)
realFunction.parent = keyFunction.parent realFunction.parent = keyFunction.parent
val realDescriptor = realFunction.descriptor val realDescriptor = realFunction.descriptor
@@ -325,15 +296,18 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32)) maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32))
} }
val valueParameterDescriptor = realDescriptor.valueParameters[i] val valueParameterDescriptor = realDescriptor.valueParameters[i]
val defaultValueArgument = val defaultValueArgument = if (valueParameterDescriptor.isVararg) {
if (valueParameterDescriptor.isVararg) null else nullConst(expression, valueParameterDescriptor.type) null
} else {
nullConst(expression, realFunction.valueParameters[i].type, context)
}
valueParameterDescriptor to (valueArgument ?: defaultValueArgument) valueParameterDescriptor to (valueArgument ?: defaultValueArgument)
}) })
maskValues.forEachIndexed { i, maskValue -> maskValues.forEachIndexed { i, maskValue ->
params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int( params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int(
startOffset = irBody.startOffset, startOffset = irBody.startOffset,
endOffset = irBody.endOffset, endOffset = irBody.endOffset,
type = descriptor.builtIns.intType, type = context.irBuiltIns.intType,
value = maskValue value = maskValue
) )
} }
@@ -347,7 +321,7 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
) )
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { } else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
params += realDescriptor.valueParameters.last() to params += realDescriptor.valueParameters.last() to
IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.builtIns.any.defaultType) IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.irBuiltIns.anyType)
} }
params.forEach { params.forEach {
log { "descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}" } log { "descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}" }
@@ -366,7 +340,7 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
private fun CallableMemberDescriptor.needsDefaultArgumentsLowering(skipInlineMethods: Boolean) = private fun CallableMemberDescriptor.needsDefaultArgumentsLowering(skipInlineMethods: Boolean) =
valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline && skipInlineMethods) valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline && skipInlineMethods)
private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendContext): IrFunction { private fun IrFunction.generateDefaultsFunction(context: CommonBackendContext): IrFunction = with(this.descriptor) {
return context.ir.defaultParameterDeclarationsCache.getOrPut(this) { return context.ir.defaultParameterDeclarationsCache.getOrPut(this) {
val descriptor = when (this) { val descriptor = when (this) {
is ClassConstructorDescriptor -> is ClassConstructorDescriptor ->
@@ -389,8 +363,10 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
} }
} }
val function = this@generateDefaultsFunction
val syntheticParameters = MutableList((valueParameters.size + 31) / 32) { i -> val syntheticParameters = MutableList((valueParameters.size + 31) / 32) { i ->
valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), descriptor.builtIns.intType) valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), context.irBuiltIns.intType)
} }
if (this is ClassConstructorDescriptor) { if (this is ClassConstructorDescriptor) {
syntheticParameters += valueParameter( syntheticParameters += valueParameter(
@@ -402,10 +378,29 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
syntheticParameters += valueParameter( syntheticParameters += valueParameter(
descriptor, syntheticParameters.last().index + 1, descriptor, syntheticParameters.last().index + 1,
"handler".synthesizedName, "handler".synthesizedName,
context.ir.symbols.any.owner.defaultType context.irBuiltIns.anyType
) )
} }
val newValueParameters = function.valueParameters.map {
val parameterDescriptor = ValueParameterDescriptorImpl(
containingDeclaration = descriptor,
original = null, /* ValueParameterDescriptorImpl::copy do not save original. */
index = it.index,
annotations = it.descriptor.annotations,
name = it.name,
outType = it.descriptor.type,
declaresDefaultValue = false,
isCrossinline = it.isCrossinline,
isNoinline = it.isNoinline,
varargElementType = (it.descriptor as ValueParameterDescriptor).varargElementType,
source = it.descriptor.source
)
it.copy(parameterDescriptor)
} + syntheticParameters
descriptor.initialize( descriptor.initialize(
/* receiverParameterType = */ extensionReceiverParameter?.type, /* receiverParameterType = */ extensionReceiverParameter?.type,
/* dispatchReceiverParameter = */ dispatchReceiverParameter, /* dispatchReceiverParameter = */ dispatchReceiverParameter,
@@ -425,24 +420,11 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
setInitialized() setInitialized()
} }
}, },
/* unsubstitutedValueParameters = */ valueParameters.map { /* unsubstitutedValueParameters = */ newValueParameters.map { it.descriptor as ValueParameterDescriptor },
ValueParameterDescriptorImpl(
containingDeclaration = descriptor,
original = null, /* ValueParameterDescriptorImpl::copy do not save original. */
index = it.index,
annotations = it.annotations,
name = it.name,
outType = it.type,
declaresDefaultValue = false,
isCrossinline = it.isCrossinline,
isNoinline = it.isNoinline,
varargElementType = it.varargElementType,
source = it.source
)
} + syntheticParameters,
/* unsubstitutedReturnType = */ returnType, /* unsubstitutedReturnType = */ returnType,
/* modality = */ Modality.FINAL, /* modality = */ Modality.FINAL,
/* visibility = */ this.visibility) /* visibility = */ this.visibility
)
descriptor.isSuspend = this.isSuspend descriptor.isSuspend = this.isSuspend
context.log { "adds to cache[$this] = $descriptor" } context.log { "adds to cache[$this] = $descriptor" }
@@ -463,7 +445,29 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
) )
} }
result.createParameterDeclarations() result.returnType = function.returnType
function.typeParameters.mapTo(result.typeParameters) {
assert(function.descriptor.typeParameters[it.index] == it.descriptor)
IrTypeParameterImpl(
startOffset, endOffset, origin, descriptor.typeParameters[it.index]
).apply { this.superTypes += it.superTypes }
}
result.parent = function.parent
result.createDispatchReceiverParameter()
function.extensionReceiverParameter?.let {
result.extensionReceiverParameter = IrValueParameterImpl(
it.startOffset,
it.endOffset,
it.origin,
descriptor.extensionReceiverParameter!!,
it.type,
it.varargElementType
).apply { parent = result }
}
result.valueParameters += newValueParameters.also { it.forEach { it.parent = result } }
result result
} }
@@ -472,20 +476,28 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER : object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER :
IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT") IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT")
private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType): ValueParameterDescriptor { private fun IrFunction.valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: IrType): IrValueParameter {
return ValueParameterDescriptorImpl( val parameterDescriptor = ValueParameterDescriptorImpl(
containingDeclaration = descriptor, containingDeclaration = descriptor,
original = null, original = null,
index = index, index = index,
annotations = Annotations.EMPTY, annotations = Annotations.EMPTY,
name = name, name = name,
outType = type, outType = type.toKotlinType(),
declaresDefaultValue = false, declaresDefaultValue = false,
isCrossinline = false, isCrossinline = false,
isNoinline = false, isNoinline = false,
varargElementType = null, varargElementType = null,
source = SourceElement.NO_SOURCE source = SourceElement.NO_SOURCE
) )
return IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
parameterDescriptor,
type,
null
)
} }
internal val kConstructorMarkerName = "marker".synthesizedName internal val kConstructorMarkerName = "marker".synthesizedName
@@ -68,7 +68,7 @@ class InitializersLowering(
if (declaration.descriptor.dispatchReceiverParameter != null) // TODO isStaticField if (declaration.descriptor.dispatchReceiverParameter != null) // TODO isStaticField
IrGetValueImpl( IrGetValueImpl(
irFieldInitializer.startOffset, irFieldInitializer.endOffset, irFieldInitializer.startOffset, irFieldInitializer.endOffset,
irClass.thisReceiver!!.symbol irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
) )
else null else null
val irSetField = IrSetFieldImpl( val irSetField = IrSetFieldImpl(
@@ -76,6 +76,7 @@ class InitializersLowering(
declaration.symbol, declaration.symbol,
receiver, receiver,
irFieldInitializer, irFieldInitializer,
context.irBuiltIns.unitType,
null, null null, null
) )
@@ -93,7 +94,7 @@ class InitializersLowering(
fun transformInstanceInitializerCallsInConstructors(irClass: IrClass) { fun transformInstanceInitializerCallsInConstructors(irClass: IrClass) {
irClass.transformChildrenVoid(object : IrElementTransformerVoid() { irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression { override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.builtIns.unitType, null, return IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null,
instanceInitializerStatements.map { it.copy(irClass) }) instanceInitializerStatements.map { it.copy(irClass) })
} }
}) })
@@ -16,26 +16,8 @@
package org.jetbrains.kotlin.backend.common.lower package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
abstract class SymbolWithIrBuilder<out S: IrSymbol, out D: IrDeclaration> { abstract class SymbolWithIrBuilder<out S: IrSymbol, out D: IrDeclaration> {
@@ -62,155 +44,3 @@ abstract class SymbolWithIrBuilder<out S: IrSymbol, out D: IrDeclaration> {
return builtIr return builtIr
} }
} }
fun BackendContext.createPropertyGetterBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin,
fieldSymbol: IrFieldSymbol, type: KotlinType)
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
PropertyGetterDescriptorImpl(
/* correspondingProperty = */ fieldSymbol.descriptor,
/* annotations = */ Annotations.EMPTY,
/* modality = */ Modality.FINAL,
/* visibility = */ Visibilities.PRIVATE,
/* isDefault = */ false,
/* isExternal = */ false,
/* isInline = */ false,
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/* original = */ null,
/* source = */ SourceElement.NO_SOURCE
)
)
override fun doInitialize() {
val descriptor = symbol.descriptor as PropertyGetterDescriptorImpl
descriptor.apply {
initialize(type)
}
}
override fun buildIr() = IrFunctionImpl(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
symbol = symbol).apply {
createParameterDeclarations()
body = createIrBuilder(this.symbol, startOffset, endOffset).irBlockBody {
+irReturn(irGetField(irGet(this@apply.dispatchReceiverParameter!!.symbol), fieldSymbol))
}
}
}
private fun BackendContext.createPropertySetterBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin,
fieldSymbol: IrFieldSymbol, type: KotlinType)
= object: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>() {
override fun buildSymbol() = IrSimpleFunctionSymbolImpl(
PropertySetterDescriptorImpl(
/* correspondingProperty = */ fieldSymbol.descriptor,
/* annotations = */ Annotations.EMPTY,
/* modality = */ Modality.FINAL,
/* visibility = */ Visibilities.PRIVATE,
/* isDefault = */ false,
/* isExternal = */ false,
/* isInline = */ false,
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/* original = */ null,
/* source = */ SourceElement.NO_SOURCE
)
)
lateinit var valueParameterDescriptor: ValueParameterDescriptor
override fun doInitialize() {
val descriptor = symbol.descriptor as PropertySetterDescriptorImpl
descriptor.apply {
valueParameterDescriptor = ValueParameterDescriptorImpl(
containingDeclaration = this,
original = null,
index = 0,
annotations = Annotations.EMPTY,
name = Name.identifier("value"),
outType = type,
declaresDefaultValue = false,
isCrossinline = false,
isNoinline = false,
varargElementType = null,
source = SourceElement.NO_SOURCE
)
initialize(valueParameterDescriptor)
}
}
override fun buildIr() = IrFunctionImpl(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
symbol = symbol).apply {
createParameterDeclarations()
body = createIrBuilder(this.symbol, startOffset, endOffset).irBlockBody {
+irSetField(irGet(this@apply.dispatchReceiverParameter!!.symbol), fieldSymbol, irGet(this@apply.valueParameters.single().symbol))
}
}
}
fun BackendContext.createPropertyWithBackingFieldBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin,
owner: ClassDescriptor, name: Name, type: KotlinType, isMutable: Boolean)
= object: SymbolWithIrBuilder<IrFieldSymbol, IrProperty>() {
private lateinit var getterBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>
private var setterBuilder: SymbolWithIrBuilder<IrSimpleFunctionSymbol, IrSimpleFunction>? = null
override fun buildSymbol() = IrFieldSymbolImpl(
PropertyDescriptorImpl.create(
/* containingDeclaration = */ owner,
/* annotations = */ Annotations.EMPTY,
/* modality = */ Modality.FINAL,
/* visibility = */ Visibilities.PRIVATE,
/* isVar = */ isMutable,
/* name = */ name,
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/* source = */ SourceElement.NO_SOURCE,
/* lateInit = */ false,
/* isConst = */ false,
/* isExpect = */ false,
/* isActual = */ false,
/* isExternal = */ false,
/* isDelegated = */ false
)
)
override fun doInitialize() {
val descriptor = symbol.descriptor as PropertyDescriptorImpl
getterBuilder = createPropertyGetterBuilder(startOffset, endOffset, origin, symbol, type).apply { initialize() }
if (isMutable)
setterBuilder = createPropertySetterBuilder(startOffset, endOffset, origin, symbol, type).apply { initialize() }
descriptor.initialize(
/* getter = */ getterBuilder.symbol.descriptor as PropertyGetterDescriptorImpl,
/* setter = */ setterBuilder?.symbol?.descriptor as? PropertySetterDescriptorImpl)
val receiverType: KotlinType? = null
descriptor.setType(type, emptyList(), owner.thisAsReceiverParameter, receiverType)
}
override fun buildIr(): IrProperty {
val backingField = IrFieldImpl(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
symbol = symbol)
return IrPropertyImpl(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
isDelegated = false,
descriptor = symbol.descriptor,
backingField = backingField,
getter = getterBuilder.ir,
setter = setterBuilder?.ir)
}
}
@@ -58,7 +58,7 @@ private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyL
return lower.context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).run { return lower.context.createIrBuilder(expression.symbol, expression.startOffset, expression.endOffset).run {
IrCompositeImpl(startOffset, endOffset, context.builtIns.stringType).apply { IrCompositeImpl(startOffset, endOffset, context.irBuiltIns.stringType).apply {
receiver?.let { receiver?.let {
//put receiver for bound callable reference //put receiver for bound callable reference
statements.add(it) statements.add(it)
@@ -68,7 +68,7 @@ private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyL
IrConstImpl.string( IrConstImpl.string(
expression.startOffset, expression.startOffset,
expression.endOffset, expression.endOffset,
context.builtIns.stringType, context.irBuiltIns.stringType,
callableReference.descriptor.name.asString() callableReference.descriptor.name.asString()
) )
) )
@@ -27,6 +27,8 @@ import org.jetbrains.kotlin.ir.expressions.IrBlock
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isPrimitiveType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -45,20 +47,20 @@ class LateinitLowering(
private fun transformGetter(backingField: IrField, getter: IrFunction) { private fun transformGetter(backingField: IrField, getter: IrFunction) {
val type = backingField.type val type = backingField.type
assert(!KotlinBuiltIns.isPrimitiveType(type)) { "'lateinit' modifier is not allowed on primitive types" } assert(!type.isPrimitiveType()) { "'lateinit' modifier is not allowed on primitive types" }
val startOffset = getter.startOffset val startOffset = getter.startOffset
val endOffset = getter.endOffset val endOffset = getter.endOffset
val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset) val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset)
irBuilder.run { irBuilder.run {
val block = irBlock(type) val block = irBlock(type)
val resultVar = scope.createTemporaryVariable( val resultVar = scope.createTemporaryVariable(
irGetField(getter.dispatchReceiverParameter?.let { irGet(it.symbol) }, backingField.symbol) irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField)
) )
block.statements.add(resultVar) block.statements.add(resultVar)
val throwIfNull = irIfThenElse( val throwIfNull = irIfThenElse(
context.builtIns.nothingType, context.irBuiltIns.nothingType,
irNotEquals(irGet(resultVar.symbol), irNull()), irNotEquals(irGet(resultVar), irNull()),
irReturn(irGet(resultVar.symbol)), irReturn(irGet(resultVar)),
throwUninitializedPropertyAccessException(backingField) throwUninitializedPropertyAccessException(backingField)
) )
block.statements.add(throwIfNull) block.statements.add(throwIfNull)
@@ -76,15 +78,15 @@ class LateinitLowering(
IrConstImpl.string( IrConstImpl.string(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.builtIns.stringType, context.irBuiltIns.stringType,
backingField.name.asString() backingField.name.asString()
) )
) )
} }
} }
private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException.owner
private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type) private fun IrBuilderWithScope.irBlock(type: IrType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
} }
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.parents import org.jetbrains.kotlin.resolve.descriptorUtil.parents
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.types.KotlinType
import java.util.* import java.util.*
interface LocalNameProvider { interface LocalNameProvider {
@@ -98,12 +97,12 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
abstract val transformedDescriptor: FunctionDescriptor abstract val transformedDescriptor: FunctionDescriptor
abstract val transformedDeclaration: IrFunction abstract val transformedDeclaration: IrFunction
val capturedValueToParameter: MutableMap<ValueDescriptor, IrValueParameterSymbol> = HashMap() val capturedValueToParameter: MutableMap<ValueDescriptor, IrValueParameter> = HashMap()
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val newSymbol = capturedValueToParameter[descriptor] ?: return null val parameter = capturedValueToParameter[descriptor] ?: return null
return IrGetValueImpl(startOffset, endOffset, newSymbol) return IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol)
} }
} }
@@ -141,9 +140,10 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val field = capturedValueToField[descriptor] ?: return null val field = capturedValueToField[descriptor] ?: return null
val receiver = declaration.thisReceiver!!
return IrGetFieldImpl( return IrGetFieldImpl(
startOffset, endOffset, field.symbol, startOffset, endOffset, field.symbol, field.type,
receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol) receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
) )
} }
@@ -155,9 +155,10 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val field = classContext.capturedValueToField[descriptor] ?: return null val field = classContext.capturedValueToField[descriptor] ?: return null
val receiver = member.dispatchReceiverParameter!!
return IrGetFieldImpl( return IrGetFieldImpl(
startOffset, endOffset, field.symbol, startOffset, endOffset, field.symbol, field.type,
receiver = IrGetValueImpl(startOffset, endOffset, member.dispatchReceiverParameter!!.symbol) receiver = IrGetValueImpl(startOffset, endOffset, receiver.type, receiver.symbol)
) )
} }
@@ -168,12 +169,12 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap() val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap()
val localClassConstructors: MutableMap<ClassConstructorDescriptor, LocalClassConstructorContext> = LinkedHashMap() val localClassConstructors: MutableMap<ClassConstructorDescriptor, LocalClassConstructorContext> = LinkedHashMap()
val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrSymbol>() val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrDeclaration>()
val FunctionDescriptor.transformed: IrFunctionSymbol? val FunctionDescriptor.transformed: IrFunction?
get() = transformedDeclarations[this] as IrFunctionSymbol? get() = transformedDeclarations[this] as IrFunction?
val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameterSymbol> = HashMap() val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameter> = HashMap()
val newParameterToOld: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap() val newParameterToOld: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap()
val newParameterToCaptured: MutableMap<ValueParameterDescriptor, IrValueSymbol> = HashMap() val newParameterToCaptured: MutableMap<ValueParameterDescriptor, IrValueSymbol> = HashMap()
@@ -200,7 +201,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
val body = original.getDefault(argument)!! val body = original.getDefault(argument)!!
oldParameterToNew[argument]!!.owner.defaultValue = body oldParameterToNew[argument]!!.defaultValue = body
} }
} }
} }
@@ -218,7 +219,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun visitClass(declaration: IrClass): IrStatement { override fun visitClass(declaration: IrClass): IrStatement {
if (declaration.descriptor in localClasses) { if (declaration.descriptor in localClasses) {
// Replace local class definition with an empty composite. // Replace local class definition with an empty composite.
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType)
} else { } else {
return super.visitClass(declaration) return super.visitClass(declaration)
} }
@@ -227,7 +228,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun visitFunction(declaration: IrFunction): IrStatement { override fun visitFunction(declaration: IrFunction): IrStatement {
if (declaration.descriptor in localFunctions) { if (declaration.descriptor in localFunctions) {
// Replace local function definition with an empty composite. // Replace local function definition with an empty composite.
return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.builtIns.unitType) return IrCompositeImpl(declaration.startOffset, declaration.endOffset, context.irBuiltIns.unitType)
} else { } else {
if (localContext is LocalClassContext && declaration.parent == localContext.declaration) { if (localContext is LocalClassContext && declaration.parent == localContext.declaration) {
return declaration.apply { return declaration.apply {
@@ -250,7 +251,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
val body = declaration.getDefault(argument)!! val body = declaration.getDefault(argument)!!
oldParameterToNew[argument]!!.owner.defaultValue = body oldParameterToNew[argument]!!.defaultValue = body
} }
} }
} else { } else {
@@ -266,7 +267,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
} }
oldParameterToNew[descriptor]?.let { oldParameterToNew[descriptor]?.let {
return IrGetValueImpl(expression.startOffset, expression.endOffset, it) return IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol)
} }
return expression return expression
@@ -287,14 +288,17 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val oldCallee = expression.descriptor.original val oldCallee = expression.descriptor.original
val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression val newCallee = transformedDeclarations[oldCallee] as IrConstructor? ?: return expression
return IrDelegatingConstructorCallImpl( return IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
newCallee, context.irBuiltIns.unitType,
newCallee.descriptor, newCallee.symbol,
remapTypeArguments(expression, newCallee.descriptor) newCallee.descriptor
).fillArguments(expression) ).also {
it.fillArguments(expression)
it.copyTypeArgumentsFrom(expression)
}
} }
private fun <T : IrMemberAccessExpression> T.fillArguments(oldExpression: IrMemberAccessExpression): T { private fun <T : IrMemberAccessExpression> T.fillArguments(oldExpression: IrMemberAccessExpression): T {
@@ -310,16 +314,17 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
newParameterToCaptured[newValueParameterDescriptor] newParameterToCaptured[newValueParameterDescriptor]
?: throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") ?: throw AssertionError("Non-mapped parameter $newValueParameterDescriptor")
val capturedValue = capturedValueSymbol.owner
val capturedValueDescriptor = capturedValueSymbol.descriptor val capturedValueDescriptor = capturedValueSymbol.descriptor
localContext?.irGet( localContext?.irGet(
oldExpression.startOffset, oldExpression.endOffset, oldExpression.startOffset, oldExpression.endOffset,
capturedValueDescriptor capturedValueDescriptor
) ?: ) ?: run {
// Captured value is directly available for the caller. // Captured value is directly available for the caller.
IrGetValueImpl( val value = oldParameterToNew[capturedValueDescriptor] ?: capturedValue
oldExpression.startOffset, oldExpression.endOffset, IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, value.type, value.symbol)
oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol }
)
} }
} }
@@ -339,11 +344,14 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newCallableReference = IrFunctionReferenceImpl( val newCallableReference = IrFunctionReferenceImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
expression.type, // TODO functional type for transformed descriptor expression.type, // TODO functional type for transformed descriptor
newCallee, newCallee.symbol,
newCallee.descriptor, newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor), expression.typeArgumentsCount,
expression.origin expression.origin
).fillArguments(expression) ).also {
it.fillArguments(expression)
it.copyTypeArgumentsFrom(expression)
}
return newCallableReference return newCallableReference
} }
@@ -354,7 +362,11 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val oldReturnTarget = expression.returnTarget val oldReturnTarget = expression.returnTarget
val newReturnTarget = oldReturnTarget.transformed ?: return expression val newReturnTarget = oldReturnTarget.transformed ?: return expression
return IrReturnImpl(expression.startOffset, expression.endOffset, newReturnTarget, expression.value) return IrReturnImpl(
expression.startOffset, expression.endOffset,
context.irBuiltIns.nothingType,
newReturnTarget.symbol, expression.value
)
} }
override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression { override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression {
@@ -398,8 +410,10 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
0, 0,
IrSetFieldImpl( IrSetFieldImpl(
startOffset, endOffset, field.symbol, startOffset, endOffset, field.symbol,
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol),
capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE capturedValueExpression,
context.irBuiltIns.unitType,
STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE
) )
) )
} }
@@ -422,31 +436,19 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
rewriteFunctionBody(memberDeclaration, null) rewriteFunctionBody(memberDeclaration, null)
} }
private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) = private fun createNewCall(oldCall: IrCall, newCallee: IrFunction) =
if (oldCall is IrCallWithShallowCopy) if (oldCall is IrCallWithShallowCopy)
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol) oldCall.shallowCopy(oldCall.origin, newCallee.symbol, oldCall.superQualifierSymbol)
else else
IrCallImpl( IrCallImpl(
oldCall.startOffset, oldCall.endOffset, oldCall.startOffset, oldCall.endOffset,
newCallee, newCallee.returnType,
newCallee.symbol,
newCallee.descriptor, newCallee.descriptor,
remapTypeArguments(oldCall, newCallee.descriptor),
oldCall.origin, oldCall.superQualifierSymbol oldCall.origin, oldCall.superQualifierSymbol
) ).also {
it.copyTypeArgumentsFrom(oldCall)
private fun remapTypeArguments( }
oldExpression: IrMemberAccessExpression,
newCallee: CallableDescriptor
): Map<TypeParameterDescriptor, KotlinType>? {
val oldCallee = oldExpression.descriptor.original
return if (oldCallee.typeParameters.isEmpty())
null
else oldCallee.typeParameters.associateBy(
{ newCallee.typeParameters[it.index] },
{ oldExpression.getTypeArgumentOrDefault(it) }
)
}
private fun transformDescriptors() { private fun transformDescriptors() {
localFunctions.values.forEach { localFunctions.values.forEach {
@@ -519,7 +521,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
oldDescriptor.extensionReceiverParameter?.type, oldDescriptor.extensionReceiverParameter?.type,
newDispatchReceiverParameter, newDispatchReceiverParameter,
newTypeParameters, newTypeParameters,
newValueParameters, newValueParameters.map { it.descriptor as ValueParameterDescriptor },
oldDescriptor.returnType, oldDescriptor.returnType,
Modality.FINAL, Modality.FINAL,
Visibilities.PRIVATE Visibilities.PRIVATE
@@ -533,9 +535,26 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
IrFunctionImpl(startOffset, endOffset, origin, newDescriptor) IrFunctionImpl(startOffset, endOffset, origin, newDescriptor)
}.apply { }.apply {
parent = memberDeclaration.parent parent = memberDeclaration.parent
createParameterDeclarations() returnType = localFunctionContext.declaration.returnType
localFunctionContext.declaration.typeParameters.mapTo(this.typeParameters) {
IrTypeParameterImpl(it.startOffset, it.endOffset, it.origin, it.descriptor)
.apply { superTypes += it.superTypes }
}
localFunctionContext.declaration.extensionReceiverParameter?.let {
this.extensionReceiverParameter = IrValueParameterImpl(
it.startOffset,
it.endOffset,
it.origin,
descriptor.extensionReceiverParameter!!,
it.type,
null
)
}
this.valueParameters += newValueParameters
recordTransformedValueParameters(localFunctionContext) recordTransformedValueParameters(localFunctionContext)
transformedDeclarations[oldDescriptor] = this.symbol transformedDeclarations[oldDescriptor] = this
} }
} }
@@ -543,7 +562,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
localContext: LocalContextWithClosureAsParameters, localContext: LocalContextWithClosureAsParameters,
capturedValues: List<IrValueSymbol> capturedValues: List<IrValueSymbol>
) )
: List<ValueParameterDescriptor> { : List<IrValueParameter> {
val oldDescriptor = localContext.descriptor val oldDescriptor = localContext.descriptor
val newDescriptor = localContext.transformedDescriptor val newDescriptor = localContext.transformedDescriptor
@@ -551,17 +570,23 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val closureParametersCount = capturedValues.size val closureParametersCount = capturedValues.size
val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size
val newValueParameters = ArrayList<ValueParameterDescriptor>(newValueParametersCount).apply { val newValueParameters = ArrayList<IrValueParameter>(newValueParametersCount).apply {
capturedValues.mapIndexedTo(this) { i, capturedValue -> capturedValues.mapIndexedTo(this) { i, capturedValue ->
createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply { val parameterDescriptor = createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply {
newParameterToCaptured[this] = capturedValue newParameterToCaptured[this] = capturedValue
} }
capturedValue.owner.copy(parameterDescriptor)
} }
oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor -> localContext.declaration.valueParameters.mapIndexedTo(this) { i, oldValueParameter ->
createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply { val parameterDescriptor = createUnsubstitutedParameter(
newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor) newDescriptor,
oldValueParameter.descriptor as ValueParameterDescriptor,
closureParametersCount + i
).apply {
newParameterToOld.putAbsentOrSame(this, oldValueParameter.descriptor)
} }
oldValueParameter.copy(parameterDescriptor)
} }
} }
return newValueParameters return newValueParameters
@@ -572,14 +597,14 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
valueParameters.forEach { valueParameters.forEach {
val capturedValue = newParameterToCaptured[it.descriptor] val capturedValue = newParameterToCaptured[it.descriptor]
if (capturedValue != null) { if (capturedValue != null) {
localContext.capturedValueToParameter[capturedValue.descriptor] = it.symbol localContext.capturedValueToParameter[capturedValue.descriptor] = it
} }
} }
(listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach { (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach {
val oldParameter = newParameterToOld[it.descriptor] val oldParameter = newParameterToOld[it.descriptor]
if (oldParameter != null) { if (oldParameter != null) {
oldParameterToNew.putAbsentOrSame(oldParameter, it.symbol) oldParameterToNew.putAbsentOrSame(oldParameter, it)
} }
} }
@@ -603,7 +628,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues) val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues)
newDescriptor.initialize( newDescriptor.initialize(
newValueParameters, newValueParameters.map { it.descriptor as ValueParameterDescriptor },
Visibilities.PRIVATE, Visibilities.PRIVATE,
newTypeParameters newTypeParameters
) )
@@ -618,12 +643,23 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
} }
constructorContext.transformedDeclaration = with(constructorContext.declaration) { constructorContext.transformedDeclaration = with(constructorContext.declaration) {
IrConstructorImpl(startOffset, endOffset, origin, newDescriptor) IrConstructorImpl(startOffset, endOffset, origin, newDescriptor).also { it.returnType = returnType }
}.apply { }.apply {
parent = constructorContext.declaration.parent parent = constructorContext.declaration.parent
createParameterDeclarations() constructorContext.declaration.dispatchReceiverParameter?.let {
this.dispatchReceiverParameter = IrValueParameterImpl(
it.startOffset,
it.endOffset,
it.origin,
descriptor.dispatchReceiverParameter!!,
it.type,
null
)
}
this.valueParameters += newValueParameters
recordTransformedValueParameters(constructorContext) recordTransformedValueParameters(constructorContext)
transformedDeclarations[oldDescriptor] = this.symbol transformedDeclarations[oldDescriptor] = this
} }
} }
@@ -662,7 +698,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl( localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl(
localClassContext.declaration.startOffset, localClassContext.declaration.endOffset, localClassContext.declaration.startOffset, localClassContext.declaration.endOffset,
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
fieldDescriptor fieldDescriptor, capturedValue.owner.type
).apply { ).apply {
parent = localClassContext.declaration parent = localClassContext.declaration
} }
@@ -776,3 +812,12 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
} }
} }
private fun IrValueDeclaration.copy(newDescriptor: ParameterDescriptor): IrValueParameter = IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
newDescriptor,
type,
(this as? IrValueParameter)?.varargElementType
)
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -60,7 +61,7 @@ abstract class AbstractVariableRemapper : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression = override fun visitGetValue(expression: IrGetValue): IrExpression =
remapVariable(expression.descriptor)?.let { remapVariable(expression.descriptor)?.let {
IrGetValueImpl(expression.startOffset, expression.endOffset, it.symbol, expression.origin) IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol, expression.origin)
} ?: expression } ?: expression
} }
@@ -84,7 +85,7 @@ fun <T : IrBuilder> T.at(element: IrElement) = this.at(element.startOffset, elem
*/ */
inline fun IrGeneratorWithScope.irBlock( inline fun IrGeneratorWithScope.irBlock(
expression: IrExpression, origin: IrStatementOrigin? = null, expression: IrExpression, origin: IrStatementOrigin? = null,
resultType: KotlinType? = expression.type, resultType: IrType? = expression.type,
body: IrBlockBuilder.() -> Unit body: IrBlockBuilder.() -> Unit
) = ) =
this.irBlock(expression.startOffset, expression.endOffset, origin, resultType, body) this.irBlock(expression.startOffset, expression.endOffset, origin, resultType, body)
@@ -93,13 +94,15 @@ inline fun IrGeneratorWithScope.irBlockBody(irElement: IrElement, body: IrBlockB
this.irBlockBody(irElement.startOffset, irElement.endOffset, body) this.irBlockBody(irElement.startOffset, irElement.endOffset, body)
fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) = fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) =
IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, thenPart, null) IrIfThenElseImpl(startOffset, endOffset, context.irBuiltIns.unitType).apply {
branches += IrBranchImpl(condition, thenPart)
}
fun IrBuilderWithScope.irNot(arg: IrExpression) = fun IrBuilderWithScope.irNot(arg: IrExpression) =
primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg) primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg)
fun IrBuilderWithScope.irThrow(arg: IrExpression) = fun IrBuilderWithScope.irThrow(arg: IrExpression) =
IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg) IrThrowImpl(startOffset, endOffset, context.irBuiltIns.nothingType, arg)
fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) = fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
IrCatchImpl( IrCatchImpl(
@@ -107,21 +110,12 @@ fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
catchParameter catchParameter
) )
fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) =
IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, typeOperand, arg)
fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) = fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) =
IrTypeOperatorCallImpl( IrTypeOperatorCallImpl(
startOffset, endOffset, context.builtIns.unitType, startOffset, endOffset, context.irBuiltIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.irBuiltIns.unitType, context.irBuiltIns.unitClass, arg
) )
fun IrBuilderWithScope.irGetField(receiver: IrExpression, symbol: IrFieldSymbol) =
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
fun IrBuilderWithScope.irSetField(receiver: IrExpression, symbol: IrFieldSymbol, value: IrExpression) =
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value)
open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() { open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() {
private var currentBuilder: IrBuilderWithScope? = null private var currentBuilder: IrBuilderWithScope? = null
@@ -27,10 +27,12 @@ import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irTemporary import org.jetbrains.kotlin.ir.builders.irTemporary
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrSymbolDeclaration import org.jetbrains.kotlin.ir.declarations.IrSymbolDeclaration
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -60,33 +62,33 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
private val nameToString = Name.identifier("toString") private val nameToString = Name.identifier("toString")
private val nameAppend = Name.identifier("append") private val nameAppend = Name.identifier("append")
private val stringBuilder = context.ir.symbols.stringBuilder private val stringBuilder = context.ir.symbols.stringBuilder.owner
//TODO: calculate and pass string length to the constructor. //TODO: calculate and pass string length to the constructor.
private val constructor = stringBuilder.constructors.single { private val constructor = stringBuilder.constructors.single {
it.owner.valueParameters.size == 0 it.valueParameters.size == 0
} }
private val toStringFunction = stringBuilder.functions.single { private val toStringFunction = stringBuilder.functions.single {
it.owner.valueParameters.size == 0 && it.descriptor.name == nameToString it.valueParameters.size == 0 && it.name == nameToString
} }
private val defaultAppendFunction = stringBuilder.functions.single { private val defaultAppendFunction = stringBuilder.functions.single {
it.descriptor.name == nameAppend && it.descriptor.name == nameAppend &&
it.owner.valueParameters.size == 1 && it.valueParameters.size == 1 &&
it.owner.valueParameters.single().type == builtIns.nullableAnyType it.valueParameters.single().type.isNullableAny()
} }
private val appendFunctions: Map<KotlinType, IrFunctionSymbol?> = private val appendFunctions: Map<KotlinType, IrSimpleFunction?> =
typesWithSpecialAppendFunction.map { type -> typesWithSpecialAppendFunction.map { type ->
type to stringBuilder.functions.toList().atMostOne { type to stringBuilder.functions.toList().atMostOne {
it.descriptor.name == nameAppend && it.descriptor.name == nameAppend &&
it.owner.valueParameters.size == 1 && it.valueParameters.size == 1 &&
it.owner.valueParameters.single().type == type it.valueParameters.single().type.toKotlinType() == type
} }
}.toMap() }.toMap()
private fun typeToAppendFunction(type: KotlinType): IrFunctionSymbol { private fun typeToAppendFunction(type: KotlinType): IrSimpleFunction {
return appendFunctions[type] ?: defaultAppendFunction return appendFunctions[type] ?: defaultAppendFunction
} }
@@ -96,9 +98,9 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val blockBuilder = buildersStack.last() val blockBuilder = buildersStack.last()
return blockBuilder.irBlock(expression) { return blockBuilder.irBlock(expression) {
val stringBuilderImpl = irTemporary(irCall(constructor)).symbol val stringBuilderImpl = irTemporary(irCall(constructor))
expression.arguments.forEach { arg -> expression.arguments.forEach { arg ->
val appendFunction = typeToAppendFunction(arg.type) val appendFunction = typeToAppendFunction(arg.type.toKotlinType())
+irCall(appendFunction).apply { +irCall(appendFunction).apply {
dispatchReceiver = irGet(stringBuilderImpl) dispatchReceiver = irGet(stringBuilderImpl)
putValueArgument(0, arg) putValueArgument(0, arg)
@@ -18,14 +18,12 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.util.explicitParameters import org.jetbrains.kotlin.ir.util.explicitParameters
import org.jetbrains.kotlin.ir.util.getArgumentsWithSymbols import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -55,7 +53,7 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
irFunction.body = builder.irBlockBody { irFunction.body = builder.irBlockBody {
// Define variables containing current values of parameters: // Define variables containing current values of parameters:
val parameterToVariable = parameters.associate { val parameterToVariable = parameters.associate {
it to irTemporaryVar(irGet(it), nameHint = it.suggestVariableName()).symbol it to irTemporaryVar(irGet(it), nameHint = it.symbol.suggestVariableName())
} }
// (these variables are to be updated on any tail call). // (these variables are to be updated on any tail call).
@@ -63,11 +61,11 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
val loop = this val loop = this
condition = irTrue() condition = irTrue()
body = irBlock(startOffset, endOffset, resultType = context.builtIns.unitType) { body = irBlock(startOffset, endOffset, resultType = context.irBuiltIns.unitType) {
// Read variables containing current values of parameters: // Read variables containing current values of parameters:
val parameterToNew = parameters.associate { val parameterToNew = parameters.associate {
val variable = parameterToVariable[it]!! val variable = parameterToVariable[it]!!
it to irTemporary(irGet(variable), nameHint = it.suggestVariableName()).symbol it to irTemporary(irGet(variable), nameHint = it.symbol.suggestVariableName())
} }
val transformer = BodyTransformer( val transformer = BodyTransformer(
@@ -89,8 +87,8 @@ private class BodyTransformer(
val builder: IrBuilderWithScope, val builder: IrBuilderWithScope,
val irFunction: IrFunction, val irFunction: IrFunction,
val loop: IrLoop, val loop: IrLoop,
val parameterToNew: Map<IrValueParameterSymbol, IrValueSymbol>, val parameterToNew: Map<IrValueParameter, IrValueDeclaration>,
val parameterToVariable: Map<IrValueParameterSymbol, IrVariableSymbol>, val parameterToVariable: Map<IrValueParameter, IrVariable>,
val tailRecursionCalls: Set<IrCall> val tailRecursionCalls: Set<IrCall>
) : IrElementTransformerVoid() { ) : IrElementTransformerVoid() {
@@ -98,7 +96,7 @@ private class BodyTransformer(
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val value = parameterToNew[expression.symbol] ?: return expression val value = parameterToNew[expression.symbol.owner] ?: return expression
return builder.at(expression).irGet(value) return builder.at(expression).irGet(value)
} }
@@ -113,7 +111,7 @@ private class BodyTransformer(
private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) { private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) {
// Get all specified arguments: // Get all specified arguments:
val parameterToArgument = expression.getArgumentsWithSymbols().map { (parameter, argument) -> val parameterToArgument = expression.getArgumentsWithIr().map { (parameter, argument) ->
parameter to argument parameter to argument
} }
@@ -122,7 +120,7 @@ private class BodyTransformer(
at(argument) at(argument)
// Note that argument can use values of parameters, so it is important that // Note that argument can use values of parameters, so it is important that
// references to parameters are mapped using `parameterToNew`, not `parameterToVariable`. // references to parameters are mapped using `parameterToNew`, not `parameterToVariable`.
+irSetVar(parameterToVariable[parameter]!!, argument) +irSetVar(parameterToVariable[parameter]!!.symbol, argument)
} }
val specifiedParameters = parameterToArgument.map { (parameter, _) -> parameter }.toSet() val specifiedParameters = parameterToArgument.map { (parameter, _) -> parameter }.toSet()
@@ -130,7 +128,7 @@ private class BodyTransformer(
// For each unspecified argument set the corresponding variable to default: // For each unspecified argument set the corresponding variable to default:
parameters.filter { it !in specifiedParameters }.forEach { parameter -> parameters.filter { it !in specifiedParameters }.forEach { parameter ->
val originalDefaultValue = parameter.owner.defaultValue?.expression ?: throw Error("no argument specified for $parameter") val originalDefaultValue = parameter.defaultValue?.expression ?: throw Error("no argument specified for $parameter")
// Copy default value, mapping parameters to variables containing freshly computed arguments: // Copy default value, mapping parameters to variables containing freshly computed arguments:
val defaultValue = originalDefaultValue val defaultValue = originalDefaultValue
@@ -140,15 +138,15 @@ private class BodyTransformer(
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val variableSymbol = parameterToVariable[expression.symbol] ?: return expression val variable = parameterToVariable[expression.symbol.owner] ?: return expression
return IrGetValueImpl( return IrGetValueImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset, variable.type,
variableSymbol, expression.origin variable.symbol, expression.origin
) )
} }
}, data = null) }, data = null)
+irSetVar(parameterToVariable[parameter]!!, defaultValue) +irSetVar(parameterToVariable[parameter]!!.symbol, defaultValue)
} }
// Jump to the entry: // Jump to the entry:
@@ -32,14 +32,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.getPropertyGetter
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -68,20 +64,25 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
element?.transformChildrenVoid(object: IrElementTransformerVoid() { element?.transformChildrenVoid(object: IrElementTransformerVoid() {
val transformer = this val transformer = this
private fun replaceEmptyParameterWithEmptyArray(expression: IrMemberAccessExpression) { private fun replaceEmptyParameterWithEmptyArray(expression: IrFunctionAccessExpression) {
log { "call of: ${expression.descriptor}" } log { "call of: ${expression.descriptor}" }
context.createIrBuilder(owner, expression.startOffset, expression.endOffset).apply { context.createIrBuilder(owner, expression.startOffset, expression.endOffset).apply {
expression.descriptor.valueParameters.forEach { expression.descriptor.valueParameters.forEach {
log { "varargElementType: ${it.varargElementType} expr: ${ir2string(expression.getValueArgument(it))}" } log { "varargElementType: ${it.varargElementType} expr: ${ir2string(expression.getValueArgument(it))}" }
} }
expression.descriptor.valueParameters.filter { it.varargElementType != null && expression.getValueArgument(it) == null }.forEach { expression.symbol.owner.valueParameters
expression.putValueArgument(it.index, .filter { it.varargElementType != null && expression.getValueArgument(it.index) == null }
IrVarargImpl(startOffset = startOffset, .forEach {
endOffset = endOffset, expression.putValueArgument(
type = it.type, it.index,
varargElementType = it.varargElementType!!) IrVarargImpl(
) startOffset = startOffset,
} endOffset = endOffset,
type = it.type,
varargElementType = it.varargElementType!!
)
)
}
} }
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
} }
@@ -99,28 +100,27 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
override fun visitVararg(expression: IrVararg): IrExpression { override fun visitVararg(expression: IrVararg): IrExpression {
expression.transformChildrenVoid(transformer) expression.transformChildrenVoid(transformer)
val hasSpreadElement = hasSpreadElement(expression) val hasSpreadElement = hasSpreadElement(expression)
if (!hasSpreadElement && expression.elements.all { it is IrConst<*> && KotlinBuiltIns.isString(it.type) }) { if (!hasSpreadElement && expression.elements.all { it is IrConst<*> && it.type.isString() }) {
log { "skipped vararg expression because it's string array literal" } log { "skipped vararg expression because it's string array literal" }
return expression return expression
} }
val irBuilder = context.createIrBuilder(owner, expression.startOffset, expression.endOffset) val irBuilder = context.createIrBuilder(owner, expression.startOffset, expression.endOffset)
irBuilder.run { irBuilder.run {
val type = expression.varargElementType val type = expression.varargElementType
log { "$expression: array type:$type, is array of primitives ${!KotlinBuiltIns.isArray(expression.type)}" } log { "$expression: array type:$type, is array of primitives ${!expression.type.isArray()}" }
val arrayHandle = arrayType(expression.type) val arrayHandle = arrayType(expression.type)
val arrayConstructor = arrayHandle.arraySymbol.constructors.find { it.owner.valueParameters.size == 1 }!! val arrayConstructor = arrayHandle.arraySymbol.owner.constructors.find { it.valueParameters.size == 1 }!!
val block = irBlock(arrayHandle.arraySymbol.owner.defaultType) val block = irBlock(expression.type)
val arrayConstructorCall = if (arrayConstructor.owner.typeParameters.isEmpty()) { val arrayConstructorCall = irCall(arrayConstructor)
irCall(arrayConstructor)
} else {
irCall(arrayConstructor, listOf(type))
}
if (arrayConstructor.typeParameters.isNotEmpty()) {
arrayConstructorCall.putTypeArgument(0, expression.varargElementType)
}
val vars = expression.elements.map { val vars = expression.elements.map {
val initVar = scope.createTemporaryVariable( val initVar = scope.createTemporaryVariable(
(it as? IrSpreadElement)?.expression ?: it as IrExpression, (it as? IrSpreadElement)?.expression ?: it as IrExpression,
"elem".synthesizedString, true) "elem".synthesizedString, true)
block.statements.add(initVar) block.statements.add(initVar)
it to initVar it to initVar
}.toMap() }.toMap()
@@ -138,32 +138,31 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
log { "element:$i> ${ir2string(element)}" } log { "element:$i> ${ir2string(element)}" }
val dst = vars[element]!! val dst = vars[element]!!
if (element !is IrSpreadElement) { if (element !is IrSpreadElement) {
val setArrayElementCall = irCall(arrayHandle.setMethodSymbol) val setArrayElementCall = irCall(arrayHandle.setMethodSymbol.owner)
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol) setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable)
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i)) setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable) else irConstInt(i))
setArrayElementCall.putValueArgument(1, irGet(dst.symbol)) setArrayElementCall.putValueArgument(1, irGet(dst))
block.statements.add(setArrayElementCall) block.statements.add(setArrayElementCall)
if (hasSpreadElement) { if (hasSpreadElement) {
block.statements.add(incrementVariable(indexTmpVariable.symbol, kIntOne)) block.statements.add(incrementVariable(indexTmpVariable, kIntOne))
} }
} else { } else {
val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString) val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst)), "length".synthesizedString)
block.statements.add(arraySizeVariable) block.statements.add(arraySizeVariable)
val copyCall = irCall(arrayHandle.copyRangeToSymbol).apply { val copyCall = irCall(arrayHandle.copyRangeToSymbol.owner).apply {
extensionReceiver = irGet(dst.symbol) extensionReceiver = irGet(dst)
putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */ putValueArgument(0, irGet(arrayTmpVariable)) /* destination */
putValueArgument(1, kIntZero) /* fromIndex */ putValueArgument(1, kIntZero) /* fromIndex */
putValueArgument(2, irGet(arraySizeVariable.symbol)) /* toIndex */ putValueArgument(2, irGet(arraySizeVariable)) /* toIndex */
putValueArgument(3, irGet(indexTmpVariable.symbol)) /* destinationIndex */ putValueArgument(3, irGet(indexTmpVariable)) /* destinationIndex */
} }
block.statements.add(copyCall) block.statements.add(copyCall)
block.statements.add(incrementVariable(indexTmpVariable.symbol, block.statements.add(incrementVariable(indexTmpVariable, irGet(arraySizeVariable)))
irGet(arraySizeVariable.symbol)))
log { "element:$i:spread element> ${ir2string(element.expression)}" } log { "element:$i:spread element> ${ir2string(element.expression)}" }
} }
} }
} }
block.statements.add(irGet(arrayTmpVariable.symbol)) block.statements.add(irGet(arrayTmpVariable))
return block return block
} }
} }
@@ -171,24 +170,21 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
} }
private val symbols = context.ir.symbols private val symbols = context.ir.symbols
private val intPlusInt = symbols.intPlusInt private val intPlusInt = symbols.intPlusInt.owner
private fun arrayType(type: KotlinType): ArrayHandle = when { private fun arrayType(type: IrType): ArrayHandle {
KotlinBuiltIns.isPrimitiveArray(type) -> { val primitiveType = KotlinBuiltIns.getPrimitiveArrayType(type.classifierOrFail.descriptor)
val primitiveType = KotlinBuiltIns.getPrimitiveArrayType(type.constructor.declarationDescriptor!!) return when (primitiveType) {
when (primitiveType) { PrimitiveType.BYTE -> kByteArrayHandler
PrimitiveType.BYTE -> kByteArrayHandler PrimitiveType.SHORT -> kShortArrayHandler
PrimitiveType.SHORT -> kShortArrayHandler PrimitiveType.CHAR -> kCharArrayHandler
PrimitiveType.CHAR -> kCharArrayHandler PrimitiveType.INT -> kIntArrayHandler
PrimitiveType.INT -> kIntArrayHandler PrimitiveType.LONG -> kLongArrayHandler
PrimitiveType.LONG -> kLongArrayHandler PrimitiveType.FLOAT -> kFloatArrayHandler
PrimitiveType.FLOAT -> kFloatArrayHandler PrimitiveType.DOUBLE -> kDoubleArrayHandler
PrimitiveType.DOUBLE -> kDoubleArrayHandler PrimitiveType.BOOLEAN -> kBooleanArrayHandler
PrimitiveType.BOOLEAN -> kBooleanArrayHandler else -> kArrayHandler
else -> TODO("unsupported type: $primitiveType")
}
} }
else -> kArrayHandler
} }
private fun IrBuilderWithScope.intPlus() = irCall(intPlusInt) private fun IrBuilderWithScope.intPlus() = irCall(intPlusInt)
@@ -199,9 +195,9 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
} }
} }
private fun IrBuilderWithScope.incrementVariable(symbol: IrVariableSymbol, value: IrExpression): IrExpression { private fun IrBuilderWithScope.incrementVariable(variable: IrVariable, value: IrExpression): IrExpression {
return irSetVar(symbol, intPlus().apply { return irSetVar(variable.symbol, intPlus().apply {
dispatchReceiver = irGet(symbol) dispatchReceiver = irGet(variable)
putValueArgument(0, value) putValueArgument(0, value)
}) })
} }
@@ -212,14 +208,14 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size
val initialValue = irConstInt(notSpreadElementCount) as IrExpression val initialValue = irConstInt(notSpreadElementCount) as IrExpression
return vars.filter{it.key is IrSpreadElement}.toList().fold( initial = initialValue) { result, it -> return vars.filter{it.key is IrSpreadElement}.toList().fold( initial = initialValue) { result, it ->
val arraySize = irArraySize(arrayHandle, irGet(it.second.symbol)) val arraySize = irArraySize(arrayHandle, irGet(it.second))
increment(result, arraySize) increment(result, arraySize)
} }
} }
} }
private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression { private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression {
val arraySize = irCall(arrayHandle.sizeGetterSymbol).apply { val arraySize = irCall(arrayHandle.sizeGetterSymbol.owner).apply {
dispatchReceiver = expression dispatchReceiver = expression
} }
return arraySize return arraySize
@@ -256,7 +252,8 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
} }
private fun IrBuilderWithScope.irConstInt(value: Int): IrConst<Int> = IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, value) private fun IrBuilderWithScope.irConstInt(value: Int): IrConst<Int> =
private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type) IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, value)
private fun IrBuilderWithScope.irBlock(type: IrType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
private val IrBuilderWithScope.kIntZero get() = irConstInt(0) private val IrBuilderWithScope.kIntZero get() = irConstInt(0)
private val IrBuilderWithScope.kIntOne get() = irConstInt(1) private val IrBuilderWithScope.kIntOne get() = irConstInt(1)
@@ -16,17 +16,11 @@
package org.jetbrains.kotlin.ir.builders package org.jetbrains.kotlin.ir.builders
import org.jetbrains.kotlin.backend.common.descriptors.substitute
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.types.KotlinType
fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) = fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) =
IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin) IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin)
@@ -37,18 +31,5 @@ fun IrBuilderWithScope.irBreak(loop: IrLoop) =
fun IrBuilderWithScope.irContinue(loop: IrLoop) = fun IrBuilderWithScope.irContinue(loop: IrLoop) =
IrContinueImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop) IrContinueImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
fun IrBuilderWithScope.irTrue() = IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType, true)
fun IrBuilderWithScope.irFalse() = IrConstImpl.boolean(startOffset, endOffset, context.irBuiltIns.booleanType, false)
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: Map<TypeParameterDescriptor, KotlinType>) =
IrCallImpl(this.startOffset, this.endOffset, symbol, symbol.descriptor.substitute(typeArguments), typeArguments)
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List<KotlinType>) =
irCall(symbol, symbol.descriptor.typeParameters.zip(typeArguments).toMap())
fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) = fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) =
IrGetObjectValueImpl(startOffset, endOffset, classSymbol.owner.defaultType, classSymbol) IrGetObjectValueImpl(startOffset, endOffset, IrSimpleTypeImpl(classSymbol, false, emptyList(), emptyList()), classSymbol)
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, symbol: IrFieldSymbol) =
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
@@ -9,6 +9,9 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
@@ -128,9 +131,14 @@ fun IrBuilderWithScope.irIfThenReturnFalse(condition: IrExpression) =
fun IrBuilderWithScope.irGet(type: IrType, variable: IrValueSymbol) = fun IrBuilderWithScope.irGet(type: IrType, variable: IrValueSymbol) =
IrGetValueImpl(startOffset, endOffset, type, variable) IrGetValueImpl(startOffset, endOffset, type, variable)
fun IrBuilderWithScope.irGet(variable: IrValueDeclaration) = irGet(variable.type, variable.symbol)
fun IrBuilderWithScope.irSetVar(variable: IrVariableSymbol, value: IrExpression) = fun IrBuilderWithScope.irSetVar(variable: IrVariableSymbol, value: IrExpression) =
IrSetVariableImpl(startOffset, endOffset, context.irBuiltIns.unitType, variable, value, IrStatementOrigin.EQ) IrSetVariableImpl(startOffset, endOffset, context.irBuiltIns.unitType, variable, value, IrStatementOrigin.EQ)
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, field: IrField) =
IrGetFieldImpl(startOffset, endOffset, field.symbol, field.type, receiver)
fun IrBuilderWithScope.irEqeqeq(arg1: IrExpression, arg2: IrExpression) = fun IrBuilderWithScope.irEqeqeq(arg1: IrExpression, arg2: IrExpression) =
context.eqeqeq(startOffset, endOffset, arg1, arg2) context.eqeqeq(startOffset, endOffset, arg1, arg2)
@@ -169,6 +177,9 @@ fun IrBuilderWithScope.irCall(callee: IrFunctionSymbol, type: IrType): IrCall =
fun IrBuilderWithScope.irCall(callee: IrFunctionSymbol, descriptor: FunctionDescriptor, type: IrType): IrCall = fun IrBuilderWithScope.irCall(callee: IrFunctionSymbol, descriptor: FunctionDescriptor, type: IrType): IrCall =
IrCallImpl(startOffset, endOffset, type, callee, descriptor) IrCallImpl(startOffset, endOffset, type, callee, descriptor)
fun IrBuilderWithScope.irCall(callee: IrFunction): IrCall =
irCall(callee.symbol, callee.descriptor, callee.returnType)
fun IrBuilderWithScope.irCallOp( fun IrBuilderWithScope.irCallOp(
callee: IrFunctionSymbol, callee: IrFunctionSymbol,
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -61,7 +62,7 @@ class Scope(val scopeOwnerSymbol: IrSymbol) {
isMutable: Boolean = false, isMutable: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE
): IrVariable { ): IrVariable {
val originalKotlinType = irExpression.type.originalKotlinType ?: throw AssertionError("No originalKotlinType for $irExpression") val originalKotlinType = irExpression.type.originalKotlinType ?: irExpression.type.toKotlinType()
return IrVariableImpl( return IrVariableImpl(
irExpression.startOffset, irExpression.endOffset, origin, irExpression.startOffset, irExpression.endOffset, origin,
createDescriptorForTemporaryVariable( createDescriptorForTemporaryVariable(
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2018 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.types
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName
private fun IrType.isBuiltInClassType(descriptorPredicate: (ClassDescriptor) -> Boolean, hasQuestionMark: Boolean): Boolean {
if (this !is IrSimpleType) return false
if (this.hasQuestionMark != hasQuestionMark) return false
val classSymbol = this.classifier as? IrClassSymbol ?: return false
return descriptorPredicate(classSymbol.descriptor)
}
private fun IrType.isNotNullClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = false)
private fun IrType.isNullableClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = true)
private fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean): Boolean {
if (this !is IrSimpleType) return false
if (this.hasQuestionMark != hasQuestionMark) return false
val classSymbol = this.classifier as? IrClassSymbol ?: return false
return classFqNameEquals(classSymbol.descriptor, fqName)
}
private fun classFqNameEquals(descriptor: ClassDescriptor, fqName: FqNameUnsafe): Boolean =
descriptor.name == fqName.shortName() && fqName == getFqName(descriptor)
fun IrType.isNullableAny(): Boolean = isBuiltInClassType(KotlinBuiltIns::isAny, hasQuestionMark = true)
fun IrType.isString(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.string)
fun IrType.isArray(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.array)
fun IrType.isNothing(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.nothing)
fun IrType.isPrimitiveType(): Boolean =
isBuiltInClassType(KotlinBuiltIns::isPrimitiveClass, hasQuestionMark = false)
fun IrType.isNullablePrimitiveType(): Boolean =
isBuiltInClassType(KotlinBuiltIns::isPrimitiveClass, hasQuestionMark = true)
fun IrType.isUnit() = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.unit)
fun IrType.isNullableUnit() = isNullableClassType(KotlinBuiltIns.FQ_NAMES.unit)
fun IrType.isUnitOrNullableUnit() = this.isUnit() || this.isNullableUnit()
fun IrType.isBoolean(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES._boolean)
fun IrType.isChar(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES._char)
fun IrType.isByte(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES._byte)
fun IrType.isShort(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES._short)
fun IrType.isInt(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES._int)
fun IrType.isLong(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES._long)
fun IrType.isFloat(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES._float)
fun IrType.isDouble(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES._double)
@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.ir.types package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -53,3 +54,19 @@ fun IrType.makeNullable() =
) )
else else
this this
fun IrType.toKotlinType(): KotlinType = when (this) {
is IrSimpleType -> {
val classifier = this.classifier.descriptor
val arguments = this.arguments.mapIndexed { index, it ->
when (it) {
is IrTypeProjection -> TypeProjectionImpl(it.variance, it.type.toKotlinType())
is IrStarProjection -> StarProjectionImpl((classifier as ClassDescriptor).declaredTypeParameters[index])
else -> error(it)
}
}
classifier.defaultType.replace(newArguments = arguments).makeNullableAsSpecified(this.hasQuestionMark)
}
else -> TODO(this.toString())
}
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
@@ -79,6 +80,36 @@ fun IrFunctionAccessExpression.getArgumentsWithSymbols(): List<Pair<IrValueParam
return res return res
} }
/**
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
* The arguments are to be evaluated in the same order as they appear in the resulting list.
*/
fun IrMemberAccessExpression.getArgumentsWithIr(): List<Pair<IrValueParameter, IrExpression>> {
val res = mutableListOf<Pair<IrValueParameter, IrExpression>>()
val irFunction = when (this) {
is IrFunctionAccessExpression -> this.symbol.owner
is IrFunctionReference -> this.symbol.owner
else -> error(this)
}
dispatchReceiver?.let {
res += (irFunction.dispatchReceiverParameter!! to it)
}
extensionReceiver?.let {
res += (irFunction.extensionReceiverParameter!! to it)
}
irFunction.valueParameters.forEachIndexed { index, it ->
val arg = getValueArgument(index)
if (arg != null) {
res += (it to arg)
}
}
return res
}
/** /**
* Sets arguments that are specified by given mapping of parameters. * Sets arguments that are specified by given mapping of parameters.
*/ */
@@ -203,14 +234,20 @@ val DeclarationDescriptorWithSource.endOffsetOrUndefined: Int get() = endOffset
val IrClassSymbol.functions: Sequence<IrSimpleFunctionSymbol> val IrClassSymbol.functions: Sequence<IrSimpleFunctionSymbol>
get() = this.owner.declarations.asSequence().filterIsInstance<IrSimpleFunction>().map { it.symbol } get() = this.owner.declarations.asSequence().filterIsInstance<IrSimpleFunction>().map { it.symbol }
val IrClass.functions: Sequence<IrSimpleFunction>
get() = this.declarations.asSequence().filterIsInstance<IrSimpleFunction>()
val IrClassSymbol.constructors: Sequence<IrConstructorSymbol> val IrClassSymbol.constructors: Sequence<IrConstructorSymbol>
get() = this.owner.declarations.asSequence().filterIsInstance<IrConstructor>().map { it.symbol } get() = this.owner.declarations.asSequence().filterIsInstance<IrConstructor>().map { it.symbol }
val IrFunction.explicitParameters: List<IrValueParameterSymbol> val IrClass.constructors: Sequence<IrConstructor>
get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol } get() = this.declarations.asSequence().filterIsInstance<IrConstructor>()
val IrClass.defaultType: KotlinType val IrFunction.explicitParameters: List<IrValueParameter>
get() = this.descriptor.defaultType get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters)
val IrClass.defaultType: IrType
get() = this.thisReceiver!!.type
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
@@ -263,3 +300,31 @@ fun IrAnnotationContainer.hasAnnotation(name: FqName) =
annotations.any { annotations.any {
it.symbol.owner.parentAsClass.descriptor.fqNameSafe == name it.symbol.owner.parentAsClass.descriptor.fqNameSafe == name
} }
fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter {
assert(this.descriptor.type == newDescriptor.type)
return IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
newDescriptor,
type,
varargElementType
)
}
fun IrFunction.createDispatchReceiverParameter() {
assert(this.dispatchReceiverParameter == null)
val descriptor = this.descriptor.dispatchReceiverParameter ?: return
this.dispatchReceiverParameter = IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
descriptor,
this.parentAsClass.defaultType,
null
).also { it.parent = this }
}