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.expressions.*
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.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.makeNullable
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) {
if (expectedType != type) {
reportError(this, "unexpected expression.type: expected $expectedType, got ${type}")
// TODO: compare IR types instead.
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_NOTNULL,
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
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrLoop
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.visitors.acceptVoid
@@ -41,8 +42,10 @@ fun <T : IrElement> T.deepCopyWithVariables(): T {
val symbolsRemapper = DeepCopySymbolRemapper(descriptorsRemapper)
acceptVoid(symbolsRemapper)
val typesRemapper = DeepCopyTypeRemapper(symbolsRemapper)
return this.transform(
object : DeepCopyIrTreeWithReturnableBlockSymbols(symbolsRemapper) {
object : DeepCopyIrTreeWithReturnableBlockSymbols(symbolsRemapper, typesRemapper) {
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
return irLoop
}
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.renderer.*
import org.jetbrains.kotlin.types.KotlinType
@@ -285,7 +286,7 @@ class DumpIrTreeWithDescriptorsVisitor(out: Appendable): IrElementVisitor<Unit,
for (typeParameter in expression.descriptor.original.typeParameters) {
val typeArgument = expression.getTypeArgument(typeParameter) ?: continue
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")
}
}
@@ -25,10 +25,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.SymbolRemapper
import org.jetbrains.kotlin.ir.util.TypeRemapper
open class DeepCopyIrTreeWithReturnableBlockSymbols(
private val symbolRemapper: SymbolRemapper
) : DeepCopyIrTreeWithSymbols(symbolRemapper) {
symbolRemapper: SymbolRemapper,
typeRemapper: TypeRemapper
) : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper) {
private inline fun <reified T : IrElement> T.transform() =
transform(this@DeepCopyIrTreeWithReturnableBlockSymbols, null) as T
@@ -16,7 +16,6 @@
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.descriptors.*
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.IrDeclarationOrigin
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.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.ir.util.defaultType
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(
superConstructorSymbol: IrConstructorSymbol,
constructorDescriptor: ClassConstructorDescriptor,
origin: IrDeclarationOrigin
)
: IrConstructor {
superConstructor: IrConstructor,
irBuiltIns: IrBuiltIns,
origin: IrDeclarationOrigin,
isPrimary: Boolean = false
): 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 ->
constructor.createParameterDeclarations()
assert(superConstructor.dispatchReceiverParameter == null) // Inner classes aren't supported.
constructor.valueParameters += valueParameters
constructor.returnType = this.defaultType
constructor.body = IrBlockBodyImpl(
startOffset, endOffset,
listOf(
IrDelegatingConstructorCallImpl(
startOffset, endOffset,
superConstructorSymbol, superConstructorSymbol.descriptor
).apply {
constructor.valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.symbol))
}
},
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol)
)
startOffset, endOffset,
listOf(
IrDelegatingConstructorCallImpl(
startOffset, endOffset, irBuiltIns.unitType,
superConstructor.symbol, superConstructor.descriptor
).apply {
constructor.valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol))
}
},
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol, irBuiltIns.unitType)
)
)
constructor.parent = this
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.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
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.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
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.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
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) :
DeclarationContainerLoweringPass {
@@ -82,34 +76,31 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" }
functionDescriptor.overriddenDescriptors.forEach { context.log { "DEFAULT-REPLACER: $it" } }
if (bodies.isNotEmpty()) {
val newIrFunction = functionDescriptor.generateDefaultsFunction(context)
val newIrFunction = irFunction.generateDefaultsFunction(context)
newIrFunction.parent = irFunction.parent
val descriptor = newIrFunction.descriptor
log { "$functionDescriptor -> $descriptor" }
val builder = context.createIrBuilder(newIrFunction.symbol)
newIrFunction.body = builder.irBlockBody(newIrFunction) {
val params = mutableListOf<IrVariableSymbol>()
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>()
val params = mutableListOf<IrVariable>()
val variables = mutableMapOf<ValueDescriptor, IrValueDeclaration>()
irFunction.dispatchReceiverParameter?.let {
variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!.symbol
variables[it.descriptor] = newIrFunction.dispatchReceiverParameter!!
}
if (descriptor.extensionReceiverParameter != null) {
variables[functionDescriptor.extensionReceiverParameter!!] =
newIrFunction.extensionReceiverParameter!!.symbol
newIrFunction.extensionReceiverParameter!!
}
for (valueParameter in functionDescriptor.valueParameters) {
val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol
val temporaryVariableSymbol =
IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor))
params.add(temporaryVariableSymbol)
variables.put(valueParameter, temporaryVariableSymbol)
if (valueParameter.hasDefaultValue()) {
val kIntAnd = symbols.intAnd
val parameter = newIrFunction.valueParameters[valueParameter.index]
val argument = if (valueParameter.hasDefaultValue()) {
val kIntAnd = symbols.intAnd.owner
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)))
}, irInt(0))
val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter)
@@ -122,41 +113,40 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
return irGet(valueSymbol)
}
})
val variableInitialization = irIfThenElse(
type = temporaryVariableSymbol.descriptor.type,
irIfThenElse(
type = parameter.type,
condition = condition,
thenPart = expressionBody.expression,
elsePart = irGet(parameterSymbol)
)
+scope.createTemporaryVariable(
symbol = temporaryVariableSymbol,
initializer = variableInitialization
elsePart = irGet(parameter)
)
/* Mapping calculated values with its origin variables. */
} else {
+scope.createTemporaryVariable(
symbol = temporaryVariableSymbol,
initializer = irGet(parameterSymbol)
)
irGet(parameter)
}
val temporaryVariable = irTemporary(argument, nameHint = parameter.name.asString())
params.add(temporaryVariable)
variables.put(valueParameter, temporaryVariable)
}
if (irFunction is IrConstructor) {
+IrDelegatingConstructorCallImpl(
startOffset = irFunction.startOffset,
endOffset = irFunction.endOffset,
type = context.irBuiltIns.unitType,
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor
).apply {
params.forEachIndexed { i, variable ->
putValueArgument(i, irGet(variable))
}
if (functionDescriptor.dispatchReceiverParameter != null) {
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!)
}
}
} else {
+irReturn(irCall(irFunction.symbol).apply {
+irReturn(irCall(irFunction).apply {
if (functionDescriptor.dispatchReceiverParameter != null) {
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!)
}
if (functionDescriptor.extensionReceiverParameter != null) {
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 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 {
return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!")
}
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) =
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol
private fun maskParameter(function: IrFunction, number: Int) =
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }
private fun markerParameterDescriptor(descriptor: FunctionDescriptor) =
descriptor.valueParameters.single { it.name == kConstructorMarkerName }
private fun nullConst(expression: IrElement, type: KotlinType): IrExpression? {
when {
KotlinBuiltIns.isFloat(type) -> return IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
KotlinBuiltIns.isDouble(type) -> return IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
KotlinBuiltIns.isBoolean(type) -> return IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
KotlinBuiltIns.isByte(type) -> return IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isChar(type) -> return IrConstImpl.char(expression.startOffset, expression.endOffset, type, 0.toChar())
KotlinBuiltIns.isShort(type) -> return IrConstImpl.short(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isInt(type) -> return IrConstImpl.int(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isLong(type) -> return IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0)
else -> return IrConstImpl.constNull(expression.startOffset, expression.endOffset, type.builtIns.nullableNothingType)
}
private fun nullConst(expression: IrElement, type: IrType, context: CommonBackendContext) = when {
type.isFloat() -> IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
type.isDouble() -> IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
type.isBoolean() -> IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
type.isByte() -> IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0)
type.isChar() -> IrConstImpl.char(expression.startOffset, expression.endOffset, type, 0.toChar())
type.isShort() -> IrConstImpl.short(expression.startOffset, expression.endOffset, type, 0)
type.isInt() -> IrConstImpl.int(expression.startOffset, expression.endOffset, type, 0)
type.isLong() -> IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0)
else -> IrConstImpl.constNull(expression.startOffset, expression.endOffset, context.irBuiltIns.nothingNType)
}
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)
return expression
val (symbolForCall, params) = parametersForCall(expression)
symbolForCall as IrConstructorSymbol
return IrDelegatingConstructorCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
symbol = symbolForCall as IrConstructorSymbol,
type = context.irBuiltIns.unitType,
symbol = symbolForCall,
descriptor = symbolForCall.descriptor
)
.apply {
@@ -273,13 +244,14 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
return IrCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = symbol.owner.returnType,
symbol = symbol,
descriptor = descriptor,
typeArguments = expression.descriptor.typeParameters.map {
it to (expression.getTypeArgument(it) ?: it.defaultType)
}.toMap()
typeArgumentsCount = expression.typeArgumentsCount
)
.apply {
this.copyTypeArgumentsFrom(expression)
params.forEach {
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(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?>>> {
val descriptor = expression.descriptor
val keyFunction = expression.symbol.owner.findSuperMethodWithDefaultArguments()!!
val keyDescriptor = keyFunction.descriptor
val realFunction = keyDescriptor.generateDefaultsFunction(context)
val realFunction = keyFunction.generateDefaultsFunction(context)
realFunction.parent = keyFunction.parent
val realDescriptor = realFunction.descriptor
@@ -325,15 +296,18 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
maskValues[maskIndex] = maskValues[maskIndex] or (1 shl (i % 32))
}
val valueParameterDescriptor = realDescriptor.valueParameters[i]
val defaultValueArgument =
if (valueParameterDescriptor.isVararg) null else nullConst(expression, valueParameterDescriptor.type)
val defaultValueArgument = if (valueParameterDescriptor.isVararg) {
null
} else {
nullConst(expression, realFunction.valueParameters[i].type, context)
}
valueParameterDescriptor to (valueArgument ?: defaultValueArgument)
})
maskValues.forEachIndexed { i, maskValue ->
params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int(
startOffset = irBody.startOffset,
endOffset = irBody.endOffset,
type = descriptor.builtIns.intType,
type = context.irBuiltIns.intType,
value = maskValue
)
}
@@ -347,7 +321,7 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
)
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
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 {
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) =
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) {
val descriptor = when (this) {
is ClassConstructorDescriptor ->
@@ -389,8 +363,10 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
}
}
val function = this@generateDefaultsFunction
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) {
syntheticParameters += valueParameter(
@@ -402,10 +378,29 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
syntheticParameters += valueParameter(
descriptor, syntheticParameters.last().index + 1,
"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(
/* receiverParameterType = */ extensionReceiverParameter?.type,
/* dispatchReceiverParameter = */ dispatchReceiverParameter,
@@ -425,24 +420,11 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
setInitialized()
}
},
/* unsubstitutedValueParameters = */ valueParameters.map {
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,
/* unsubstitutedValueParameters = */ newValueParameters.map { it.descriptor as ValueParameterDescriptor },
/* unsubstitutedReturnType = */ returnType,
/* modality = */ Modality.FINAL,
/* visibility = */ this.visibility)
/* visibility = */ this.visibility
)
descriptor.isSuspend = this.isSuspend
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
}
@@ -472,20 +476,28 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER :
IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT")
private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType): ValueParameterDescriptor {
return ValueParameterDescriptorImpl(
private fun IrFunction.valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: IrType): IrValueParameter {
val parameterDescriptor = ValueParameterDescriptorImpl(
containingDeclaration = descriptor,
original = null,
index = index,
annotations = Annotations.EMPTY,
name = name,
outType = type,
outType = type.toKotlinType(),
declaresDefaultValue = false,
isCrossinline = false,
isNoinline = false,
varargElementType = null,
source = SourceElement.NO_SOURCE
)
return IrValueParameterImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
parameterDescriptor,
type,
null
)
}
internal val kConstructorMarkerName = "marker".synthesizedName
@@ -68,7 +68,7 @@ class InitializersLowering(
if (declaration.descriptor.dispatchReceiverParameter != null) // TODO isStaticField
IrGetValueImpl(
irFieldInitializer.startOffset, irFieldInitializer.endOffset,
irClass.thisReceiver!!.symbol
irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol
)
else null
val irSetField = IrSetFieldImpl(
@@ -76,6 +76,7 @@ class InitializersLowering(
declaration.symbol,
receiver,
irFieldInitializer,
context.irBuiltIns.unitType,
null, null
)
@@ -93,7 +94,7 @@ class InitializersLowering(
fun transformInstanceInitializerCallsInConstructors(irClass: IrClass) {
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
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) })
}
})
@@ -16,26 +16,8 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
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.declarations.IrDeclaration
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> {
@@ -62,155 +44,3 @@ abstract class SymbolWithIrBuilder<out S: IrSymbol, out D: IrDeclaration> {
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 {
IrCompositeImpl(startOffset, endOffset, context.builtIns.stringType).apply {
IrCompositeImpl(startOffset, endOffset, context.irBuiltIns.stringType).apply {
receiver?.let {
//put receiver for bound callable reference
statements.add(it)
@@ -68,7 +68,7 @@ private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyL
IrConstImpl.string(
expression.startOffset,
expression.endOffset,
context.builtIns.stringType,
context.irBuiltIns.stringType,
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.IrConstImpl
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.transformChildrenVoid
import org.jetbrains.kotlin.types.KotlinType
@@ -45,20 +47,20 @@ class LateinitLowering(
private fun transformGetter(backingField: IrField, getter: IrFunction) {
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 endOffset = getter.endOffset
val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset)
irBuilder.run {
val block = irBlock(type)
val resultVar = scope.createTemporaryVariable(
irGetField(getter.dispatchReceiverParameter?.let { irGet(it.symbol) }, backingField.symbol)
irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField)
)
block.statements.add(resultVar)
val throwIfNull = irIfThenElse(
context.builtIns.nothingType,
irNotEquals(irGet(resultVar.symbol), irNull()),
irReturn(irGet(resultVar.symbol)),
context.irBuiltIns.nothingType,
irNotEquals(irGet(resultVar), irNull()),
irReturn(irGet(resultVar)),
throwUninitializedPropertyAccessException(backingField)
)
block.statements.add(throwIfNull)
@@ -76,15 +78,15 @@ class LateinitLowering(
IrConstImpl.string(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
context.builtIns.stringType,
context.irBuiltIns.stringType,
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.resolve.descriptorUtil.parents
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
interface LocalNameProvider {
@@ -98,12 +97,12 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
abstract val transformedDescriptor: FunctionDescriptor
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? {
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? {
val field = capturedValueToField[descriptor] ?: return null
val receiver = declaration.thisReceiver!!
return IrGetFieldImpl(
startOffset, endOffset, field.symbol,
receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol)
startOffset, endOffset, field.symbol, field.type,
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? {
val field = classContext.capturedValueToField[descriptor] ?: return null
val receiver = member.dispatchReceiverParameter!!
return IrGetFieldImpl(
startOffset, endOffset, field.symbol,
receiver = IrGetValueImpl(startOffset, endOffset, member.dispatchReceiverParameter!!.symbol)
startOffset, endOffset, field.symbol, field.type,
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 localClassConstructors: MutableMap<ClassConstructorDescriptor, LocalClassConstructorContext> = LinkedHashMap()
val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrDeclaration>()
val FunctionDescriptor.transformed: IrFunctionSymbol?
get() = transformedDeclarations[this] as IrFunctionSymbol?
val FunctionDescriptor.transformed: IrFunction?
get() = transformedDeclarations[this] as IrFunction?
val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameterSymbol> = HashMap()
val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameter> = HashMap()
val newParameterToOld: MutableMap<ParameterDescriptor, ParameterDescriptor> = 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 ->
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 {
if (declaration.descriptor in localClasses) {
// 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 {
return super.visitClass(declaration)
}
@@ -227,7 +228,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun visitFunction(declaration: IrFunction): IrStatement {
if (declaration.descriptor in localFunctions) {
// 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 {
if (localContext is LocalClassContext && declaration.parent == localContext.declaration) {
return declaration.apply {
@@ -250,7 +251,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
val body = declaration.getDefault(argument)!!
oldParameterToNew[argument]!!.owner.defaultValue = body
oldParameterToNew[argument]!!.defaultValue = body
}
}
} else {
@@ -266,7 +267,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
}
oldParameterToNew[descriptor]?.let {
return IrGetValueImpl(expression.startOffset, expression.endOffset, it)
return IrGetValueImpl(expression.startOffset, expression.endOffset, it.type, it.symbol)
}
return expression
@@ -287,14 +288,17 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
expression.transformChildrenVoid(this)
val oldCallee = expression.descriptor.original
val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression
val newCallee = transformedDeclarations[oldCallee] as IrConstructor? ?: return expression
return IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset,
newCallee,
newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor)
).fillArguments(expression)
context.irBuiltIns.unitType,
newCallee.symbol,
newCallee.descriptor
).also {
it.fillArguments(expression)
it.copyTypeArgumentsFrom(expression)
}
}
private fun <T : IrMemberAccessExpression> T.fillArguments(oldExpression: IrMemberAccessExpression): T {
@@ -310,16 +314,17 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
newParameterToCaptured[newValueParameterDescriptor]
?: throw AssertionError("Non-mapped parameter $newValueParameterDescriptor")
val capturedValue = capturedValueSymbol.owner
val capturedValueDescriptor = capturedValueSymbol.descriptor
localContext?.irGet(
oldExpression.startOffset, oldExpression.endOffset,
capturedValueDescriptor
) ?:
// Captured value is directly available for the caller.
IrGetValueImpl(
oldExpression.startOffset, oldExpression.endOffset,
oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol
)
) ?: run {
// Captured value is directly available for the caller.
val value = oldParameterToNew[capturedValueDescriptor] ?: capturedValue
IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, value.type, value.symbol)
}
}
}
@@ -339,11 +344,14 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newCallableReference = IrFunctionReferenceImpl(
expression.startOffset, expression.endOffset,
expression.type, // TODO functional type for transformed descriptor
newCallee,
newCallee.symbol,
newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor),
expression.typeArgumentsCount,
expression.origin
).fillArguments(expression)
).also {
it.fillArguments(expression)
it.copyTypeArgumentsFrom(expression)
}
return newCallableReference
}
@@ -354,7 +362,11 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val oldReturnTarget = expression.returnTarget
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 {
@@ -398,8 +410,10 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
0,
IrSetFieldImpl(
startOffset, endOffset, field.symbol,
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.type, irClass.thisReceiver!!.symbol),
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)
}
private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) =
private fun createNewCall(oldCall: IrCall, newCallee: IrFunction) =
if (oldCall is IrCallWithShallowCopy)
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol)
oldCall.shallowCopy(oldCall.origin, newCallee.symbol, oldCall.superQualifierSymbol)
else
IrCallImpl(
oldCall.startOffset, oldCall.endOffset,
newCallee,
newCallee.returnType,
newCallee.symbol,
newCallee.descriptor,
remapTypeArguments(oldCall, newCallee.descriptor),
oldCall.origin, oldCall.superQualifierSymbol
)
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) }
)
}
).also {
it.copyTypeArgumentsFrom(oldCall)
}
private fun transformDescriptors() {
localFunctions.values.forEach {
@@ -519,7 +521,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
oldDescriptor.extensionReceiverParameter?.type,
newDispatchReceiverParameter,
newTypeParameters,
newValueParameters,
newValueParameters.map { it.descriptor as ValueParameterDescriptor },
oldDescriptor.returnType,
Modality.FINAL,
Visibilities.PRIVATE
@@ -533,9 +535,26 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
IrFunctionImpl(startOffset, endOffset, origin, newDescriptor)
}.apply {
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)
transformedDeclarations[oldDescriptor] = this.symbol
transformedDeclarations[oldDescriptor] = this
}
}
@@ -543,7 +562,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
localContext: LocalContextWithClosureAsParameters,
capturedValues: List<IrValueSymbol>
)
: List<ValueParameterDescriptor> {
: List<IrValueParameter> {
val oldDescriptor = localContext.descriptor
val newDescriptor = localContext.transformedDescriptor
@@ -551,17 +570,23 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val closureParametersCount = capturedValues.size
val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size
val newValueParameters = ArrayList<ValueParameterDescriptor>(newValueParametersCount).apply {
val newValueParameters = ArrayList<IrValueParameter>(newValueParametersCount).apply {
capturedValues.mapIndexedTo(this) { i, capturedValue ->
createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply {
val parameterDescriptor = createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply {
newParameterToCaptured[this] = capturedValue
}
capturedValue.owner.copy(parameterDescriptor)
}
oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor ->
createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply {
newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor)
localContext.declaration.valueParameters.mapIndexedTo(this) { i, oldValueParameter ->
val parameterDescriptor = createUnsubstitutedParameter(
newDescriptor,
oldValueParameter.descriptor as ValueParameterDescriptor,
closureParametersCount + i
).apply {
newParameterToOld.putAbsentOrSame(this, oldValueParameter.descriptor)
}
oldValueParameter.copy(parameterDescriptor)
}
}
return newValueParameters
@@ -572,14 +597,14 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
valueParameters.forEach {
val capturedValue = newParameterToCaptured[it.descriptor]
if (capturedValue != null) {
localContext.capturedValueToParameter[capturedValue.descriptor] = it.symbol
localContext.capturedValueToParameter[capturedValue.descriptor] = it
}
}
(listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach {
val oldParameter = newParameterToOld[it.descriptor]
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)
newDescriptor.initialize(
newValueParameters,
newValueParameters.map { it.descriptor as ValueParameterDescriptor },
Visibilities.PRIVATE,
newTypeParameters
)
@@ -618,12 +643,23 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
}
constructorContext.transformedDeclaration = with(constructorContext.declaration) {
IrConstructorImpl(startOffset, endOffset, origin, newDescriptor)
IrConstructorImpl(startOffset, endOffset, origin, newDescriptor).also { it.returnType = returnType }
}.apply {
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)
transformedDeclarations[oldDescriptor] = this.symbol
transformedDeclarations[oldDescriptor] = this
}
}
@@ -662,7 +698,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl(
localClassContext.declaration.startOffset, localClassContext.declaration.endOffset,
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
fieldDescriptor
fieldDescriptor, capturedValue.owner.type
).apply {
parent = localClassContext.declaration
}
@@ -775,4 +811,13 @@ 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.symbols.IrFieldSymbol
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.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -60,7 +61,7 @@ abstract class AbstractVariableRemapper : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression =
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
}
@@ -84,7 +85,7 @@ fun <T : IrBuilder> T.at(element: IrElement) = this.at(element.startOffset, elem
*/
inline fun IrGeneratorWithScope.irBlock(
expression: IrExpression, origin: IrStatementOrigin? = null,
resultType: KotlinType? = expression.type,
resultType: IrType? = expression.type,
body: IrBlockBuilder.() -> Unit
) =
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)
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) =
primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg)
fun IrBuilderWithScope.irThrow(arg: IrExpression) =
IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg)
IrThrowImpl(startOffset, endOffset, context.irBuiltIns.nothingType, arg)
fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
IrCatchImpl(
@@ -107,21 +110,12 @@ fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
catchParameter
)
fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) =
IrTypeOperatorCallImpl(startOffset, endOffset, type, IrTypeOperator.CAST, typeOperand, arg)
fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) =
IrTypeOperatorCallImpl(
startOffset, endOffset, context.builtIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg
startOffset, endOffset, context.irBuiltIns.unitType,
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() {
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.declarations.IrDeclaration
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.expressions.IrExpression
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.functions
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 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.
private val constructor = stringBuilder.constructors.single {
it.owner.valueParameters.size == 0
it.valueParameters.size == 0
}
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 {
it.descriptor.name == nameAppend &&
it.owner.valueParameters.size == 1 &&
it.owner.valueParameters.single().type == builtIns.nullableAnyType
it.valueParameters.size == 1 &&
it.valueParameters.single().type.isNullableAny()
}
private val appendFunctions: Map<KotlinType, IrFunctionSymbol?> =
private val appendFunctions: Map<KotlinType, IrSimpleFunction?> =
typesWithSpecialAppendFunction.map { type ->
type to stringBuilder.functions.toList().atMostOne {
it.descriptor.name == nameAppend &&
it.owner.valueParameters.size == 1 &&
it.owner.valueParameters.single().type == type
it.valueParameters.size == 1 &&
it.valueParameters.single().type.toKotlinType() == type
}
}.toMap()
private fun typeToAppendFunction(type: KotlinType): IrFunctionSymbol {
private fun typeToAppendFunction(type: KotlinType): IrSimpleFunction {
return appendFunctions[type] ?: defaultAppendFunction
}
@@ -96,9 +98,9 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
expression.transformChildrenVoid(this)
val blockBuilder = buildersStack.last()
return blockBuilder.irBlock(expression) {
val stringBuilderImpl = irTemporary(irCall(constructor)).symbol
val stringBuilderImpl = irTemporary(irCall(constructor))
expression.arguments.forEach { arg ->
val appendFunction = typeToAppendFunction(arg.type)
val appendFunction = typeToAppendFunction(arg.type.toKotlinType())
+irCall(appendFunction).apply {
dispatchReceiver = irGet(stringBuilderImpl)
putValueArgument(0, arg)
@@ -18,14 +18,12 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.*
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.impl.IrGetValueImpl
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.getArgumentsWithSymbols
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -55,7 +53,7 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
irFunction.body = builder.irBlockBody {
// Define variables containing current values of parameters:
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).
@@ -63,11 +61,11 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
val loop = this
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:
val parameterToNew = parameters.associate {
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(
@@ -89,8 +87,8 @@ private class BodyTransformer(
val builder: IrBuilderWithScope,
val irFunction: IrFunction,
val loop: IrLoop,
val parameterToNew: Map<IrValueParameterSymbol, IrValueSymbol>,
val parameterToVariable: Map<IrValueParameterSymbol, IrVariableSymbol>,
val parameterToNew: Map<IrValueParameter, IrValueDeclaration>,
val parameterToVariable: Map<IrValueParameter, IrVariable>,
val tailRecursionCalls: Set<IrCall>
) : IrElementTransformerVoid() {
@@ -98,7 +96,7 @@ private class BodyTransformer(
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
val value = parameterToNew[expression.symbol] ?: return expression
val value = parameterToNew[expression.symbol.owner] ?: return expression
return builder.at(expression).irGet(value)
}
@@ -113,7 +111,7 @@ private class BodyTransformer(
private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) {
// Get all specified arguments:
val parameterToArgument = expression.getArgumentsWithSymbols().map { (parameter, argument) ->
val parameterToArgument = expression.getArgumentsWithIr().map { (parameter, argument) ->
parameter to argument
}
@@ -122,7 +120,7 @@ private class BodyTransformer(
at(argument)
// Note that argument can use values of parameters, so it is important that
// 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()
@@ -130,7 +128,7 @@ private class BodyTransformer(
// For each unspecified argument set the corresponding variable to default:
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:
val defaultValue = originalDefaultValue
@@ -140,15 +138,15 @@ private class BodyTransformer(
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
val variableSymbol = parameterToVariable[expression.symbol] ?: return expression
val variable = parameterToVariable[expression.symbol.owner] ?: return expression
return IrGetValueImpl(
expression.startOffset, expression.endOffset,
variableSymbol, expression.origin
expression.startOffset, expression.endOffset, variable.type,
variable.symbol, expression.origin
)
}
}, data = null)
+irSetVar(parameterToVariable[parameter]!!, defaultValue)
+irSetVar(parameterToVariable[parameter]!!.symbol, defaultValue)
}
// 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.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.util.constructors
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.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -68,20 +64,25 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
element?.transformChildrenVoid(object: IrElementTransformerVoid() {
val transformer = this
private fun replaceEmptyParameterWithEmptyArray(expression: IrMemberAccessExpression) {
private fun replaceEmptyParameterWithEmptyArray(expression: IrFunctionAccessExpression) {
log { "call of: ${expression.descriptor}" }
context.createIrBuilder(owner, expression.startOffset, expression.endOffset).apply {
expression.descriptor.valueParameters.forEach {
log { "varargElementType: ${it.varargElementType} expr: ${ir2string(expression.getValueArgument(it))}" }
}
expression.descriptor.valueParameters.filter { it.varargElementType != null && expression.getValueArgument(it) == null }.forEach {
expression.putValueArgument(it.index,
IrVarargImpl(startOffset = startOffset,
endOffset = endOffset,
type = it.type,
varargElementType = it.varargElementType!!)
)
}
expression.symbol.owner.valueParameters
.filter { it.varargElementType != null && expression.getValueArgument(it.index) == null }
.forEach {
expression.putValueArgument(
it.index,
IrVarargImpl(
startOffset = startOffset,
endOffset = endOffset,
type = it.type,
varargElementType = it.varargElementType!!
)
)
}
}
expression.transformChildrenVoid(this)
}
@@ -99,28 +100,27 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
override fun visitVararg(expression: IrVararg): IrExpression {
expression.transformChildrenVoid(transformer)
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" }
return expression
}
val irBuilder = context.createIrBuilder(owner, expression.startOffset, expression.endOffset)
irBuilder.run {
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 arrayConstructor = arrayHandle.arraySymbol.constructors.find { it.owner.valueParameters.size == 1 }!!
val block = irBlock(arrayHandle.arraySymbol.owner.defaultType)
val arrayConstructorCall = if (arrayConstructor.owner.typeParameters.isEmpty()) {
irCall(arrayConstructor)
} else {
irCall(arrayConstructor, listOf(type))
}
val arrayConstructor = arrayHandle.arraySymbol.owner.constructors.find { it.valueParameters.size == 1 }!!
val block = irBlock(expression.type)
val arrayConstructorCall = irCall(arrayConstructor)
if (arrayConstructor.typeParameters.isNotEmpty()) {
arrayConstructorCall.putTypeArgument(0, expression.varargElementType)
}
val vars = expression.elements.map {
val initVar = scope.createTemporaryVariable(
(it as? IrSpreadElement)?.expression ?: it as IrExpression,
"elem".synthesizedString, true)
(it as? IrSpreadElement)?.expression ?: it as IrExpression,
"elem".synthesizedString, true)
block.statements.add(initVar)
it to initVar
}.toMap()
@@ -138,32 +138,31 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
log { "element:$i> ${ir2string(element)}" }
val dst = vars[element]!!
if (element !is IrSpreadElement) {
val setArrayElementCall = irCall(arrayHandle.setMethodSymbol)
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol)
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i))
setArrayElementCall.putValueArgument(1, irGet(dst.symbol))
val setArrayElementCall = irCall(arrayHandle.setMethodSymbol.owner)
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable)
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable) else irConstInt(i))
setArrayElementCall.putValueArgument(1, irGet(dst))
block.statements.add(setArrayElementCall)
if (hasSpreadElement) {
block.statements.add(incrementVariable(indexTmpVariable.symbol, kIntOne))
block.statements.add(incrementVariable(indexTmpVariable, kIntOne))
}
} 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)
val copyCall = irCall(arrayHandle.copyRangeToSymbol).apply {
extensionReceiver = irGet(dst.symbol)
putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */
val copyCall = irCall(arrayHandle.copyRangeToSymbol.owner).apply {
extensionReceiver = irGet(dst)
putValueArgument(0, irGet(arrayTmpVariable)) /* destination */
putValueArgument(1, kIntZero) /* fromIndex */
putValueArgument(2, irGet(arraySizeVariable.symbol)) /* toIndex */
putValueArgument(3, irGet(indexTmpVariable.symbol)) /* destinationIndex */
putValueArgument(2, irGet(arraySizeVariable)) /* toIndex */
putValueArgument(3, irGet(indexTmpVariable)) /* destinationIndex */
}
block.statements.add(copyCall)
block.statements.add(incrementVariable(indexTmpVariable.symbol,
irGet(arraySizeVariable.symbol)))
block.statements.add(incrementVariable(indexTmpVariable, irGet(arraySizeVariable)))
log { "element:$i:spread element> ${ir2string(element.expression)}" }
}
}
}
block.statements.add(irGet(arrayTmpVariable.symbol))
block.statements.add(irGet(arrayTmpVariable))
return block
}
}
@@ -171,24 +170,21 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
}
private val symbols = context.ir.symbols
private val intPlusInt = symbols.intPlusInt
private val intPlusInt = symbols.intPlusInt.owner
private fun arrayType(type: KotlinType): ArrayHandle = when {
KotlinBuiltIns.isPrimitiveArray(type) -> {
val primitiveType = KotlinBuiltIns.getPrimitiveArrayType(type.constructor.declarationDescriptor!!)
when (primitiveType) {
PrimitiveType.BYTE -> kByteArrayHandler
PrimitiveType.SHORT -> kShortArrayHandler
PrimitiveType.CHAR -> kCharArrayHandler
PrimitiveType.INT -> kIntArrayHandler
PrimitiveType.LONG -> kLongArrayHandler
PrimitiveType.FLOAT -> kFloatArrayHandler
PrimitiveType.DOUBLE -> kDoubleArrayHandler
PrimitiveType.BOOLEAN -> kBooleanArrayHandler
else -> TODO("unsupported type: $primitiveType")
}
private fun arrayType(type: IrType): ArrayHandle {
val primitiveType = KotlinBuiltIns.getPrimitiveArrayType(type.classifierOrFail.descriptor)
return when (primitiveType) {
PrimitiveType.BYTE -> kByteArrayHandler
PrimitiveType.SHORT -> kShortArrayHandler
PrimitiveType.CHAR -> kCharArrayHandler
PrimitiveType.INT -> kIntArrayHandler
PrimitiveType.LONG -> kLongArrayHandler
PrimitiveType.FLOAT -> kFloatArrayHandler
PrimitiveType.DOUBLE -> kDoubleArrayHandler
PrimitiveType.BOOLEAN -> kBooleanArrayHandler
else -> kArrayHandler
}
else -> kArrayHandler
}
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 {
return irSetVar(symbol, intPlus().apply {
dispatchReceiver = irGet(symbol)
private fun IrBuilderWithScope.incrementVariable(variable: IrVariable, value: IrExpression): IrExpression {
return irSetVar(variable.symbol, intPlus().apply {
dispatchReceiver = irGet(variable)
putValueArgument(0, value)
})
}
@@ -212,14 +208,14 @@ class VarargInjectionLowering constructor(val context: CommonBackendContext): De
val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size
val initialValue = irConstInt(notSpreadElementCount) as IrExpression
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)
}
}
}
private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression {
val arraySize = irCall(arrayHandle.sizeGetterSymbol).apply {
val arraySize = irCall(arrayHandle.sizeGetterSymbol.owner).apply {
dispatchReceiver = expression
}
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.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
private fun IrBuilderWithScope.irConstInt(value: Int): IrConst<Int> =
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.kIntOne get() = irConstInt(1)
@@ -16,17 +16,11 @@
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.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) =
IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin)
@@ -37,18 +31,5 @@ fun IrBuilderWithScope.irBreak(loop: IrLoop) =
fun IrBuilderWithScope.irContinue(loop: IrLoop) =
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) =
IrGetObjectValueImpl(startOffset, endOffset, classSymbol.owner.defaultType, classSymbol)
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, symbol: IrFieldSymbol) =
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
IrGetObjectValueImpl(startOffset, endOffset, IrSimpleTypeImpl(classSymbol, false, emptyList(), emptyList()), classSymbol)
@@ -9,6 +9,9 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
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.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
@@ -128,9 +131,14 @@ fun IrBuilderWithScope.irIfThenReturnFalse(condition: IrExpression) =
fun IrBuilderWithScope.irGet(type: IrType, variable: IrValueSymbol) =
IrGetValueImpl(startOffset, endOffset, type, variable)
fun IrBuilderWithScope.irGet(variable: IrValueDeclaration) = irGet(variable.type, variable.symbol)
fun IrBuilderWithScope.irSetVar(variable: IrVariableSymbol, value: IrExpression) =
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) =
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 =
IrCallImpl(startOffset, endOffset, type, callee, descriptor)
fun IrBuilderWithScope.irCall(callee: IrFunction): IrCall =
irCall(callee.symbol, callee.descriptor, callee.returnType)
fun IrBuilderWithScope.irCallOp(
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.createFunctionSymbol
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.types.KotlinType
@@ -61,7 +62,7 @@ class Scope(val scopeOwnerSymbol: IrSymbol) {
isMutable: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE
): IrVariable {
val originalKotlinType = irExpression.type.originalKotlinType ?: throw AssertionError("No originalKotlinType for $irExpression")
val originalKotlinType = irExpression.type.originalKotlinType ?: irExpression.type.toKotlinType()
return IrVariableImpl(
irExpression.startOffset, irExpression.endOffset, origin,
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
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
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.safeAs
@@ -52,4 +53,20 @@ fun IrType.makeNullable() =
Variance.INVARIANT
)
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.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
@@ -79,6 +80,36 @@ fun IrFunctionAccessExpression.getArgumentsWithSymbols(): List<Pair<IrValueParam
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.
*/
@@ -203,14 +234,20 @@ val DeclarationDescriptorWithSource.endOffsetOrUndefined: Int get() = endOffset
val IrClassSymbol.functions: Sequence<IrSimpleFunctionSymbol>
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>
get() = this.owner.declarations.asSequence().filterIsInstance<IrConstructor>().map { it.symbol }
val IrFunction.explicitParameters: List<IrValueParameterSymbol>
get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol }
val IrClass.constructors: Sequence<IrConstructor>
get() = this.declarations.asSequence().filterIsInstance<IrConstructor>()
val IrClass.defaultType: KotlinType
get() = this.descriptor.defaultType
val IrFunction.explicitParameters: List<IrValueParameter>
get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters)
val IrClass.defaultType: IrType
get() = this.thisReceiver!!.type
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
@@ -263,3 +300,31 @@ fun IrAnnotationContainer.hasAnnotation(name: FqName) =
annotations.any {
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 }
}