From b11abeed6aa1f1d98ef777dd6ea8a0b1c7f8abf1 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Sat, 9 Jun 2018 10:16:44 +0300 Subject: [PATCH] IrTypes: migrate some code from backend.common (cherry picked from commit 3788130) --- .../backend/common/CheckIrElementVisitor.kt | 12 +- .../common/DeepCopyIrTreeWithDeclarations.kt | 5 +- .../DumpIrTreeWithDescriptorsVisitor.kt | 3 +- .../jetbrains/kotlin/backend/common/IrCopy.kt | 6 +- .../kotlin/backend/common/ir/IrUtils.kt | 120 +++++----- .../lower/DefaultArgumentStubGenerator.kt | 218 +++++++++--------- .../common/lower/InitializersLowering.kt | 5 +- .../backend/common/lower/IrBuildUtils.kt | 172 +------------- .../lower/KCallableNamePropertyLowering.kt | 4 +- .../backend/common/lower/LateinitLowering.kt | 18 +- .../common/lower/LocalDeclarationsLowering.kt | 185 +++++++++------ .../kotlin/backend/common/lower/LowerUtils.kt | 24 +- .../lower/StringConcatenationLowering.kt | 26 ++- .../backend/common/lower/TailrecLowering.kt | 32 ++- .../backend/common/lower/VarargLowering.kt | 123 +++++----- .../kotlin/ir/builders/IrBuilders.kt | 23 +- .../kotlin/ir/builders/ExpressionHelpers.kt | 11 + .../org/jetbrains/kotlin/ir/builders/Scope.kt | 3 +- .../kotlin/ir/types/irTypePredicates.kt | 56 +++++ .../org/jetbrains/kotlin/ir/types/irTypes.kt | 21 +- .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 73 +++++- 21 files changed, 572 insertions(+), 568 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt index 406bc7a854f..61d24c6ee4e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/CheckIrElementVisitor.kt @@ -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 } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt index 61bb0069131..5930a934a43 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt @@ -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.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 } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/DumpIrTreeWithDescriptorsVisitor.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/DumpIrTreeWithDescriptorsVisitor.kt index b27f0e2c024..9b1e8328776 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/DumpIrTreeWithDescriptorsVisitor.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/DumpIrTreeWithDescriptorsVisitor.kt @@ -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 T.transform() = transform(this@DeepCopyIrTreeWithReturnableBlockSymbols, null) as T diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt index 16be1eae59c..c5e50daf98a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt @@ -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, - 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) - } -} diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index ece407a54cc..41c51e4b9ab 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -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() - val variables = mutableMapOf() + val params = mutableListOf() + val variables = mutableMapOf() 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>> { 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 diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt index 1a98bb9e62f..4ce29daf084 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InitializersLowering.kt @@ -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) }) } }) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/IrBuildUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/IrBuildUtils.kt index b0a677538ea..b1fe029fea5 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/IrBuildUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/IrBuildUtils.kt @@ -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 { @@ -62,155 +44,3 @@ abstract class SymbolWithIrBuilder { return builtIr } } - -fun BackendContext.createPropertyGetterBuilder(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, - fieldSymbol: IrFieldSymbol, type: KotlinType) - = object: SymbolWithIrBuilder() { - - 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() { - - 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() { - - private lateinit var getterBuilder: SymbolWithIrBuilder - private var setterBuilder: SymbolWithIrBuilder? = 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) - } -} diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt index 6ce0cbb48b1..d965cdefaac 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/KCallableNamePropertyLowering.kt @@ -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() ) ) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt index 843e02f78f1..219e4717d42 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LateinitLowering.kt @@ -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) } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index e06abf4c776..a16f41f87f5 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -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 = HashMap() + val capturedValueToParameter: MutableMap = 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 = LinkedHashMap() val localClassConstructors: MutableMap = LinkedHashMap() - val transformedDeclarations = mutableMapOf() + val transformedDeclarations = mutableMapOf() - val FunctionDescriptor.transformed: IrFunctionSymbol? - get() = transformedDeclarations[this] as IrFunctionSymbol? + val FunctionDescriptor.transformed: IrFunction? + get() = transformedDeclarations[this] as IrFunction? - val oldParameterToNew: MutableMap = HashMap() + val oldParameterToNew: MutableMap = HashMap() val newParameterToOld: MutableMap = HashMap() val newParameterToCaptured: MutableMap = 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.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? { - 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 ) - : List { + : List { 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(newValueParametersCount).apply { + val newValueParameters = ArrayList(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 } } -} \ No newline at end of file +} + +private fun IrValueDeclaration.copy(newDescriptor: ParameterDescriptor): IrValueParameter = IrValueParameterImpl( + startOffset, + endOffset, + IrDeclarationOrigin.DEFINED, + newDescriptor, + type, + (this as? IrValueParameter)?.varargElementType +) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt index 485d8410e9d..ecf392b5531 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt @@ -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.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 diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt index fef59ef7b50..cba3cf8c73d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/StringConcatenationLowering.kt @@ -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 = + private val appendFunctions: Map = 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) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt index 8bdf76ef5ec..5030b937fd6 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt @@ -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, - val parameterToVariable: Map, + val parameterToNew: Map, + val parameterToVariable: Map, val tailRecursionCalls: Set ) : 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: diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/VarargLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/VarargLowering.kt index ec3ade13ab1..24491e1e08d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/VarargLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/VarargLowering.kt @@ -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 = 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 = + 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) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt index 0ac7c5af126..4ecdf364690 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/IrBuilders.kt @@ -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) = - IrCallImpl(this.startOffset, this.endOffset, symbol, symbol.descriptor.substitute(typeArguments), typeArguments) - -fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List) = - 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) \ No newline at end of file + IrGetObjectValueImpl(startOffset, endOffset, IrSimpleTypeImpl(classSymbol, false, emptyList(), emptyList()), classSymbol) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt index a1496dba38e..03750f9d514 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt @@ -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, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/Scope.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/Scope.kt index a276549b715..c5bd79e0319 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/Scope.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/Scope.kt @@ -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( diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt new file mode 100644 index 00000000000..96adb8bcf09 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt @@ -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) \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt index 520e3bbf89b..8c1fb9423db 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt @@ -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 \ No newline at end of file + 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()) +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index eb39dcc873a..a68c8cd3e8e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -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> { + val res = mutableListOf>() + 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 get() = this.owner.declarations.asSequence().filterIsInstance().map { it.symbol } +val IrClass.functions: Sequence + get() = this.declarations.asSequence().filterIsInstance() + val IrClassSymbol.constructors: Sequence get() = this.owner.declarations.asSequence().filterIsInstance().map { it.symbol } -val IrFunction.explicitParameters: List - get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol } +val IrClass.constructors: Sequence + get() = this.declarations.asSequence().filterIsInstance() -val IrClass.defaultType: KotlinType - get() = this.descriptor.defaultType +val IrFunction.explicitParameters: List + 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 } +}