diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt index a09224e0166..e72cfb196d7 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/DeepCopyIrTreeWithDeclarations.kt @@ -20,14 +20,26 @@ import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor -import org.jetbrains.kotlin.ir.expressions.IrBlock -import org.jetbrains.kotlin.ir.expressions.IrLoop +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl +import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.util.DeepCopyIrTree +import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols +import org.jetbrains.kotlin.ir.util.DeepCopySymbolsRemapper +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid /** * Copies IR tree with descriptors of all declarations inside; * updates the references to these declarations. */ +@Deprecated("Creates unbound symbols") open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() { private fun DeclarationDescriptor.notSupported(): Nothing = TODO("${this}") @@ -95,4 +107,69 @@ open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() { override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop { return irLoop } -} \ No newline at end of file +} + +fun IrElement.deepCopyWithVariablesImpl(): IrElement { + // FIXME: support non-transformed loops + + val remapper = DeepCopySymbolsRemapper() + acceptVoid(remapper) + + val variableDescriptorReplacer = object : IrElementTransformerVoid() { + + val copiedVariables = mutableMapOf() + + override fun visitVariable(declaration: IrVariable): IrStatement { + declaration.transformChildrenVoid() + + val descriptor = declaration.descriptor + val newDescriptor = LocalVariableDescriptor( + /* containingDeclaration = */ descriptor.containingDeclaration, + /* annotations = */ descriptor.annotations, + /* name = */ descriptor.name, + /* type = */ descriptor.type, + /* mutable = */ descriptor.isVar, + /* isDelegated = */ false, + /* source = */ descriptor.source + ) + val newSymbol = IrVariableSymbolImpl(newDescriptor) + copiedVariables[declaration.symbol] = newSymbol + + return with(declaration) { + IrVariableImpl(startOffset, endOffset, origin, newSymbol).also { + it.initializer = initializer + } + } + + } + + override fun visitValueAccess(expression: IrValueAccessExpression): IrExpression { + assert(expression.symbol !in copiedVariables) + return super.visitValueAccess(expression) + } + + override fun visitGetValue(expression: IrGetValue): IrExpression { + val newSymbol = copiedVariables[expression.symbol] ?: return super.visitGetValue(expression) + + expression.transformChildrenVoid() + return with(expression) { + IrGetValueImpl(startOffset, endOffset, newSymbol, origin) + } + } + + override fun visitSetVariable(expression: IrSetVariable): IrExpression { + val newSymbol = copiedVariables[expression.symbol] ?: return super.visitSetVariable(expression) + + expression.transformChildrenVoid() + return with(expression) { + IrSetVariableImpl(startOffset, endOffset, newSymbol, value, origin) + } + } + + } + + return this.transform(DeepCopyIrTreeWithSymbols(remapper), null).transform(variableDescriptorReplacer, null) +} + +inline fun T.deepCopyWithVariables(): T = + this.deepCopyWithVariablesImpl() as T \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt index 56d38bbc3dd..f45d8a6c70f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrElementTransformerVoidWithContext.kt @@ -38,7 +38,7 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform } override final fun visitClass(declaration: IrClass): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) + scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) val result = visitClassNew(declaration) scopeStack.pop() return result @@ -52,14 +52,14 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform } override final fun visitField(declaration: IrField): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) + scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) val result = visitFieldNew(declaration) scopeStack.pop() return result } override final fun visitFunction(declaration: IrFunction): IrStatement { - scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) + scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) val result = visitFunctionNew(declaration) scopeStack.pop() return result @@ -102,13 +102,13 @@ abstract internal class IrElementVisitorVoidWithContext : IrElementVisitorVoid { private val scopeStack = mutableListOf() override final fun visitFile(declaration: IrFile) { - scopeStack.push(ScopeWithIr(Scope(declaration.packageFragmentDescriptor), declaration)) + scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) visitFileNew(declaration) scopeStack.pop() } override final fun visitClass(declaration: IrClass) { - scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) + scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) visitClassNew(declaration) scopeStack.pop() } @@ -121,7 +121,7 @@ abstract internal class IrElementVisitorVoidWithContext : IrElementVisitorVoid { override final fun visitField(declaration: IrField) { val isDelegated = declaration.descriptor.isDelegated - if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) + if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration)) visitFieldNew(declaration) if (isDelegated) scopeStack.pop() } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt index 993494a79cb..30f17f4b6cb 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/IrValidator.kt @@ -203,7 +203,7 @@ private class IrValidator(val context: BackendContext, performHeavyValidations: private fun recordDeclaration(declaration: IrDeclaration) { if (foundDeclarations.isAlreadyDeclared(declaration)) { - if (declaration.descriptor !is ReceiverParameterDescriptor && declaration !is IrTypeParameter) { + if (declaration !is IrValueParameter && declaration !is IrTypeParameter) { // TODO: remove the check. error(declaration, "redeclaration") } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt index d80d85f54b9..88b0bc74d5f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCatch import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.expressions.IrValueAccessExpression +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -30,7 +31,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils // TODO: synchronize with JVM BE // TODO: rename the file. -class Closure(val capturedValues: List = emptyList()) +class Closure(val capturedValues: List = emptyList()) class ClosureAnnotator { private val closureBuilders = mutableMapOf() @@ -51,7 +52,7 @@ class ClosureAnnotator { } private class ClosureBuilder(val owner: DeclarationDescriptor) { - val capturedValues = mutableSetOf() + val capturedValues = mutableSetOf() private val declaredValues = mutableSetOf() private val includes = mutableSetOf() @@ -63,11 +64,11 @@ class ClosureAnnotator { * variables declared in the node. */ fun buildClosure(): Closure { - val result = mutableSetOf().apply { addAll(capturedValues) } + val result = mutableSetOf().apply { addAll(capturedValues) } includes.forEach { if (!it.processed) { it.processed = true - it.buildClosure().capturedValues.filterTo(result) { isExternal(it) } + it.buildClosure().capturedValues.filterTo(result) { isExternal(it.descriptor) } } } // TODO: We can save the closure and reuse it. @@ -84,9 +85,9 @@ class ClosureAnnotator { declaredValues.add(valueDescriptor) } - fun seeVariable(valueDescriptor: ValueDescriptor) { - if (isExternal(valueDescriptor)) - capturedValues.add(valueDescriptor) + fun seeVariable(value: IrValueSymbol) { + if (isExternal(value.descriptor)) + capturedValues.add(value) } fun isExternal(valueDescriptor: ValueDescriptor): Boolean { @@ -159,7 +160,7 @@ class ClosureAnnotator { } override fun visitVariableAccess(expression: IrValueAccessExpression) { - closuresStack.peek()?.seeVariable(expression.descriptor) + closuresStack.peek()?.seeVariable(expression.symbol) super.visitVariableAccess(expression) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index c2591479d09..bb0361755d1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.* @@ -78,13 +79,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai get() = declaration.descriptor 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 newDescriptor = capturedValueToParameter[descriptor] ?: return null + val newSymbol = capturedValueToParameter[descriptor] ?: return null - return IrGetValueImpl(startOffset, endOffset, newDescriptor) + return IrGetValueImpl(startOffset, endOffset, newSymbol) } } @@ -92,6 +94,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai lateinit var closure: Closure override lateinit var transformedDescriptor: FunctionDescriptor + override lateinit var transformedDeclaration: IrSimpleFunction var index: Int = -1 @@ -104,6 +107,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai get() = declaration.descriptor override lateinit var transformedDescriptor: ClassConstructorDescriptor + override lateinit var transformedDeclaration: IrConstructor override fun toString(): String = "LocalClassConstructorContext for $descriptor" @@ -115,13 +119,13 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai lateinit var closure: Closure - val capturedValueToField: MutableMap = HashMap() + val capturedValueToField: MutableMap = HashMap() override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { - val fieldDescriptor = capturedValueToField[descriptor] ?: return null + val field = capturedValueToField[descriptor] ?: return null - return IrGetFieldImpl(startOffset, endOffset, fieldDescriptor, - receiver = IrGetValueImpl(startOffset, endOffset, this.descriptor.thisAsReceiverParameter) + return IrGetFieldImpl(startOffset, endOffset, field.symbol, + receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol) ) } @@ -134,14 +138,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai val localClasses: MutableMap = LinkedHashMap() val localClassConstructors: MutableMap = LinkedHashMap() - val transformedDescriptors = mutableMapOf() + val transformedDeclarations = mutableMapOf() - val FunctionDescriptor.transformed: FunctionDescriptor? - get() = transformedDescriptors[this] as FunctionDescriptor? + val FunctionDescriptor.transformed: IrFunctionSymbol? + get() = transformedDeclarations[this] as IrFunctionSymbol? - val oldParameterToNew: MutableMap = HashMap() + val oldParameterToNew: MutableMap = HashMap() val newParameterToOld: MutableMap = HashMap() - val newParameterToCaptured: MutableMap = HashMap() + val newParameterToCaptured: MutableMap = HashMap() fun lowerLocalDeclarations(): List? { collectLocalDeclarations() @@ -163,16 +167,12 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai localFunctions.values.mapTo(this) { val original = it.declaration - IrFunctionImpl( - original.startOffset, original.endOffset, original.origin, - it.transformedDescriptor, - original.body - ).apply { - createParameterDeclarations() + it.transformedDeclaration.apply { + this.body = original.body original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> val body = original.getDefault(argument)!! - this.putDefault(oldParameterToNew[argument] as ValueParameterDescriptor, body) + oldParameterToNew[argument]!!.owner.defaultValue = body } } } @@ -205,16 +205,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai override fun visitConstructor(declaration: IrConstructor): IrStatement { // Body is transformed separately. See loop over constructors in rewriteDeclarations(). - val transformedDescriptor = localClassConstructors[declaration.descriptor]?.transformedDescriptor - if (transformedDescriptor != null) { - return IrConstructorImpl(declaration.startOffset, declaration.endOffset, declaration.origin, - transformedDescriptor, declaration.body!!).apply { - - createParameterDeclarations() + val constructorContext = localClassConstructors[declaration.descriptor] + if (constructorContext != null) { + return constructorContext.transformedDeclaration.apply { + this.body = declaration.body!! declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> val body = declaration.getDefault(argument)!! - this.putDefault(oldParameterToNew[argument] as ValueParameterDescriptor, body) + oldParameterToNew[argument]!!.owner.defaultValue = body } } } else { @@ -251,12 +249,13 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai expression.transformChildrenVoid(this) val oldCallee = expression.descriptor.original - val newCallee = transformedDescriptors[oldCallee] as ClassConstructorDescriptor? ?: return expression + val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression val newExpression = IrDelegatingConstructorCallImpl( expression.startOffset, expression.endOffset, newCallee, - remapTypeArguments(expression, newCallee) + newCallee.descriptor, + remapTypeArguments(expression, newCallee.descriptor) ).fillArguments(expression) return newExpression @@ -271,17 +270,18 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor) } else { // The callee expects captured value as argument. - val capturedValueDescriptor = + val capturedValueSymbol = newParameterToCaptured[newValueParameterDescriptor] ?: throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") + 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] ?: capturedValueDescriptor) + oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol) } } @@ -302,7 +302,8 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai expression.startOffset, expression.endOffset, expression.type, // TODO functional type for transformed descriptor newCallee, - remapTypeArguments(expression, newCallee), + newCallee.descriptor, + remapTypeArguments(expression, newCallee.descriptor), expression.origin ).fillArguments(expression) @@ -319,14 +320,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai } override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression { - if (expression.descriptor in transformedDescriptors) { + if (expression.descriptor in transformedDeclarations) { TODO() } return super.visitDeclarationReference(expression) } override fun visitDeclaration(declaration: IrDeclaration): IrStatement { - if (declaration.descriptor in transformedDescriptors) { + if (declaration.descriptor in transformedDeclarations) { TODO() } return super.visitDeclaration(declaration) @@ -352,24 +353,18 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai .filter { it.declaration.callsSuper() } assert(constructorsCallingSuper.any(), { "Expected at least one constructor calling super; class: $classDescriptor" }) - localClassContext.capturedValueToField.forEach { capturedValue, fieldDescriptor -> + localClassContext.capturedValueToField.forEach { capturedValue, field -> val startOffset = irClass.startOffset val endOffset = irClass.endOffset - irClass.declarations.add( - IrFieldImpl( - startOffset, endOffset, - DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, - fieldDescriptor - ) - ) + irClass.declarations.add(field) for (constructorContext in constructorsCallingSuper) { val blockBody = constructorContext.declaration.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}") val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!! blockBody.statements.add(0, - IrSetFieldImpl(startOffset, endOffset, fieldDescriptor, - IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter), + IrSetFieldImpl(startOffset, endOffset, field.symbol, + IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE)) } } @@ -391,15 +386,16 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai rewriteFunctionBody(memberDeclaration, null) } - private fun createNewCall(oldCall: IrCall, newCallee: FunctionDescriptor) = + private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) = if (oldCall is IrCallWithShallowCopy) - oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifier) + oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol) else IrCallImpl( oldCall.startOffset, oldCall.endOffset, newCallee, - remapTypeArguments(oldCall, newCallee), - oldCall.origin, oldCall.superQualifier + newCallee.descriptor, + remapTypeArguments(oldCall, newCallee.descriptor), + oldCall.origin, oldCall.superQualifierSymbol ) private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map? { @@ -463,7 +459,6 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai } localFunctionContext.transformedDescriptor = newDescriptor - transformedDescriptors[oldDescriptor] = newDescriptor if (oldDescriptor.dispatchReceiverParameter != null) { throw AssertionError("local functions must not have dispatch receiver") @@ -490,12 +485,20 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai ) oldDescriptor.extensionReceiverParameter?.let { - recordRemappedParameter(it, newDescriptor.extensionReceiverParameter!!) + newParameterToOld.putAbsentOrSame(newDescriptor.extensionReceiverParameter!!, it) + } + + localFunctionContext.transformedDeclaration = with(localFunctionContext.declaration) { + IrFunctionImpl(startOffset, endOffset, origin, newDescriptor) + }.apply { + createParameterDeclarations() + recordTransformedValueParameters(localFunctionContext) + transformedDeclarations[oldDescriptor] = this.symbol } } private fun createTransformedValueParameters(localContext: LocalContextWithClosureAsParameters, - capturedValues: List) + capturedValues: List) : List { val oldDescriptor = localContext.descriptor @@ -505,21 +508,39 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size val newValueParameters = ArrayList(newValueParametersCount).apply { - capturedValues.mapIndexedTo(this) { i, capturedValueDescriptor -> - createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValueDescriptor, i).apply { - localContext.recordCapturedAsParameter(capturedValueDescriptor, this) + capturedValues.mapIndexedTo(this) { i, capturedValue -> + createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply { + newParameterToCaptured[this] = capturedValue } } oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor -> createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply { - recordRemappedParameter(oldValueParameterDescriptor, this) + newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor) } } } return newValueParameters } + private fun IrFunction.recordTransformedValueParameters(localContext: LocalContextWithClosureAsParameters) { + + valueParameters.forEach { + val capturedValue = newParameterToCaptured[it.descriptor] + if (capturedValue != null) { + localContext.capturedValueToParameter[capturedValue.descriptor] = it.symbol + } + } + + (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach { + val oldParameter = newParameterToOld[it.descriptor] + if (oldParameter != null) { + oldParameterToNew.putAbsentOrSame(oldParameter, it.symbol) + } + } + + } + private fun createTransformedConstructorDescriptor(constructorContext: LocalClassConstructorContext) { val oldDescriptor = constructorContext.descriptor val localClassContext = localClasses[oldDescriptor.containingDeclaration]!! @@ -528,7 +549,6 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source) constructorContext.transformedDescriptor = newDescriptor - transformedDescriptors[oldDescriptor] = newDescriptor // Do not substitute type parameters for now. val newTypeParameters = oldDescriptor.typeParameters @@ -545,12 +565,20 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai newDescriptor.returnType = oldDescriptor.returnType oldDescriptor.dispatchReceiverParameter?.let { - recordRemappedParameter(it, newDescriptor.dispatchReceiverParameter!!) + newParameterToOld.putAbsentOrSame(newDescriptor.dispatchReceiverParameter!!, it) } oldDescriptor.extensionReceiverParameter?.let { throw AssertionError("constructors can't have extension receiver") } + + constructorContext.transformedDeclaration = with(constructorContext.declaration) { + IrConstructorImpl(startOffset, endOffset, origin, newDescriptor) + }.apply { + createParameterDeclarations() + recordTransformedValueParameters(constructorContext) + transformedDeclarations[oldDescriptor] = this.symbol + } } private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) { @@ -563,7 +591,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai Modality.FINAL, Visibilities.PRIVATE, /* isVar = */ false, - suggestNameForCapturedValue(capturedValue), + suggestNameForCapturedValue(capturedValue.descriptor), CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, /* lateInit = */ false, @@ -578,25 +606,19 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai val extensionReceiverParameter: ReceiverParameterDescriptor? = null fieldDescriptor.setType( - capturedValue.type, + capturedValue.descriptor.type, emptyList(), classDescriptor.thisAsReceiverParameter, extensionReceiverParameter) - localClassContext.capturedValueToField[capturedValue] = fieldDescriptor + localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl( + localClassContext.declaration.startOffset, localClassContext.declaration.endOffset, + DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, + fieldDescriptor + ) } } - private fun LocalContextWithClosureAsParameters.recordCapturedAsParameter( - oldDescriptor: ValueDescriptor, - newDescriptor: ValueParameterDescriptor - ) { - - capturedValueToParameter[oldDescriptor] = newDescriptor - newParameterToCaptured[newDescriptor] = oldDescriptor - - } - private fun MutableMap.putAbsentOrSame(key: K, value: V) { val current = this.getOrPut(key, { value }) @@ -605,11 +627,6 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai } } - private fun recordRemappedParameter(oldDescriptor: ParameterDescriptor, newDescriptor: ParameterDescriptor) { - oldParameterToNew.putAbsentOrSame(oldDescriptor, newDescriptor) - newParameterToOld.putAbsentOrSame(newDescriptor, oldDescriptor) - } - private fun suggestNameForCapturedValue(valueDescriptor: ValueDescriptor): Name = if (valueDescriptor.name.isSpecial) { val oldNameStr = valueDescriptor.name.asString() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt index c1f8ed20044..b8c1e874dcf 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LowerUtils.kt @@ -126,11 +126,10 @@ fun IrBuilderWithScope.irNot(arg: IrExpression) = fun IrBuilderWithScope.irThrow(arg: IrExpression) = IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg) -fun IrBuilderWithScope.irCatch(parameter: VariableDescriptor, result: IrExpression) = +fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) = IrCatchImpl( startOffset, endOffset, - IrVariableImpl(startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter), - result + catchParameter ) fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) = diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt index 6a02aacee5b..7c3ccc2bba6 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/TailrecLowering.kt @@ -16,22 +16,16 @@ package org.jetbrains.kotlin.backend.common.lower -import org.jetbrains.kotlin.backend.common.BackendContext -import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDeclarations -import org.jetbrains.kotlin.backend.common.FunctionLoweringPass -import org.jetbrains.kotlin.backend.common.collectTailRecursionCalls -import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters -import org.jetbrains.kotlin.backend.common.descriptors.getOriginalParameter -import org.jetbrains.kotlin.descriptors.ParameterDescriptor -import org.jetbrains.kotlin.descriptors.ValueDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.descriptors.VariableDescriptor +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.getDefault 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.getArguments +import org.jetbrains.kotlin.ir.util.explicitParameters +import org.jetbrains.kotlin.ir.util.getArgumentsWithSymbols import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -53,11 +47,10 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct return } - val descriptor = irFunction.descriptor val oldBody = irFunction.body as IrBlockBody - val builder = context.createIrBuilder(descriptor).at(oldBody) + val builder = context.createIrBuilder(irFunction.symbol).at(oldBody) - val parameters = descriptor.explicitParameters + val parameters = irFunction.explicitParameters irFunction.body = builder.irBlockBody { // Define variables containing current values of parameters: @@ -74,7 +67,7 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct // Read variables containing current values of parameters: val parameterToNew = parameters.associate { val variable = parameterToVariable[it]!! - it to defineTemporary(irGet(variable), nameHint = it.suggestVariableName()) + it to irTemporary(irGet(variable), nameHint = it.suggestVariableName()).symbol } val transformer = BodyTransformer(builder, irFunction, loop, @@ -94,16 +87,16 @@ 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() { - val parameters = irFunction.descriptor.explicitParameters + val parameters = irFunction.explicitParameters override fun visitGetValue(expression: IrGetValue): IrExpression { expression.transformChildrenVoid(this) - val value = parameterToNew[expression.descriptor] ?: return expression + val value = parameterToNew[expression.symbol] ?: return expression return builder.at(expression).irGet(value) } @@ -118,8 +111,8 @@ private class BodyTransformer( private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) { // Get all specified arguments: - val parameterToArgument = expression.getArguments().map { (parameter, argument) -> - expression.descriptor.getOriginalParameter(parameter) to argument + val parameterToArgument = expression.getArgumentsWithSymbols().map { (parameter, argument) -> + parameter to argument } // For each specified argument set the corresponding variable to it in the correct order: @@ -135,15 +128,24 @@ private class BodyTransformer( // For each unspecified argument set the corresponding variable to default: parameters.filter { it !in specifiedParameters }.forEach { parameter -> - val originalDefaultValue = irFunction.getDefaultArgumentExpression(parameter) ?: + val originalDefaultValue = parameter.owner.defaultValue?.expression ?: throw Error("no argument specified for $parameter") // Copy default value, mapping parameters to variables containing freshly computed arguments: - val defaultValue = originalDefaultValue.transform(object : DeepCopyIrTreeWithDeclarations() { - override fun mapValueReference(descriptor: ValueDescriptor): ValueDescriptor { - return parameterToVariable[descriptor]?.descriptor ?: super.mapValueReference(descriptor) - } - }, data = null) + val defaultValue = originalDefaultValue + .deepCopyWithVariables() + .transform(object : IrElementTransformerVoid() { + + override fun visitGetValue(expression: IrGetValue): IrExpression { + expression.transformChildrenVoid(this) + + val variableSymbol = parameterToVariable[expression.symbol] ?: return expression + return IrGetValueImpl( + expression.startOffset, expression.endOffset, + variableSymbol, expression.origin + ) + } + }, data = null) +irSetVar(parameterToVariable[parameter]!!, defaultValue) } @@ -153,23 +155,9 @@ private class BodyTransformer( } } -private fun IrFunction.getDefaultArgumentExpression(parameter: ParameterDescriptor): IrExpression? { - if (parameter !is ValueParameterDescriptor) { - return null - } - - val body = this.getDefault(parameter) ?: return null - - if (body !is IrExpressionBody) { - throw Error("unexpected default argument body: $body") - } - - return body.expression -} - -private fun ParameterDescriptor.suggestVariableName(): String = if (name.isSpecial) { - val oldNameStr = name.asString() +private fun IrValueParameterSymbol.suggestVariableName(): String = if (descriptor.name.isSpecial) { + val oldNameStr = descriptor.name.asString() "$" + oldNameStr.substring(1, oldNameStr.length - 1) } else { - name.identifier + descriptor.name.identifier } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index b99d6c9a9ae..e6b6b3be470 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -32,15 +32,15 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.SourceManager -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -55,22 +55,34 @@ import java.util.* import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.reflect.KProperty -internal class SpecialDescriptorsFactory(val context: Context) { - private val enumSpecialDescriptorsFactory by lazy { EnumSpecialDescriptorsFactory(context) } - private val outerThisDescriptors = mutableMapOf() +internal class SpecialDeclarationsFactory(val context: Context) { + private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) } + private val outerThisFields = mutableMapOf() private val bridgesDescriptors = mutableMapOf, FunctionDescriptor>() private val loweredEnums = mutableMapOf() - fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor = + object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS : + IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") + + fun getOuterThisField(innerClassDescriptor: ClassDescriptor): IrField = if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor") - else outerThisDescriptors.getOrPut(innerClassDescriptor) { + else outerThisFields.getOrPut(innerClassDescriptor) { val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) ?: throw AssertionError("No containing class for inner class $innerClassDescriptor") val receiver = ReceiverParameterDescriptorImpl(innerClassDescriptor, ImplicitClassReceiver(innerClassDescriptor)) - PropertyDescriptorImpl.create(innerClassDescriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE, - false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, - false, false, false, false, false, false).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver) + val descriptor = PropertyDescriptorImpl.create( + innerClassDescriptor, Annotations.EMPTY, Modality.FINAL, + Visibilities.PRIVATE, false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, + SourceElement.NO_SOURCE, false, false, false, false, false, false + ).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver) + + IrFieldImpl( + innerClassDescriptor.startOffsetOrUndefined, + innerClassDescriptor.endOffsetOrUndefined, + DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS, + descriptor + ) } fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): FunctionDescriptor { @@ -93,7 +105,7 @@ internal class SpecialDescriptorsFactory(val context: Context) { fun getLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum { assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: $enumClassDescriptor" }) return loweredEnums.getOrPut(enumClassDescriptor) { - enumSpecialDescriptorsFactory.createLoweredEnum(enumClassDescriptor) + enumSpecialDeclarationsFactory.createLoweredEnum(enumClassDescriptor) } } @@ -219,7 +231,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { override val builtIns: KonanBuiltIns by lazy(PUBLICATION) { moduleDescriptor.builtIns as KonanBuiltIns } - val specialDescriptorsFactory = SpecialDescriptorsFactory(this) + val specialDeclarationsFactory = SpecialDeclarationsFactory(this) val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) { ReflectionTypes(moduleDescriptor) } private val vtableBuilders = mutableMapOf() @@ -233,6 +245,9 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { // to dump this information into generated file. var serializedLinkData: LinkData? = null + @Deprecated("") + lateinit var psi2IrGeneratorContext: GeneratorContext + // TODO: make lateinit? var irModule: IrModuleFragment? = null set(module: IrModuleFragment?) { @@ -244,7 +259,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { ir = Ir(this, module) } - lateinit var ir: Ir + override lateinit var ir: Ir override val irBuiltIns get() = ir.irModule.irBuiltins diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt index 7d01c4257d6..3c47631d587 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/EnumSpecialDescriptorsFactory.kt @@ -22,7 +22,13 @@ import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructorDe import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.* -import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.* +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.util.createParameterDeclarations +import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined +import org.jetbrains.kotlin.ir.util.functions +import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -32,19 +38,33 @@ import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.replace -internal data class LoweredEnum(val implObjectDescriptor: ClassDescriptor, - val valuesProperty: PropertyDescriptor, - val valuesGetter: FunctionDescriptor, - val itemGetter: FunctionDescriptor, + +internal object DECLARATION_ORIGIN_ENUM : + IrDeclarationOriginImpl("ENUM") + +internal data class LoweredEnum(val implObject: IrClass, + val valuesField: IrField, + val valuesGetter: IrSimpleFunction, + val itemGetterSymbol: IrFunctionSymbol, + val itemGetterDescriptor: FunctionDescriptor, val entriesMap: Map) -internal class EnumSpecialDescriptorsFactory(val context: Context) { +internal class EnumSpecialDeclarationsFactory(val context: Context) { fun createLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum { + + val startOffset = enumClassDescriptor.startOffsetOrUndefined + val endOffset = enumClassDescriptor.endOffsetOrUndefined + val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL, ClassKind.OBJECT, listOf(context.builtIns.anyType), SourceElement.NO_SOURCE, false) val valuesProperty = createEnumValuesField(enumClassDescriptor, implObjectDescriptor) - val valuesGetter = createValuesGetterDescriptor(enumClassDescriptor, implObjectDescriptor) + val valuesField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesProperty) + + val valuesGetterDescriptor = createValuesGetterDescriptor(enumClassDescriptor, implObjectDescriptor) + val valuesGetter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesGetterDescriptor).apply { + createParameterDeclarations() + } val memberScope = MemberScope.Empty @@ -53,9 +73,18 @@ internal class EnumSpecialDescriptorsFactory(val context: Context) { val constructorDescriptor = implObjectDescriptor.createSimpleDelegatingConstructorDescriptor(constructorOfAny, true) implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor) + val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply { + createParameterDeclarations() + } - return LoweredEnum(implObjectDescriptor, valuesProperty, valuesGetter, - getEnumItemGetter(enumClassDescriptor), createEnumEntriesMap(enumClassDescriptor)) + val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor) + + return LoweredEnum( + implObject, + valuesField, + valuesGetter, + itemGetterSymbol, itemGetterDescriptor, + createEnumEntriesMap(enumClassDescriptor)) } private fun createValuesGetterDescriptor(enumClassDescriptor: ClassDescriptor, implObjectDescriptor: ClassDescriptor) @@ -87,15 +116,15 @@ internal class EnumSpecialDescriptorsFactory(val context: Context) { } private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin")) - private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor + private val genericArrayType = context.ir.symbols.array.descriptor - private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): FunctionDescriptor { - val getter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND).single() + private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): Pair { + val getter = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") } val typeParameterT = genericArrayType.declaredTypeParameters[0] val enumClassType = enumClassDescriptor.defaultType val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) - return getter.substitute(typeSubstitutor)!! + return getter to getter.descriptor.substitute(typeSubstitutor)!! } private fun createEnumEntriesMap(enumClassDescriptor: ClassDescriptor): Map { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt index 5a8815dcc27..f16fa0842c5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanBackendContext.kt @@ -18,13 +18,16 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.konan.descriptors.KonanSharedVariablesManager +import org.jetbrains.kotlin.backend.konan.ir.Ir abstract internal class KonanBackendContext(val config: KonanConfig) : BackendContext { abstract override val builtIns: KonanBuiltIns + abstract val ir: Ir + override val sharedVariablesManager by lazy { // Creating lazily because builtIns module seems to be incomplete during `link` test; // TODO: investigate this. - KonanSharedVariablesManager(builtIns) + KonanSharedVariablesManager(this) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt index e2b06d5632d..a73d5ac32f5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanDriver.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.messageCollector import org.jetbrains.kotlin.backend.common.validateIrModule import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex +import org.jetbrains.kotlin.backend.konan.ir.Symbols import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM import org.jetbrains.kotlin.backend.konan.serialization.KonanSerializationUtil import org.jetbrains.kotlin.backend.konan.serialization.markBackingFields @@ -81,10 +82,15 @@ public fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEn phaser.phase(KonanPhase.PSI_TO_IR) { // Translate AST to high level IR. val translator = Psi2IrTranslator(Psi2IrConfiguration(false)) - val module = translator.generateModule(context.moduleDescriptor, - environment.getSourceFiles(), bindingContext) + val generatorContext = translator.createGeneratorContext(context.moduleDescriptor, bindingContext) + context.psi2IrGeneratorContext = generatorContext + + val symbols = Symbols(context, generatorContext.symbolTable) + + val module = translator.generateModuleFragment(generatorContext, environment.getSourceFiles()) context.irModule = module + context.ir.symbols = symbols validateIrModule(context, module) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt index 401678da29c..7e296bc23cc 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt @@ -20,8 +20,12 @@ import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.validateIrFile import org.jetbrains.kotlin.backend.konan.lower.* +import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.util.IrSymbolBindingChecker +import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols +import org.jetbrains.kotlin.ir.visitors.acceptVoid internal class KonanLower(val context: Context) { @@ -45,6 +49,8 @@ internal class KonanLower(val context: Context) { // Inlining must be run before other phases. phaser.phase(KonanPhase.LOWER_INLINE) { FunctionInlining(context).inline(irModule) + irModule.replaceUnboundSymbols(context) + irModule.checkSymbolsBound() } } @@ -53,24 +59,31 @@ internal class KonanLower(val context: Context) { phaser.phase(KonanPhase.LOWER_STRING_CONCAT) { StringConcatenationLowering(context).lower(irFile) + irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_ENUMS) { EnumClassLowering(context).run(irFile) + irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_INITIALIZERS) { InitializersLowering(context).runOnFilePostfix(irFile) + irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) { SharedVariablesLowering(context).runOnFilePostfix(irFile) + irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_DELEGATION) { PropertyDelegationLowering(context).lower(irFile) + irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) { LocalDeclarationsLowering(context).runOnFilePostfix(irFile) + irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_TAILREC) { TailrecLowering(context).runOnFilePostfix(irFile) + irFile.checkSymbolsBound() } phaser.phase(KonanPhase.LOWER_FINALLY) { FinallyBlocksLowering(context).runOnFilePostfix(irFile) @@ -112,4 +125,10 @@ internal class KonanLower(val context: Context) { Autoboxing(context).lower(irFile) } } + + private fun IrElement.checkSymbolsBound() { + if (context.shouldVerifyIr()) { + this.acceptVoid(IrSymbolBindingChecker()) + } + } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt index 05a4c4ae7df..b3f5909d5d1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/KonanSharedVariablesManager.kt @@ -18,12 +18,14 @@ package org.jetbrains.kotlin.backend.konan.descriptors import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager -import org.jetbrains.kotlin.backend.konan.KonanBuiltIns +import org.jetbrains.kotlin.backend.konan.KonanBackendContext import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -32,24 +34,33 @@ import org.jetbrains.kotlin.ir.expressions.IrSetVariable import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl +import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.types.* -internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : SharedVariablesManager { +internal class KonanSharedVariablesManager(val context: KonanBackendContext) : SharedVariablesManager { - private val refClass = builtIns.getKonanInternalClass("Ref") + private val refClass = context.ir.symbols.refClass - private val refClassConstructor = refClass.unsubstitutedPrimaryConstructor!! + private val refClassConstructor = refClass.constructors.single() + + private val elementProperty = refClass.owner.declarations.filterIsInstance().single() + + // TODO: refactor `SharedVariablesManager` interface instead of tracking the mapping: + private val sharedVariableDescriptorToSymbol = mutableMapOf() private fun refConstructor(elementType: KotlinType): ClassConstructorDescriptor { - val typeParameter = refClassConstructor.typeParameters[0] + val typeParameter = refClassConstructor.descriptor.typeParameters[0] - return refClassConstructor.substitute(TypeSubstitutor.create( + return refClassConstructor.descriptor.substitute(TypeSubstitutor.create( mapOf(typeParameter.typeConstructor to TypeProjectionImpl(Variance.INVARIANT, elementType)) ))!! } private fun refType(elementType: KotlinType): KotlinType { - return refClass.defaultType.replace(listOf(TypeProjectionImpl(elementType))) + return refClass.owner.defaultType.replace(listOf(TypeProjectionImpl(elementType))) } override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor { @@ -57,10 +68,12 @@ internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : Shared variableDescriptor.containingDeclaration, variableDescriptor.annotations, variableDescriptor.name, refType(variableDescriptor.type), false, false, variableDescriptor.source - ) + ).also { + sharedVariableDescriptorToSymbol[it] = IrVariableSymbolImpl(it) + } } - private fun getElementProperty(sharedVariableDescriptor: VariableDescriptor): PropertyDescriptor { + private fun getElementPropertyDescriptor(sharedVariableDescriptor: VariableDescriptor): PropertyDescriptor { return sharedVariableDescriptor.type.memberScope.getContributedDescriptors() .filterIsInstance() .single { @@ -71,49 +84,62 @@ internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : Shared override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor, originalDeclaration: IrVariable): IrStatement { + val sharedVariableSymbol = sharedVariableDescriptorToSymbol[sharedVariableDescriptor]!! + val valueType = originalDeclaration.descriptor.type - val refConstructorTypeArguments = mapOf(refClassConstructor.typeParameters[0] to valueType) + val refConstructorTypeArguments = mapOf(refClassConstructor.descriptor.typeParameters[0] to valueType) val refConstructorCall = IrCallImpl( originalDeclaration.startOffset, originalDeclaration.endOffset, - refConstructor(valueType), refConstructorTypeArguments + refClassConstructor, refConstructor(valueType), refConstructorTypeArguments ) val sharedVariableDeclaration = IrVariableImpl( originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin, - sharedVariableDescriptor, refConstructorCall - ) + sharedVariableSymbol + ).apply { + initializer = refConstructorCall + } val initializer = originalDeclaration.initializer ?: return sharedVariableDeclaration - val elementProperty = getElementProperty(sharedVariableDescriptor) + val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDescriptor) val sharedVariableInitialization = - IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!) + IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!.symbol, + elementPropertyDescriptor.setter!!) sharedVariableInitialization.dispatchReceiver = - IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDescriptor) + IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableSymbol) sharedVariableInitialization.putValueArgument(0, initializer) return IrCompositeImpl( - originalDeclaration.startOffset, originalDeclaration.endOffset, builtIns.unitType, null, + originalDeclaration.startOffset, originalDeclaration.endOffset, context.builtIns.unitType, null, listOf(sharedVariableDeclaration, sharedVariableInitialization) ) } override fun getSharedValue(sharedVariableDescriptor: VariableDescriptor, originalGet: IrGetValue): IrExpression { - val elementProperty = getElementProperty(sharedVariableDescriptor) - return IrCallImpl(originalGet.startOffset, originalGet.endOffset, elementProperty.getter!!).apply { - dispatchReceiver = IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableDescriptor) + val sharedVariableSymbol = sharedVariableDescriptorToSymbol[sharedVariableDescriptor]!! + + val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDescriptor) + + return IrCallImpl(originalGet.startOffset, originalGet.endOffset, elementProperty.getter!!.symbol, + elementPropertyDescriptor.getter!!).apply { + dispatchReceiver = IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableSymbol) } } override fun setSharedValue(sharedVariableDescriptor: VariableDescriptor, originalSet: IrSetVariable): IrExpression { - val elementProperty = getElementProperty(sharedVariableDescriptor) - return IrCallImpl(originalSet.startOffset, originalSet.endOffset, elementProperty.setter!!).apply { - dispatchReceiver = IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableDescriptor) + val sharedVariableSymbol = sharedVariableDescriptorToSymbol[sharedVariableDescriptor]!! + + val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDescriptor) + + return IrCallImpl(originalSet.startOffset, originalSet.endOffset, elementProperty.setter!!.symbol, + elementPropertyDescriptor.setter!!).apply { + dispatchReceiver = IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableSymbol) putValueArgument(0, originalSet.value) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 1b620ded100..a526a0794d3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -17,10 +17,18 @@ package org.jetbrains.kotlin.backend.konan.ir import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.KonanBuiltIns +import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass +import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi2ir.generators.SymbolTable // This is what Context collects about IR. internal class Ir(val context: Context, val irModule: IrModuleFragment) { @@ -31,4 +39,63 @@ internal class Ir(val context: Context, val irModule: IrModuleFragment) { val originalModuleIndex = ModuleIndex(irModule) lateinit var moduleIndexForCodegen: ModuleIndex + + lateinit var symbols: Symbols } + +internal class Symbols(val context: Context, val symbolTable: SymbolTable) { + + val builtIns: KonanBuiltIns get() = context.builtIns + + private fun builtInsPackage(vararg packageNameSegments: String) = + builtIns.builtInsModule.getPackage(FqName.fromSegments(listOf(*packageNameSegments))).memberScope + + val refClass = symbolTable.referenceClass(builtIns.getKonanInternalClass("Ref")) + + val areEqualByValue = builtIns.getKonanInternalFunctions("areEqualByValue").map { + symbolTable.referenceSimpleFunction(it) + } + + val areEqual = symbolTable.referenceSimpleFunction(builtIns.getKonanInternalFunctions("areEqual").single()) + + val ThrowNullPointerException = symbolTable.referenceSimpleFunction( + builtIns.getKonanInternalFunctions("ThrowNullPointerException").single()) + + val ThrowNoWhenBranchMatchedException = symbolTable.referenceSimpleFunction( + builtIns.getKonanInternalFunctions("ThrowNoWhenBranchMatchedException").single()) + + val ThrowTypeCastException = symbolTable.referenceSimpleFunction( + builtIns.getKonanInternalFunctions("ThrowTypeCastException").single()) + + val stringBuilder = symbolTable.referenceClass( + builtInsPackage("kotlin", "text").getContributedClassifier( + Name.identifier("StringBuilder"), NoLookupLocation.FROM_BACKEND + ) as ClassDescriptor + ) + + val any = symbolTable.referenceClass(builtIns.any) + + val arrayOf = symbolTable.referenceSimpleFunction( + builtInsPackage("kotlin").getContributedFunctions( + Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND + ).single() + ) + + val array = symbolTable.referenceClass(builtIns.array) + + val valuesForEnum = symbolTable.referenceSimpleFunction( + builtIns.getKonanInternalFunctions("valuesForEnum").single()) + + val valueOfForEnum = symbolTable.referenceSimpleFunction( + builtIns.getKonanInternalFunctions("valueOfForEnum").single()) + + val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl) + val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl) + val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl) + val kMutableProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty0Impl) + val kMutableProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty1Impl) + val kMutableProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty2Impl) + val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl) + val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl) + +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrUtils.kt index f557158eae0..0b58063934a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/IrUtils.kt @@ -20,17 +20,16 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl -import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrElement +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.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.name.FqName -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeSubstitutor @@ -91,30 +90,38 @@ internal fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(superCo return constructorDescriptor } -internal fun ClassDescriptor.createSimpleDelegatingConstructor(superConstructorDescriptor: ClassConstructorDescriptor, - constructorDescriptor: ClassConstructorDescriptor, - startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin) +internal fun IrClass.addSimpleDelegatingConstructor(superConstructorSymbol: IrConstructorSymbol, + constructorDescriptor: ClassConstructorDescriptor, + origin: IrDeclarationOrigin) : IrConstructor { - val body = IrBlockBodyImpl(startOffset, endOffset, - listOf( - IrDelegatingConstructorCallImpl(startOffset, endOffset, superConstructorDescriptor).apply { - constructorDescriptor.valueParameters.forEachIndexed { idx, parameter -> - putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter)) - } - }, - IrInstanceInitializerCallImpl(startOffset, endOffset, this) - ) - ) - return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor, body).apply { - createParameterDeclarations() + + return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor -> + constructor.createParameterDeclarations() + + 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) + ) + ) + + this.declarations.add(constructor) } } internal fun Context.createArrayOfExpression(arrayElementType: KotlinType, arrayElements: List, startOffset: Int, endOffset: Int): IrExpression { - val kotlinPackage = irModule!!.descriptor.getPackage(FqName("kotlin")) - val genericArrayOfFun = kotlinPackage.memberScope.getContributedFunctions(Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND).first() + + 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)!! @@ -126,7 +133,7 @@ internal fun Context.createArrayOfExpression(arrayElementType: KotlinType, val arg0VarargElementType = valueParameter0.varargElementType!! val arg0 = IrVarargImpl(startOffset, endOffset, arg0VarargType, arg0VarargElementType, arrayElements) - return IrCallImpl(startOffset, endOffset, substitutedArrayOfFun, typeArguments).apply { + return IrCallImpl(startOffset, endOffset, genericArrayOfFunSymbol, substitutedArrayOfFun, typeArguments).apply { putValueArgument(0, arg0) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt index aeba9928f90..c696eb2b427 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt @@ -16,33 +16,55 @@ package org.jetbrains.kotlin.backend.konan.ir -import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.IrBlock import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase +import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrBindableSymbolBase import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType //-----------------------------------------------------------------------------// -interface IrReturnableBlock: IrBlock { - val descriptor: CallableDescriptor +interface IrReturnableBlockSymbol : IrFunctionSymbol, IrBindableSymbol + +interface IrReturnableBlock: IrBlock, IrSymbolOwner { + override val symbol: IrReturnableBlockSymbol + val descriptor: FunctionDescriptor } +class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) : + IrBindableSymbolBase(descriptor), + IrReturnableBlockSymbol + class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType, - override val descriptor: CallableDescriptor, origin: IrStatementOrigin? = null) + override val symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin? = null) : IrContainerExpressionBase(startOffset, endOffset, type, origin), IrReturnableBlock { + + override val descriptor = symbol.descriptor + constructor(startOffset: Int, endOffset: Int, type: KotlinType, - descriptor: CallableDescriptor, origin: IrStatementOrigin?, statements: List) : + descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null) : + this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin) + + constructor(startOffset: Int, endOffset: Int, type: KotlinType, + descriptor: FunctionDescriptor, origin: IrStatementOrigin?, statements: List) : this(startOffset, endOffset, type, descriptor, origin) { this.statements.addAll(statements) } + init { + symbol.bind(this) + } + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitBlock(this, data) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index 7eec5dfa1a0..e0c667bbb8d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.OverridingUtil import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny @@ -191,6 +190,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { } else { descriptor } - return context.specialDescriptorsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor)) + return context.specialDeclarationsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor)) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt index 3455be37ea7..d331f76d215 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BridgesBuilding.kt @@ -112,7 +112,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass { IrDeclarationOriginImpl("BRIDGE_METHOD") private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) { - val bridgeDescriptor = context.specialDescriptorsFactory.getBridgeDescriptor(descriptor) + val bridgeDescriptor = context.specialDeclarationsFactory.getBridgeDescriptor(descriptor) val target = descriptor.descriptor.target val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt index a2a778fde36..27ffef0ebb5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt @@ -19,17 +19,15 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.KonanConfigKeys.Companion.ENABLE_ASSERTIONS -import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.backend.konan.util.atMostOne -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptor import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrBinaryPrimitiveImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.isNullConst +import org.jetbrains.kotlin.ir.util.type import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -89,17 +87,17 @@ private class BuiltinOperatorTransformer(val context: Context) : IrElementTransf return when (descriptor) { irBuiltins.eqeq -> { - val binary = expression as IrBinaryPrimitiveImpl - lowerEqeq(binary.argument0, binary.argument1, expression.startOffset, expression.endOffset) + lowerEqeq(expression.getValueArgument(0)!!, expression.getValueArgument(1)!!, + expression.startOffset, expression.endOffset) } irBuiltins.eqeqeq -> lowerEqeqeq(expression) irBuiltins.throwNpe -> IrCallImpl(expression.startOffset, expression.endOffset, - builtIns.getKonanInternalFunctions("ThrowNullPointerException").single()) + context.ir.symbols.ThrowNullPointerException) irBuiltins.noWhenBranchMatchedException -> IrCallImpl(expression.startOffset, expression.endOffset, - builtIns.getKonanInternalFunctions("ThrowNoWhenBranchMatchedException").single()) + context.ir.symbols.ThrowNoWhenBranchMatchedException) else -> expression } @@ -129,29 +127,30 @@ private class BuiltinOperatorTransformer(val context: Context) : IrElementTransf } } - private fun selectEqualsFunction(lhs: IrExpression, rhs: IrExpression): FunctionDescriptor { + private fun selectEqualsFunction(lhs: IrExpression, rhs: IrExpression): IrSimpleFunctionSymbol { val nullableNothingType = builtIns.nullableNothingType if (lhs.type.isSubtypeOf(nullableNothingType) && rhs.type.isSubtypeOf(nullableNothingType)) { // Compare by reference if each part is either `Nothing` or `Nothing?`: - return irBuiltins.eqeqeq + return irBuiltins.eqeqeqSymbol } // TODO: areEqualByValue intrinsics are specially treated by code generator // and thus can be declared synthetically in the compiler instead of explicitly in the runtime. // Find a type-compatible `konan.internal.areEqualByValue` intrinsic: - builtIns.getKonanInternalFunctions("areEqualByValue").atMostOne { - lhs.type.isSubtypeOf(it.valueParameters[0].type) && rhs.type.isSubtypeOf(it.valueParameters[1].type) + context.ir.symbols.areEqualByValue.atMostOne { + lhs.type.isSubtypeOf(it.owner.valueParameters[0].type) && + rhs.type.isSubtypeOf(it.owner.valueParameters[1].type) }?.let { return it } return if (lhs.isNullConst() || rhs.isNullConst()) { // or compare by reference if left or right part is `null`: - irBuiltins.eqeqeq + irBuiltins.eqeqeqSymbol } else { // or use the general implementation: - builtIns.getKonanInternalFunctions("areEqual").single() + context.ir.symbols.areEqual } } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt index 23cd1d78b15..83707db211d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt @@ -33,10 +33,12 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl -import org.jetbrains.kotlin.ir.expressions.IrCallableReference -import org.jetbrains.kotlin.ir.expressions.IrConstKind -import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.util.constructors +import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName @@ -48,39 +50,48 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin")) private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor - private fun getKPropertyImplConstructorDescriptor(receiverTypes: List, - returnType: KotlinType, - isLocal: Boolean, - isMutable: Boolean) : ClassConstructorDescriptor { - val classDescriptor = + private fun getKPropertyImplConstructor(receiverTypes: List, + returnType: KotlinType, + isLocal: Boolean, + isMutable: Boolean) : Pair { + + val symbols = context.ir.symbols + + val classSymbol = if (isLocal) { assert(receiverTypes.isEmpty(), { "Local delegated property cannot have explicit receiver" }) when { - isMutable -> reflectionTypes.kLocalDelegatedMutablePropertyImpl - else -> reflectionTypes.kLocalDelegatedPropertyImpl + isMutable -> symbols.kLocalDelegatedMutablePropertyImpl + else -> symbols.kLocalDelegatedPropertyImpl } } else { when (receiverTypes.size) { 0 -> when { - isMutable -> reflectionTypes.kMutableProperty0Impl - else -> reflectionTypes.kProperty0Impl + isMutable -> symbols.kMutableProperty0Impl + else -> symbols.kProperty0Impl } 1 -> when { - isMutable -> reflectionTypes.kMutableProperty1Impl - else -> reflectionTypes.kProperty1Impl + isMutable -> symbols.kMutableProperty1Impl + else -> symbols.kProperty1Impl } 2 -> when { - isMutable -> reflectionTypes.kMutableProperty2Impl - else -> reflectionTypes.kProperty2Impl + isMutable -> symbols.kMutableProperty2Impl + else -> symbols.kProperty2Impl } else -> throw AssertionError("More than 2 receivers is not allowed") } } + + val classDescriptor = classSymbol.descriptor + val typeParameters = classDescriptor.declaredTypeParameters val arguments = (receiverTypes + listOf(returnType)) .mapIndexed { index, type -> typeParameters[index].typeConstructor to TypeProjectionImpl(type) } .toMap() - return classDescriptor.unsubstitutedPrimaryConstructor!!.substitute(TypeSubstitutor.create(arguments))!! + + val constructorSymbol = classSymbol.constructors.single() + + return constructorSymbol to constructorSymbol.descriptor.substitute(TypeSubstitutor.create(arguments))!! } private fun ClassDescriptor.replace(vararg type: KotlinType): SimpleType { @@ -90,14 +101,21 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa override fun lower(irFile: IrFile) { val kProperties = mutableMapOf>() - val arrayItemGetter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), - NoLookupLocation.FROM_BACKEND).single() + val arrayClass = context.ir.symbols.array + + val arrayItemGetter = arrayClass.functions.single { it.descriptor.name == Name.identifier("get") } + val typeParameterT = genericArrayType.declaredTypeParameters[0] val kPropertyImplType = reflectionTypes.kProperty1Impl.replace(context.builtIns.anyType, context.builtIns.anyType) val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(kPropertyImplType))) - val substitutedArrayItemGetter = arrayItemGetter.substitute(typeSubstitutor)!! + val substitutedArrayItemGetter = arrayItemGetter.descriptor.substitute(typeSubstitutor)!! - val kPropertiesField = createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor, genericArrayType.replace(kPropertyImplType)) + val kPropertiesField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, + DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, + createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor, + genericArrayType.replace(kPropertyImplType) + ) + ) irFile.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitFunction(declaration: IrFunction): IrStatement { @@ -120,22 +138,52 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa } - override fun visitCallableReference(expression: IrCallableReference): IrExpression { + override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { expression.transformChildrenVoid(this) - val propertyDescriptor = expression.descriptor as? VariableDescriptorWithAccessors - if (propertyDescriptor == null) return expression + val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null } - if (receiversCount == 1 && propertyDescriptor is PropertyDescriptor) // Has receiver and is not local delegated. - return createKProperty(expression, propertyDescriptor) + if (receiversCount == 1) // Has receiver. + return createKProperty(expression) else if (receiversCount == 2) - throw AssertionError("Callable reference to properties with two receivers is not allowed: $propertyDescriptor") + throw AssertionError("Callable reference to properties with two receivers is not allowed: ${expression.descriptor}") else { // Cache KProperties with no arguments. - val field = kProperties.getOrPut(propertyDescriptor) { - createKProperty(expression, propertyDescriptor) to kProperties.size + val field = kProperties.getOrPut(expression.descriptor) { + createKProperty(expression) to kProperties.size } - return IrCallImpl(expression.startOffset, expression.endOffset, substitutedArrayItemGetter).apply { - dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField) + return IrCallImpl( + expression.startOffset, expression.endOffset, + arrayItemGetter, substitutedArrayItemGetter + ).apply { + dispatchReceiver = + IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol) + + putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second)) + } + } + + } + + override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { + expression.transformChildrenVoid(this) + val propertyDescriptor = expression.descriptor + + val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null } + if (receiversCount == 2) + throw AssertionError("Callable reference to properties with two receivers is not allowed: $propertyDescriptor") + else { // Cache KProperties with no arguments. + // TODO: what about `receiversCount == 1` case? + val field = kProperties.getOrPut(propertyDescriptor) { + createLocalKProperty(expression, propertyDescriptor) to kProperties.size + } + + return IrCallImpl( + expression.startOffset, expression.endOffset, + arrayItemGetter, substitutedArrayItemGetter + ).apply { + dispatchReceiver = + IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol) + putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second)) } } @@ -146,66 +194,68 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa if (kProperties.isNotEmpty()) { val initializers = kProperties.values.sortedBy { it.second }.map { it.first } // TODO: move to object for lazy initialization. - irFile.declarations.add(0, IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, - kPropertiesField, - IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, - context.createArrayOfExpression(kPropertyImplType, initializers, UNDEFINED_OFFSET, UNDEFINED_OFFSET)))) + irFile.declarations.add(0, kPropertiesField.apply { + initializer = IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, + context.createArrayOfExpression(kPropertyImplType, initializers, UNDEFINED_OFFSET, UNDEFINED_OFFSET)) + }) } } - private fun createKProperty(expression: IrCallableReference, propertyDescriptor: VariableDescriptorWithAccessors): IrCallImpl { + private fun createKProperty(expression: IrPropertyReference): IrCallImpl { val startOffset = expression.startOffset val endOffset = expression.endOffset val receiverTypes = mutableListOf() - val isLocal = propertyDescriptor !is PropertyDescriptor + + val propertyDescriptor = expression.descriptor val returnType = propertyDescriptor.type - val getterCallableReference = propertyDescriptor.getter.let { - if (it == null || isLocal) null - else { - val getter = propertyDescriptor.getter!! - getter.extensionReceiverParameter.let { - if (it != null && expression.extensionReceiver == null) - receiverTypes.add(it.type) - } - getter.dispatchReceiverParameter.let { - if (it != null && expression.dispatchReceiver == null) - receiverTypes.add(it.type) - } - val getterKFunctionType = context.reflectionTypes.getKFunctionType( - annotations = Annotations.EMPTY, - receiverType = receiverTypes.firstOrNull(), - parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]), - returnType = returnType) - IrFunctionReferenceImpl(startOffset, endOffset, getterKFunctionType, getter, null).apply { - dispatchReceiver = expression.dispatchReceiver - extensionReceiver = expression.extensionReceiver - } + val getterCallableReference = propertyDescriptor.getter?.let { getter -> + getter.extensionReceiverParameter.let { + if (it != null && expression.extensionReceiver == null) + receiverTypes.add(it.type) + } + getter.dispatchReceiverParameter.let { + if (it != null && expression.dispatchReceiver == null) + receiverTypes.add(it.type) + } + val getterKFunctionType = context.reflectionTypes.getKFunctionType( + annotations = Annotations.EMPTY, + receiverType = receiverTypes.firstOrNull(), + parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]), + returnType = returnType) + IrFunctionReferenceImpl( + startOffset, endOffset, + getterKFunctionType, expression.getter!!, getter, null + ).apply { + dispatchReceiver = expression.dispatchReceiver + extensionReceiver = expression.extensionReceiver } } - val setterCallableReference = propertyDescriptor.setter.let { - if (it == null || isLocal || !isKMutablePropertyType(expression.type)) null + val setterCallableReference = propertyDescriptor.setter?.let { + if (!isKMutablePropertyType(expression.type)) null else { val setterKFunctionType = context.reflectionTypes.getKFunctionType( annotations = Annotations.EMPTY, receiverType = receiverTypes.firstOrNull(), parameterTypes = if (receiverTypes.size < 2) listOf(returnType) else listOf(receiverTypes[1], returnType), returnType = context.builtIns.unitType) - IrFunctionReferenceImpl(startOffset, endOffset, setterKFunctionType, it, null).apply { + IrFunctionReferenceImpl( + startOffset, endOffset, + setterKFunctionType, expression.setter!!, it, null + ).apply { dispatchReceiver = expression.dispatchReceiver extensionReceiver = expression.extensionReceiver } } } - val descriptor = getKPropertyImplConstructorDescriptor( + val (symbol, descriptor) = getKPropertyImplConstructor( receiverTypes = receiverTypes, returnType = returnType, - isLocal = isLocal, + isLocal = false, isMutable = setterCallableReference != null) - val initializer = IrCallImpl(startOffset, endOffset, descriptor).apply { + val initializer = IrCallImpl(startOffset, endOffset, symbol, descriptor).apply { putValueArgument(0, IrConstImpl(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString())) if (getterCallableReference != null) @@ -216,6 +266,25 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa return initializer } + private fun createLocalKProperty(expression: IrLocalDelegatedPropertyReference, propertyDescriptor: VariableDescriptorWithAccessors): IrCallImpl { + val startOffset = expression.startOffset + val endOffset = expression.endOffset + + val returnType = propertyDescriptor.type + + val (symbol, descriptor) = getKPropertyImplConstructor( + receiverTypes = emptyList(), + returnType = returnType, + isLocal = true, + isMutable = false) + + val initializer = IrCallImpl(startOffset, endOffset, symbol, descriptor).apply { + putValueArgument(0, IrConstImpl(startOffset, endOffset, + context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString())) + } + return initializer + } + private fun isKMutablePropertyType(type: KotlinType): Boolean { val arguments = type.arguments val expectedClassDescriptor = when (arguments.size) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt index 8ba2b79fd97..afb0cb0c303 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/EnumClassLowering.kt @@ -22,26 +22,23 @@ import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions +import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.ir.createArrayOfExpression import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor -import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructor +import org.jetbrains.kotlin.backend.konan.ir.addSimpleDelegatingConstructor import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructorDescriptor import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.util.createParameterDeclarations -import org.jetbrains.kotlin.ir.util.dump -import org.jetbrains.kotlin.ir.util.transform -import org.jetbrains.kotlin.ir.util.transformFlat +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +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.FqName @@ -53,43 +50,47 @@ import org.jetbrains.kotlin.types.TypeSubstitutor internal class EnumSyntheticFunctionsBuilder(val context: Context) { fun buildValuesExpression(startOffset: Int, endOffset: Int, enumClassDescriptor: ClassDescriptor): IrExpression { - val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(enumClassDescriptor) + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor) val typeParameterT = genericValuesDescriptor.typeParameters[0] val enumClassType = enumClassDescriptor.defaultType val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) val substitutedValueOf = genericValuesDescriptor.substitute(typeSubstitutor)!! - return IrCallImpl(startOffset, endOffset, substitutedValueOf, mapOf(typeParameterT to enumClassType)) + return IrCallImpl(startOffset, endOffset, + genericValuesSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType)) .apply { val receiver = IrGetObjectValueImpl(startOffset, endOffset, - loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor) - putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver)) + loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol) + putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver)) } } fun buildValueOfExpression(startOffset: Int, endOffset: Int, enumClassDescriptor: ClassDescriptor, value: IrExpression): IrExpression { - val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(enumClassDescriptor) + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor) val typeParameterT = genericValueOfDescriptor.typeParameters[0] val enumClassType = enumClassDescriptor.defaultType val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) val substitutedValueOf = genericValueOfDescriptor.substitute(typeSubstitutor)!! - return IrCallImpl(startOffset, endOffset, substitutedValueOf, mapOf(typeParameterT to enumClassType)) + return IrCallImpl(startOffset, endOffset, + genericValueOfSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType)) .apply { putValueArgument(0, value) val receiver = IrGetObjectValueImpl(startOffset, endOffset, - loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor) - putValueArgument(1, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver)) + loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol) + putValueArgument(1, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver)) } } - private val genericValueOfDescriptor = context.builtIns.getKonanInternalFunctions("valueOfForEnum").single() + private val genericValueOfSymbol = context.ir.symbols.valueOfForEnum + private val genericValueOfDescriptor = genericValueOfSymbol.descriptor - private val genericValuesDescriptor = context.builtIns.getKonanInternalFunctions("valuesForEnum").single() + private val genericValuesSymbol = context.ir.symbols.valuesForEnum + private val genericValuesDescriptor = genericValuesSymbol.descriptor } internal class EnumUsageLowering(val context: Context) @@ -142,10 +143,10 @@ internal class EnumUsageLowering(val context: Context) Name.identifier("enumValues"), NoLookupLocation.FROM_BACKEND).single() private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClassDescriptor: ClassDescriptor, name: Name): IrExpression { - val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(enumClassDescriptor) + val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor) val ordinal = loweredEnum.entriesMap[name]!! - return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetter).apply { - dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter) + return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetterSymbol, loweredEnum.itemGetterDescriptor).apply { + dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol) putValueArgument(0, IrConstImpl.int(startOffset, endOffset, enumClassDescriptor.module.builtIns.intType, ordinal)) } } @@ -169,11 +170,11 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { } private inner class EnumClassTransformer(val irClass: IrClass) { - private val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(irClass.descriptor) + private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass.descriptor) private val enumEntryOrdinals = mutableMapOf() - private val loweredEnumConstructors = mutableMapOf() + private val loweredEnumConstructors = mutableMapOf() private val descriptorToIrConstructorWithDefaultArguments = mutableMapOf() - private val defaultEnumEntryConstructors = mutableMapOf() + private val defaultEnumEntryConstructors = mutableMapOf() private val loweredEnumConstructorParameters = mutableMapOf() private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context) @@ -205,7 +206,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { blockBody.statements.transformFlat { if (it is IrEnumConstructorCall) listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset, - irClass.descriptor)) + irClass.symbol)) else null } } @@ -254,21 +255,21 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val constructors = mutableSetOf() descriptor.constructors.forEach { - val loweredEnumConstructor = loweredEnumConstructors[it]!! + val loweredEnumConstructorSymbol = loweredEnumConstructors[it]!!.symbol + val loweredEnumConstructor = loweredEnumConstructorSymbol.descriptor val constructorDescriptor = defaultClassDescriptor.createSimpleDelegatingConstructorDescriptor(loweredEnumConstructor) - val constructor = defaultClassDescriptor.createSimpleDelegatingConstructor( - loweredEnumConstructor, constructorDescriptor, - startOffset, endOffset, DECLARATION_ORIGIN_ENUM) + val constructor = defaultClass.addSimpleDelegatingConstructor( + loweredEnumConstructorSymbol, constructorDescriptor, + DECLARATION_ORIGIN_ENUM) constructors.add(constructorDescriptor) - defaultClass.declarations.add(constructor) - defaultEnumEntryConstructors.put(loweredEnumConstructor, constructorDescriptor) + defaultEnumEntryConstructors.put(loweredEnumConstructor, constructor) val irConstructor = descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor] if (irConstructor != null) { it.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> val loweredArgument = loweredEnumConstructor.valueParameters[argument.loweredIndex()] val body = irConstructor.getDefault(loweredArgument)!! - body.transformChildrenVoid(ParameterMapper(constructorDescriptor)) + body.transformChildrenVoid(ParameterMapper(constructor)) constructor.putDefault(constructorDescriptor.valueParameters[loweredArgument.index], body) } } @@ -285,12 +286,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { } private fun createImplObject() { - val startOffset = irClass.startOffset - val endOffset = irClass.endOffset - val implObjectDescriptor = loweredEnum.implObjectDescriptor - val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor) - - implObject.createParameterDeclarations() + val implObject = loweredEnum.implObject val enumEntries = mutableListOf() var i = 0 @@ -307,9 +303,9 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { if (body is IrSyntheticBody) { when (body.kind) { IrSyntheticBodyKind.ENUM_VALUEOF -> - declaration.body = createSyntheticValueOfMethodBody(declaration.descriptor) + declaration.body = createSyntheticValueOfMethodBody(declaration) IrSyntheticBodyKind.ENUM_VALUES -> - declaration.body = createSyntheticValuesMethodBody(declaration.descriptor) + declaration.body = createSyntheticValuesMethodBody(declaration) } } } @@ -320,12 +316,12 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { ++i } - val constructorOfAny = irClass.descriptor.module.builtIns.any.constructors.first() - val constructor = implObjectDescriptor.createSimpleDelegatingConstructor( - constructorOfAny, implObjectDescriptor.constructors.single(), - startOffset, endOffset, DECLARATION_ORIGIN_ENUM) + val constructorOfAny = context.ir.symbols.any.constructors.single() + + implObject.addSimpleDelegatingConstructor( + constructorOfAny, implObject.descriptor.constructors.single(), + DECLARATION_ORIGIN_ENUM) - implObject.declarations.add(constructor) implObject.declarations.add(createSyntheticValuesPropertyDeclaration(enumEntries)) irClass.declarations.add(implObject) @@ -337,47 +333,42 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType, enumEntries.sortedBy { it.descriptor.name }.map { it.initializerExpression!! }, startOffset, endOffset) - val irField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, - loweredEnum.valuesProperty, - IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)) + val irField = loweredEnum.valuesField.apply { + initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer) + } - val getter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.valuesGetter) - - getter.createParameterDeclarations() + val getter = loweredEnum.valuesGetter val receiver = IrGetObjectValueImpl(startOffset, endOffset, - loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor) - val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver) - val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter, value) + loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol) + val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver) + val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol, value) getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement)) val irProperty = IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, - false, loweredEnum.valuesProperty, irField, getter, null) + false, loweredEnum.valuesField.descriptor, irField, getter, null) return irProperty } - private object DECLARATION_ORIGIN_ENUM : - IrDeclarationOriginImpl("ENUM") - - private fun createSyntheticValuesMethodBody(descriptor: FunctionDescriptor): IrBody { + private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody { val startOffset = irClass.startOffset val endOffset = irClass.endOffset val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass.descriptor) return IrBlockBodyImpl(startOffset, endOffset, - listOf(IrReturnImpl(startOffset, endOffset, descriptor, valuesExpression)) + listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valuesExpression)) ) } - private fun createSyntheticValueOfMethodBody(descriptor: FunctionDescriptor): IrBody { + private fun createSyntheticValueOfMethodBody(declaration: IrFunction): IrBody { val startOffset = irClass.startOffset val endOffset = irClass.endOffset - val value = IrGetValueImpl(startOffset, endOffset, descriptor.valueParameters[0]) + val value = IrGetValueImpl(startOffset, endOffset, declaration.valueParameters[0].symbol) val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass.descriptor, value) return IrBlockBodyImpl( startOffset, endOffset, - listOf(IrReturnImpl(startOffset, endOffset, descriptor, valueOfExpression)) + listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valueOfExpression)) ) } @@ -397,11 +388,13 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { enumConstructor.body!! // will be transformed later ) + loweredEnumConstructors[constructorDescriptor] = loweredEnumConstructor + loweredEnumConstructor.createParameterDeclarations() enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { val body = enumConstructor.getDefault(it)!! - body.transformChildrenVoid(ParameterMapper(constructorDescriptor)) + body.transformChildrenVoid(ParameterMapper(enumConstructor)) loweredEnumConstructor.putDefault(loweredConstructorDescriptor.valueParameters[it.loweredIndex()], body) descriptorToIrConstructorWithDefaultArguments[loweredConstructorDescriptor] = loweredEnumConstructor } @@ -428,8 +421,6 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { loweredConstructorDescriptor.returnType = constructorDescriptor.returnType - loweredEnumConstructors[constructorDescriptor] = loweredConstructorDescriptor - return loweredConstructorDescriptor } @@ -450,14 +441,15 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { irClass.transformChildrenVoid(EnumClassBodyTransformer()) } - private inner class InEnumClassConstructor(val enumClassConstructor: ClassConstructorDescriptor) : + private inner class InEnumClassConstructor(val enumClassConstructor: IrConstructor) : EnumConstructorCallTransformer { override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression { val startOffset = enumConstructorCall.startOffset val endOffset = enumConstructorCall.endOffset val origin = enumConstructorCall.origin - val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, enumConstructorCall.descriptor) + val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, + enumConstructorCall.symbol, enumConstructorCall.descriptor) assert(result.descriptor.valueParameters.size == 2) { "Enum(String, Int) constructor call expected:\n${result.dump()}" @@ -471,8 +463,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor") } - result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter, origin)) - result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter, origin)) + result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter.symbol, origin)) + result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter.symbol, origin)) return result } @@ -486,10 +478,13 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor") } - val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredDelegatedConstructor) + val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, + loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor) - result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[0])) - result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1])) + result.putValueArgument(0, + IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[0].symbol)) + result.putValueArgument(1, + IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1].symbol)) descriptor.valueParameters.forEach { valueParameter -> result.putValueArgument(valueParameter.loweredIndex(), delegatingConstructorCall.getValueArgument(valueParameter)) @@ -512,7 +507,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor") } - val result = createConstructorCall(startOffset, endOffset, loweredConstructor) + val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol) result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name)) result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal)) @@ -529,17 +524,19 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { throw AssertionError("Unexpected delegating constructor call within enum entry: $enumEntry") } - abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor): IrMemberAccessExpression + abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrMemberAccessExpression } private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) { - override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) - = IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor) + override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) + = IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor, loweredConstructor.descriptor) } private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) { - override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) - = IrCallImpl(startOffset, endOffset, defaultEnumEntryConstructors[loweredConstructor] ?: loweredConstructor) + override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall { + return IrCallImpl(startOffset, endOffset, + defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol ?: loweredConstructor) + } } private inner class EnumClassBodyTransformer : IrElementTransformerVoid() { @@ -571,7 +568,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { enumConstructorCallTransformer = InEnumEntryClassConstructor(containingClass) } else if (containingClass.kind == ClassKind.ENUM_CLASS) { assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" } - enumConstructorCallTransformer = InEnumClassConstructor(constructorDescriptor) + enumConstructorCallTransformer = InEnumClassConstructor(declaration) } val result = super.visitConstructor(declaration) @@ -605,10 +602,15 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { override fun visitGetValue(expression: IrGetValue): IrExpression { val loweredParameter = loweredEnumConstructorParameters[expression.descriptor] - if (loweredParameter != null) - return IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter, expression.origin) - else + if (loweredParameter != null) { + val loweredEnumConstructor = loweredEnumConstructors[expression.descriptor.containingDeclaration]!! + val loweredIrParameter = loweredEnumConstructor.valueParameters[loweredParameter.index] + assert(loweredIrParameter.descriptor == loweredParameter) + return IrGetValueImpl(expression.startOffset, expression.endOffset, + loweredIrParameter.symbol, expression.origin) + } else { return expression + } } } } @@ -616,14 +618,14 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass { private fun ValueParameterDescriptor.loweredIndex(): Int = index + 2 -private class ParameterMapper(val originalDescriptor: FunctionDescriptor) : IrElementTransformerVoid() { +private class ParameterMapper(val originalConstructor: IrConstructor) : IrElementTransformerVoid() { override fun visitGetValue(expression: IrGetValue): IrExpression { val descriptor = expression.descriptor when (descriptor) { is ValueParameterDescriptor -> { return IrGetValueImpl(expression.startOffset, expression.endOffset, - originalDescriptor.valueParameters[descriptor.index]) + originalConstructor.valueParameters[descriptor.index].symbol) } } return expression diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt index 37460404c9d..d1ebf7288b2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FinallyBlocksLowering.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl @@ -204,17 +205,21 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass name = Name.identifier("t"), outType = context.builtIns.throwable.defaultType ) + val catchParameter = IrVariableImpl( + startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter) + val syntheticTry = IrTryImpl( startOffset = startOffset, endOffset = endOffset, type = context.builtIns.nothingType, tryResult = transformedTry, catches = listOf( - irCatch(parameter, - irBlock { + irCatch(catchParameter).apply { + result = irBlock { +finallyExpression.copy() - +irThrow(irGet(parameter)) - })), + +irThrow(irGet(catchParameter.symbol)) + } + }), finallyExpression = null ) using(TryScope(syntheticTry, transformedFinallyExpression, this)) { @@ -243,22 +248,15 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass +finallyExpression.copy() } else -> irBlock(value, null, returnType) { - val tmp = IrTemporaryVariableDescriptorImpl( - functionDescriptor, - "tmp${tempIndex++}".synthesizedName, - returnType - ) - +irVar(tmp, irReturnableBlock(descriptor) { + val tmp = irTemporary(irReturnableBlock(descriptor) { +irReturn(descriptor, value) }) +finallyExpression.copy() - +irGet(tmp) + +irGet(tmp.symbol) } } } - private var tempIndex = 0 - private fun getFakeFunctionDescriptor(name: String, returnType: KotlinType): FunctionDescriptor { return SimpleFunctionDescriptorImpl.create( functionDescriptor, diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt index 1ec2f338dbe..5e53282b70f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InitializersLowering.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -46,8 +47,8 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass { fun lowerInitializers() { collectAndRemoveInitializers() - val initializerMethodDescriptor = createInitializerMethod() - lowerConstructors(initializerMethodDescriptor) + val initializerMethodSymbol = createInitializerMethod() + lowerConstructors(initializerMethodSymbol) } object STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER : @@ -72,13 +73,12 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass { override fun visitField(declaration: IrField): IrStatement { val initializer = declaration.initializer ?: return declaration - val propertyDescriptor = declaration.descriptor val startOffset = initializer.startOffset val endOffset = initializer.endOffset initializers.add(IrBlockImpl(startOffset, endOffset, context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER, listOf( - IrSetFieldImpl(startOffset, endOffset, propertyDescriptor, - IrGetValueImpl(startOffset, endOffset, irClass.descriptor.thisAsReceiverParameter), + IrSetFieldImpl(startOffset, endOffset, declaration.symbol, + IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), initializer.expression, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER)))) declaration.initializer = null return declaration @@ -92,7 +92,7 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass { } } - private fun createInitializerMethod(): FunctionDescriptor? { + private fun createInitializerMethod(): IrSimpleFunctionSymbol? { if (irClass.descriptor.hasPrimaryConstructor()) return null // Place initializers in the primary constructor. val initializerMethodDescriptor = SimpleFunctionDescriptorImpl.create( @@ -118,10 +118,10 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass { irClass.declarations.add(initializer) - return initializerMethodDescriptor + return initializer.symbol } - private fun lowerConstructors(initializerMethodDescriptor: FunctionDescriptor?) { + private fun lowerConstructors(initializerMethodSymbol: IrSimpleFunctionSymbol?) { irClass.transformChildrenVoid(object : IrElementTransformerVoid() { override fun visitClass(declaration: IrClass): IrStatement { @@ -135,14 +135,14 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass { blockBody.statements.transformFlat { when { it is IrInstanceInitializerCall -> { - if (initializerMethodDescriptor == null) { + if (initializerMethodSymbol == null) { assert(declaration.descriptor.isPrimary) initializers } else { val startOffset = it.startOffset val endOffset = it.endOffset - listOf(IrCallImpl(startOffset, endOffset, initializerMethodDescriptor).apply { - dispatchReceiver = IrGetValueImpl(startOffset, endOffset, irClass.descriptor.thisAsReceiverParameter) + listOf(IrCallImpl(startOffset, endOffset, initializerMethodSymbol).apply { + dispatchReceiver = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol) }) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt index 723cd97da65..5982899ee9b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt @@ -23,14 +23,14 @@ import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl -import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -44,7 +44,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { private inner class InnerClassTransformer(val irClass: IrClass) { val classDescriptor = irClass.descriptor - lateinit var outerThisFieldDescriptor: PropertyDescriptor + lateinit var outerThisFieldSymbol: IrFieldSymbol fun lowerInnerClass() { if (!irClass.descriptor.isInner) return @@ -54,17 +54,10 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { lowerConstructors() } - object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS : - IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") - private fun createOuterThisField() { - outerThisFieldDescriptor = context.specialDescriptorsFactory.getOuterThisFieldDescriptor(classDescriptor) - - irClass.declarations.add(IrFieldImpl( - irClass.startOffset, irClass.endOffset, - DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS, - outerThisFieldDescriptor - )) + val field = context.specialDeclarationsFactory.getOuterThisField(classDescriptor) + outerThisFieldSymbol = field.symbol + irClass.declarations.add(field) } private fun lowerConstructors() { @@ -86,9 +79,9 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { blockBody.statements.add( 0, IrSetFieldImpl( - startOffset, endOffset, outerThisFieldDescriptor, - IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter), - IrGetValueImpl(startOffset, endOffset, irConstructor.descriptor.dispatchReceiverParameter!!) + startOffset, endOffset, outerThisFieldSymbol, + IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), + IrGetValueImpl(startOffset, endOffset, irConstructor.dispatchReceiverParameter!!.symbol) ) ) } @@ -106,7 +99,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { if (implicitThisClass == classDescriptor) return expression - val constructorDescriptor = currentFunction!!.scope.scopeOwner as? ConstructorDescriptor + val constructorSymbol = currentFunction!!.scope.scopeOwnerSymbol as? IrConstructorSymbol val startOffset = expression.startOffset val endOffset = expression.endOffset @@ -114,14 +107,15 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { var irThis: IrExpression var innerClass: ClassDescriptor - if (constructorDescriptor == null || constructorDescriptor.constructedClass != classDescriptor) { + if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) { innerClass = classDescriptor - irThis = IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter, origin) + irThis = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol, origin) } else { // For constructor we have outer class as dispatchReceiverParameter. innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?: throw AssertionError("No containing class for inner class $classDescriptor") - irThis = IrGetValueImpl(startOffset, endOffset, constructorDescriptor.dispatchReceiverParameter!!, origin) + irThis = IrGetValueImpl(startOffset, endOffset, + constructorSymbol.owner.dispatchReceiverParameter!!.symbol, origin) } while (innerClass != implicitThisClass) { @@ -131,8 +125,8 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { return expression } - val outerThisField = context.specialDescriptorsFactory.getOuterThisFieldDescriptor(innerClass) - irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin) + val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass) + irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, irThis, origin) val outer = innerClass.containingDeclaration innerClass = outer as? ClassDescriptor ?: diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StringConcatenationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StringConcatenationLowering.kt index baeb68887cd..5b866c6840f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StringConcatenationLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/StringConcatenationLowering.kt @@ -18,23 +18,21 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlock import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.signature2Descriptor -import org.jetbrains.kotlin.ir.builders.irLetSequence +import org.jetbrains.kotlin.backend.konan.util.atMostOne import org.jetbrains.kotlin.builtins.PrimitiveType -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrSymbolDeclaration +import org.jetbrains.kotlin.ir.declarations.* 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.util.constructors +import org.jetbrains.kotlin.ir.util.functions +import org.jetbrains.kotlin.ir.util.type import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType @@ -57,30 +55,36 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower private val typesWithSpecialAppendFunction = PrimitiveType.values().map { builtIns.getPrimitiveKotlinType(it) } + builtIns.stringType - private val kotlinTextFqName = FqName.fromSegments(listOf("kotlin", "text")) private val nameToString = Name.identifier("toString") - private val nameStringBuilder = Name.identifier("StringBuilder") private val nameAppend = Name.identifier("append") - private val classStringBuilder = builtIns.builtInsModule.getPackage(kotlinTextFqName). - memberScope.getContributedClassifier(nameStringBuilder, - NoLookupLocation.FROM_BACKEND) as ClassDescriptor + private val stringBuilder = context.ir.symbols.stringBuilder //TODO: calculate and pass string length to the constructor. - private val constructor = classStringBuilder.constructors.firstOrNull { - it.valueParameters.size == 0 - }!! + private val constructor = stringBuilder.constructors.single { + it.owner.valueParameters.size == 0 + } - private val toStringFunction = classStringBuilder.signature2Descriptor(nameToString)!! - private val defaultAppendFunction = - classStringBuilder.signature2Descriptor(nameAppend, arrayOf(builtIns.nullableAnyType))!! + private val toStringFunction = stringBuilder.functions.single { + it.owner.valueParameters.size == 0 && it.descriptor.name == nameToString + } + private val defaultAppendFunction = stringBuilder.functions.single { + it.descriptor.name == nameAppend && + it.owner.valueParameters.size == 1 && + it.owner.valueParameters.single().type == builtIns.nullableAnyType + } - private val appendFunctions: Map = - typesWithSpecialAppendFunction.map { - it to classStringBuilder.signature2Descriptor(nameAppend, arrayOf(it)) + + 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 + } }.toMap() - private fun typeToAppendFunction(type : KotlinType) : FunctionDescriptor { + private fun typeToAppendFunction(type : KotlinType) : IrFunctionSymbol { return appendFunctions[type]?:defaultAppendFunction } @@ -89,11 +93,8 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower expression.transformChildrenVoid(this) val blockBuilder = buildersStack.last() - return blockBuilder.irLetSequence( - value = blockBuilder.irCall(constructor), - startOffset = expression.startOffset, - endOffset = expression.endOffset, - resultType = expression.type) { stringBuilderImpl -> + return blockBuilder.irBlock(expression) { + val stringBuilderImpl = irTemporary(irCall(constructor)).symbol expression.arguments.forEach { arg -> val appendFunction = typeToAppendFunction(arg.type) +irCall(appendFunction).apply { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt index 8cb8b9c67cf..15e5699f6c5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/TypeOperatorLowering.kt @@ -19,9 +19,7 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.FunctionLoweringPass import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* @@ -29,6 +27,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.types.KotlinType @@ -42,19 +41,17 @@ import org.jetbrains.kotlin.types.typeUtil.makeNullable */ internal class TypeOperatorLowering(val context: Context) : FunctionLoweringPass { override fun lower(irFunction: IrFunction) { - val transformer = TypeOperatorTransformer(context, irFunction.descriptor) + val transformer = TypeOperatorTransformer(context, irFunction.symbol) irFunction.transformChildrenVoid(transformer) } } -private class TypeOperatorTransformer(val context: Context, val function: FunctionDescriptor) : IrElementTransformerVoid() { +private class TypeOperatorTransformer(val context: Context, val function: IrFunctionSymbol) : IrElementTransformerVoid() { private val builder = context.createIrBuilder(function) - val throwTypeCastException by lazy { - context.builtIns.getKonanInternalFunctions("ThrowTypeCastException").single() - } + val throwTypeCastException = context.ir.symbols.ThrowTypeCastException override fun visitFunction(declaration: IrFunction): IrStatement { // ignore inner functions during this pass @@ -93,7 +90,7 @@ private class TypeOperatorTransformer(val context: Context, val function: Functi expression.argument.type.isNullable() -> { with (builder) { - irLet(expression.argument) { argument -> + irLetS(expression.argument) { argument -> irIfThenElse( type = expression.type, condition = irEqeqeq(irGet(argument), irNull()), @@ -123,7 +120,7 @@ private class TypeOperatorTransformer(val context: Context, val function: Functi val typeOperand = expression.typeOperand.erasure() return builder.irBlock(expression) { - +irLet(expression.argument) { variable -> + +irLetS(expression.argument) { variable -> irIfThenElse(expression.type, condition = irIs(irGet(variable), typeOperand), thenPart = irImplicitCast(irGet(variable), typeOperand), diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt index 6e4da26efef..fb083cc67b0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/VarargLowering.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl +import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.FqName @@ -138,31 +139,31 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar descriptor = arrayHandle.setMethodDescriptor, typeArguments = null ) - setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.descriptor) - setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.descriptor) else irConstInt(i)) - setArrayElementCall.putValueArgument(1, irGet(dst.descriptor)) + setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol) + setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i)) + setArrayElementCall.putValueArgument(1, irGet(dst.symbol)) block.statements.add(setArrayElementCall) if (hasSpreadElement) { - block.statements.add(incrementVariable(indexTmpVariable.descriptor, kIntOne)) + block.statements.add(incrementVariable(indexTmpVariable.symbol, kIntOne)) } } else { - val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.descriptor)), "length".synthesizedString) + val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString) block.statements.add(arraySizeVariable) val copyCall = irCall(arrayHandle.copyRangeToDescriptor, null).apply { - extensionReceiver = irGet(dst.descriptor) - putValueArgument(0, irGet(arrayTmpVariable.descriptor)) /* destination */ + extensionReceiver = irGet(dst.symbol) + putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */ putValueArgument(1, kIntZero) /* fromIndex */ - putValueArgument(2, irGet(arraySizeVariable.descriptor)) /* toIndex */ - putValueArgument(3, irGet(indexTmpVariable.descriptor)) /* destinationIndex */ + putValueArgument(2, irGet(arraySizeVariable.symbol)) /* toIndex */ + putValueArgument(3, irGet(indexTmpVariable.symbol)) /* destinationIndex */ } block.statements.add(copyCall) - block.statements.add(incrementVariable(indexTmpVariable.descriptor, - irGet(arraySizeVariable.descriptor))) + block.statements.add(incrementVariable(indexTmpVariable.symbol, + irGet(arraySizeVariable.symbol))) log("element:$i:spread element> ${ir2string(element.expression)}") } } } - block.statements.add(irGet(arrayTmpVariable.descriptor)) + block.statements.add(irGet(arrayTmpVariable.symbol)) return block } } @@ -203,9 +204,9 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar } } - private fun IrBuilderWithScope.incrementVariable(descriptor: VariableDescriptor, value: IrExpression): IrExpression { - return irSetVar(descriptor, intPlus().apply { - dispatchReceiver = irGet(descriptor) + private fun IrBuilderWithScope.incrementVariable(symbol: IrVariableSymbol, value: IrExpression): IrExpression { + return irSetVar(symbol, intPlus().apply { + dispatchReceiver = irGet(symbol) putValueArgument(0, value) }) } @@ -216,7 +217,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar 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.descriptor)) + val arraySize = irArraySize(arrayHandle, irGet(it.second.symbol)) increment(result, arraySize) } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt new file mode 100644 index 00000000000..07c70027a3a --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUnboundSymbolReplacer.kt @@ -0,0 +1,386 @@ +package org.jetbrains.kotlin.ir.util + +import org.jetbrains.kotlin.backend.common.pop +import org.jetbrains.kotlin.backend.common.push +import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol +import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.visitors.* +import org.jetbrains.kotlin.psi2ir.generators.ModuleDependenciesGenerator +import org.jetbrains.kotlin.psi2ir.generators.SymbolTable + +@Deprecated("") +internal fun IrModuleFragment.replaceUnboundSymbols(context: Context) { + val collector = DeclarationSymbolCollector() + with(collector) { + with(irBuiltins) { + for (op in arrayOf(eqeqeqFun, eqeqFun, lt0Fun, lteq0Fun, gt0Fun, gteq0Fun, throwNpeFun, booleanNotFun, + noWhenBranchMatchedExceptionFun)) { + + register(op.symbol) + } + } + } + this.acceptVoid(collector) + + val symbolTable = context.ir.symbols.symbolTable + + this.transformChildrenVoid(IrUnboundSymbolReplacer(symbolTable, collector.descriptorToSymbol)) + + // Generate missing external stubs: + ModuleDependenciesGenerator(context.psi2IrGeneratorContext).generateUnboundSymbolsAsDependencies(this) + + // Merge duplicated module and package declarations: + this.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) {} + + override fun visitModuleFragment(declaration: IrModuleFragment) { + declaration.dependencyModules.forEach { it.acceptVoid(this) } + + val dependencyModules = declaration.dependencyModules.groupBy { it.descriptor }.map { (_, fragments) -> + fragments.reduce { firstModule, nextModule -> + firstModule.apply { + mergeFrom(nextModule) + } + } + } + + declaration.dependencyModules.clear() + declaration.dependencyModules.addAll(dependencyModules) + } + + }) +} + +private fun IrModuleFragment.mergeFrom(other: IrModuleFragment): Unit { + assert(this.files.isEmpty()) + assert(other.files.isEmpty()) + + val thisPackages = this.externalPackageFragments.groupBy { it.packageFragmentDescriptor } + other.externalPackageFragments.forEach { + val thisPackage = thisPackages[it.packageFragmentDescriptor]?.single() + if (thisPackage == null) { + this.externalPackageFragments.add(it) + } else { + thisPackage.declarations.addAll(it.declarations) + } + } +} + +private class DeclarationSymbolCollector : IrElementVisitorVoid { + + val descriptorToSymbol = mutableMapOf() + + fun register(symbol: IrSymbol) { + descriptorToSymbol[symbol.descriptor] = symbol + } + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + + if (element is IrSymbolOwner && element !is IrAnonymousInitializer) { + register(element.symbol) + } + } +} + +private class IrUnboundSymbolReplacer( + val symbolTable: SymbolTable, + val descriptorToSymbol: Map +) : IrElementTransformerVoid() { + + private inline fun > S.replace( + referenceSymbol: (SymbolTable, D) -> S): S? { + + if (this.isBound) { + return null + } + + descriptorToSymbol[this.descriptor]?.let { + return it as S + } + + return referenceSymbol(symbolTable, this.descriptor) + } + + private inline fun > S.replaceOrSame( + referenceSymbol: (SymbolTable, D) -> S): S = this.replace(referenceSymbol) ?: this + + private fun IrFunctionSymbol.replace( + referenceSymbol: (SymbolTable, FunctionDescriptor) -> IrFunctionSymbol): IrFunctionSymbol? { + + if (this.isBound) { + return null + } + + descriptorToSymbol[this.descriptor]?.let { + return it as IrFunctionSymbol + } + + return referenceSymbol(symbolTable, this.descriptor) + } + + private inline fun S.replaceLocal(): S? { + return if (this.isBound) { + null + } else { + descriptorToSymbol[this.descriptor] as S + } + } + + override fun visitGetValue(expression: IrGetValue): IrExpression { + val symbol = expression.symbol.replaceLocal() ?: return super.visitGetValue(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrGetValueImpl(startOffset, endOffset, symbol, origin) + } + } + + override fun visitSetVariable(expression: IrSetVariable): IrExpression { + val symbol = expression.symbol.replaceLocal() ?: return super.visitSetVariable(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrSetVariableImpl(startOffset, endOffset, symbol, value, origin) + } + } + + override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceClass) ?: + return super.visitGetObjectValue(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrGetObjectValueImpl(startOffset, endOffset, type, symbol) + } + } + + override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceEnumEntry) ?: + return super.visitGetEnumValue(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrGetEnumValueImpl(startOffset, endOffset, type, symbol) + } + } + + override fun visitClassReference(expression: IrClassReference): IrExpression { + val symbol = expression.symbol.let { + if (it.isBound) { + return super.visitClassReference(expression) + } + + descriptorToSymbol[it.descriptor]?.let { + it as IrClassifierSymbol + } + + symbolTable.referenceClassifier(it.descriptor) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrClassReferenceImpl(startOffset, endOffset, type, symbol) + } + } + + override fun visitGetField(expression: IrGetField): IrExpression { + val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField) + + val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass) + + if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) { + return super.visitGetField(expression) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrGetFieldImpl(startOffset, endOffset, symbol, receiver, origin, superQualifierSymbol) + } + } + + override fun visitSetField(expression: IrSetField): IrExpression { + val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField) + + val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass) + + if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) { + return super.visitSetField(expression) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, origin, superQualifierSymbol) + } + } + + override fun visitCall(expression: IrCall): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol + + val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass) + + if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) { + return super.visitCall(expression) + } + + expression.transformChildrenVoid() + return with(expression) { + IrCallImpl(startOffset, endOffset, symbol, descriptor, + getTypeArgumentsMap(), + origin, superQualifierSymbol).also { + + it.copyArgumentsFrom(this) + } + } + } + + private fun IrMemberAccessExpression.getTypeArgumentsMap() = + descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) } + + private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) { + dispatchReceiver = original.dispatchReceiver + extensionReceiver = original.extensionReceiver + original.descriptor.valueParameters.forEachIndexed { index, _ -> + putValueArgument(index, original.getValueArgument(index)) + } + } + + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?: + return super.visitEnumConstructorCall(expression) + + return with(expression) { + IrEnumConstructorCallImpl(startOffset, endOffset, symbol).also { + it.copyArgumentsFrom(this) + } + } + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?: + return super.visitDelegatingConstructorCall(expression) + + expression.transformChildrenVoid() + return with(expression) { + IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also { + it.copyArgumentsFrom(this) + } + } + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: + return super.visitFunctionReference(expression) + + expression.transformChildrenVoid(this) + return with(expression) { + IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also { + it.copyArgumentsFrom(this) + } + } + } + + override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { + val field = expression.field?.replaceOrSame(SymbolTable::referenceField) + val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter + val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter + + if (field == expression.field && getter == expression.getter && setter == expression.setter) { + return super.visitPropertyReference(expression) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, + field, + getter, + setter, + getTypeArgumentsMap(), origin).also { + + it.copyArgumentsFrom(this) + } + } + } + + override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression { + val delegate = expression.delegate.replaceOrSame(SymbolTable::referenceVariable) + val getter = expression.getter.replace(SymbolTable::referenceFunction) ?: expression.getter + val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter + + if (delegate == expression.delegate && getter == expression.getter && setter == expression.setter) { + return super.visitLocalDelegatedPropertyReference(expression) + } + + expression.transformChildrenVoid(this) + return with(expression) { + IrLocalDelegatedPropertyReferenceImpl(startOffset, endOffset, type, descriptor, + delegate, getter, setter, origin).also { + + it.copyArgumentsFrom(this) + } + } + } + + private val returnTargetStack = mutableListOf() + + override fun visitFunction(declaration: IrFunction): IrStatement { + returnTargetStack.push(declaration.symbol) + try { + return super.visitFunction(declaration) + } finally { + returnTargetStack.pop() + } + } + + override fun visitBlock(expression: IrBlock): IrExpression { + if (expression is IrReturnableBlock) { + returnTargetStack.push(expression.symbol) + try { + return super.visitBlock(expression) + } finally { + returnTargetStack.pop() + } + } else { + return super.visitBlock(expression) + } + } + + override fun visitReturn(expression: IrReturn): IrExpression { + if (expression.returnTargetSymbol.isBound) { + return super.visitReturn(expression) + } + + val returnTargetSymbol = returnTargetStack.last { it.descriptor == expression.returnTarget } + + expression.transformChildrenVoid(this) + + return with(expression) { + IrReturnImpl(startOffset, endOffset, type, returnTargetSymbol, value) + } + } + + override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression { + val classSymbol = expression.classSymbol.replace(SymbolTable::referenceClass) ?: + return super.visitInstanceInitializerCall(expression) + + expression.transformChildrenVoid(this) + + return with(expression) { + IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol) + } + } +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index 6efe5e7ea32..b6ebeea365d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -19,17 +19,21 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* 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.symbols.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.source.PsiSourceElement +import org.jetbrains.kotlin.types.KotlinType /** * Binds the arguments explicitly represented in the IR to the parameters of the accessed function. @@ -59,6 +63,32 @@ internal fun IrMemberAccessExpression.getArguments(): List> { + val res = mutableListOf>() + val irFunction = symbol.owner as IrFunction + + dispatchReceiver?.let { + res += (irFunction.dispatchReceiverParameter!!.symbol to it) + } + + extensionReceiver?.let { + res += (irFunction.extensionReceiverParameter!!.symbol to it) + } + + irFunction.valueParameters.forEach { + val arg = getValueArgument(it.descriptor as ValueParameterDescriptor) + if (arg != null) { + res += (it.symbol to arg) + } + } + + return res +} + /** * Sets arguments that are specified by given mapping of parameters. */ @@ -146,7 +176,93 @@ fun IrClass.createParameterDeclarations() { } private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int = - (descriptor.source as? PsiSourceElement)?.psi?.startOffset ?: this.startOffset + descriptor.startOffset ?: this.startOffset private fun IrElement.innerEndOffset(descriptor: DeclarationDescriptorWithSource): Int = - (descriptor.source as? PsiSourceElement)?.psi?.endOffset ?: this.endOffset + descriptor.endOffset ?: this.endOffset + +val DeclarationDescriptorWithSource.startOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.startOffset +val DeclarationDescriptorWithSource.endOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.endOffset + +val DeclarationDescriptorWithSource.startOffsetOrUndefined: Int get() = startOffset ?: UNDEFINED_OFFSET +val DeclarationDescriptorWithSource.endOffsetOrUndefined: Int get() = endOffset ?: UNDEFINED_OFFSET + +val IrClassSymbol.functions: Sequence + get() = this.owner.declarations.asSequence().filterIsInstance().map { it.symbol } + +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 IrValueParameter.type: KotlinType + get() = this.descriptor.type + +val IrClass.defaultType: KotlinType + get() = this.descriptor.defaultType + +class IrSymbolBindingChecker : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitDeclarationReference(expression: IrDeclarationReference) { + super.visitDeclarationReference(expression) + + expression.symbol.ensureBound(expression) + } + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression) { + super.visitFunctionAccess(expression) + + expression.symbol.ensureBound(expression) + } + + override fun visitFunctionReference(expression: IrFunctionReference) { + super.visitFunctionReference(expression) + + expression.symbol.ensureBound(expression) + } + + override fun visitCall(expression: IrCall) { + super.visitCall(expression) + + expression.superQualifierSymbol?.ensureBound(expression) + } + + override fun visitPropertyReference(expression: IrPropertyReference) { + super.visitPropertyReference(expression) + + expression.field?.ensureBound(expression) + expression.getter?.ensureBound(expression) + expression.setter?.ensureBound(expression) + } + + override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) { + super.visitLocalDelegatedPropertyReference(expression) + + expression.delegate.ensureBound(expression) + expression.getter.ensureBound(expression) + expression.setter?.ensureBound(expression) + } + + override fun visitReturn(expression: IrReturn) { + super.visitReturn(expression) + + expression.returnTargetSymbol.ensureBound(expression) + } + + override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) { + super.visitInstanceInitializerCall(expression) + + expression.classSymbol.ensureBound(expression) + } + + private fun IrSymbol.ensureBound(expression: IrExpression) { + if (!this.isBound) { + throw Error("Unbound symbol ${this} found in ${expression.render()}") + } + } + +}