From b68a934d88966dc6faf78cff4fa9d0feb449e6f6 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Wed, 2 Dec 2020 19:44:32 +0700 Subject: [PATCH] Proper fix for interop enum and struct generation Current approach to generate interop enum and structs during linkage stage turned out to be fragile. We might get unbound wrapper descriptors which are useless for function body generation. The solution is to postpone body generation until linkage step is complete. --- .../jetbrains/kotlin/backend/konan/PsiToIr.kt | 5 ++ .../interop/DescriptorToIrTranslationUtils.kt | 6 ++ .../IrProviderForCEnumAndCStructStubs.kt | 18 ++++- .../cenum/CEnumByValueFunctionGenerator.kt | 77 ++++++++++--------- .../ir/interop/cenum/CEnumClassGenerator.kt | 64 +++++++++------ .../interop/cenum/CEnumCompanionGenerator.kt | 20 +++-- .../interop/cenum/CEnumVarClassGenerator.kt | 33 ++++---- .../cstruct/CStructVarClassGenerator.kt | 22 +++--- .../cstruct/CStructVarCompanionGenerator.kt | 19 +++-- 9 files changed, 164 insertions(+), 100 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt index 882b92d5d45..3b82f92092f 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/PsiToIr.kt @@ -133,6 +133,11 @@ internal fun Context.psiToIr( modulesWithoutDCE .filter(ModuleDescriptor::isFromInteropLibrary) .forEach(irProviderForCEnumsAndCStructs::referenceAllEnumsAndStructsFrom) + + + translator.addPostprocessingStep { + irProviderForCEnumsAndCStructs.generateBodies() + } } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt index f9391b4cda4..3e6228e3679 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/DescriptorToIrTranslationUtils.kt @@ -41,6 +41,12 @@ internal interface DescriptorToIrTranslationMixin { val typeTranslator: TypeTranslator + val postLinkageSteps: MutableList<() -> Unit> + + fun invokePostLinkageSteps() { + postLinkageSteps.forEach { it() } + } + fun KotlinType.toIrType() = typeTranslator.translateType(this) /** diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt index 3b24ca60afc..a6911a068b6 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/IrProviderForCEnumAndCStructStubs.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumClassGenerator import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumCompanionGenerator import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumVarClassGenerator import org.jetbrains.kotlin.backend.konan.ir.interop.cstruct.CStructVarClassGenerator +import org.jetbrains.kotlin.backend.konan.ir.interop.cstruct.CStructVarCompanionGenerator import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.* @@ -50,8 +51,10 @@ internal class IrProviderForCEnumAndCStructStubs( CEnumVarClassGenerator(context, interopBuiltIns) private val cEnumClassGenerator = CEnumClassGenerator(context, cEnumCompanionGenerator, cEnumVarClassGenerator) + private val cStructCompanionGenerator = + CStructVarCompanionGenerator(context, interopBuiltIns) private val cStructClassGenerator = - CStructVarClassGenerator(context, interopBuiltIns) + CStructVarClassGenerator(context, interopBuiltIns, cStructCompanionGenerator) fun isCEnumOrCStruct(declarationDescriptor: DeclarationDescriptor): Boolean = declarationDescriptor.run { findCEnumDescriptor(interopBuiltIns) ?: findCStructDescriptor(interopBuiltIns) } != null @@ -73,6 +76,19 @@ internal class IrProviderForCEnumAndCStructStubs( } } + /** + * We postpone generation of bodies until IR linkage is complete. + * This way we ensure that all used symbols are resolved. + */ + fun generateBodies() { + cEnumCompanionGenerator.invokePostLinkageSteps() + cEnumByValueFunctionGenerator.invokePostLinkageSteps() + cEnumClassGenerator.invokePostLinkageSteps() + cEnumVarClassGenerator.invokePostLinkageSteps() + cStructClassGenerator.invokePostLinkageSteps() + cStructCompanionGenerator.invokePostLinkageSteps() + } + fun getDeclaration(descriptor: DeclarationDescriptor, idSignature: IdSignature, file: IrFile, symbolKind: BinarySymbolData.SymbolKind): IrSymbolOwner { return symbolTable.run { when (symbolKind) { diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumByValueFunctionGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumByValueFunctionGenerator.kt index ea65b605557..102d4ca4c29 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumByValueFunctionGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumByValueFunctionGenerator.kt @@ -32,6 +32,7 @@ internal class CEnumByValueFunctionGenerator( override val irBuiltIns: IrBuiltIns = context.irBuiltIns override val symbolTable: SymbolTable = context.symbolTable override val typeTranslator: TypeTranslator = context.typeTranslator + override val postLinkageSteps: MutableList<() -> Unit> = mutableListOf() fun generateByValueFunction( companionIrClass: IrClass, @@ -51,46 +52,48 @@ internal class CEnumByValueFunctionGenerator( // i++ // } // throw NPE - byValueIrFunction.body = irBuilder(irBuiltIns, byValueIrFunction.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { - +irReturn(irBlock { - val values = irTemporary(irCall(valuesIrFunctionSymbol), isMutable = true) - val inductionVariable = irTemporary(irInt(0), isMutable = true) - val arrayClass = values.type.classOrNull!! - val valuesSize = irCall(symbols.arraySize.getValue(arrayClass), irBuiltIns.intType).also { irCall -> - irCall.dispatchReceiver = irGet(values) - } - val getElementFn = symbols.arrayGet.getValue(arrayClass) - val plusFun = symbols.getBinaryOperator(OperatorNameConventions.PLUS, irBuiltIns.intType, irBuiltIns.intType) - val lessFunctionSymbol = irBuiltIns.lessFunByOperandType.getValue(irBuiltIns.intClass) - +irWhile().also { loop -> - loop.condition = irCall(lessFunctionSymbol, irBuiltIns.booleanType).also { irCall -> - irCall.putValueArgument(0, irGet(inductionVariable)) - irCall.putValueArgument(1, valuesSize) + postLinkageSteps.add { + byValueIrFunction.body = irBuilder(irBuiltIns, byValueIrFunction.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +irReturn(irBlock { + val values = irTemporary(irCall(valuesIrFunctionSymbol), isMutable = true) + val inductionVariable = irTemporary(irInt(0), isMutable = true) + val arrayClass = values.type.classOrNull!! + val valuesSize = irCall(symbols.arraySize.getValue(arrayClass), irBuiltIns.intType).also { irCall -> + irCall.dispatchReceiver = irGet(values) } - loop.body = irBlock { - val entry = irTemporary(irCall(getElementFn, byValueIrFunction.returnType).also { irCall -> - irCall.dispatchReceiver = irGet(values) + val getElementFn = symbols.arrayGet.getValue(arrayClass) + val plusFun = symbols.getBinaryOperator(OperatorNameConventions.PLUS, irBuiltIns.intType, irBuiltIns.intType) + val lessFunctionSymbol = irBuiltIns.lessFunByOperandType.getValue(irBuiltIns.intClass) + +irWhile().also { loop -> + loop.condition = irCall(lessFunctionSymbol, irBuiltIns.booleanType).also { irCall -> irCall.putValueArgument(0, irGet(inductionVariable)) - }, isMutable = true) - val valueGetter = entry.type.getClass()!!.getPropertyGetter("value")!! - val entryValue = irGet(irValueParameter.type, irGet(entry), valueGetter) - +irIfThenElse( - type = irBuiltIns.unitType, - condition = irEquals(entryValue, irGet(irValueParameter)), - thenPart = irReturn(irGet(entry)), - elsePart = irSetVar( - inductionVariable, - irCallOp(plusFun, irBuiltIns.intType, - irGet(inductionVariable), - irInt(1) - ) - ) - ) + irCall.putValueArgument(1, valuesSize) + } + loop.body = irBlock { + val entry = irTemporary(irCall(getElementFn, byValueIrFunction.returnType).also { irCall -> + irCall.dispatchReceiver = irGet(values) + irCall.putValueArgument(0, irGet(inductionVariable)) + }, isMutable = true) + val valueGetter = entry.type.getClass()!!.getPropertyGetter("value")!! + val entryValue = irGet(irValueParameter.type, irGet(entry), valueGetter) + +irIfThenElse( + type = irBuiltIns.unitType, + condition = irEquals(entryValue, irGet(irValueParameter)), + thenPart = irReturn(irGet(entry)), + elsePart = irSetVar( + inductionVariable, + irCallOp(plusFun, irBuiltIns.intType, + irGet(inductionVariable), + irInt(1) + ) + ) + ) + } } - } - +IrCallImpl.fromSymbolDescriptor(startOffset, endOffset, irBuiltIns.nothingType, - symbols.throwNullPointerException) - }) + +IrCallImpl.fromSymbolOwner(startOffset, endOffset, irBuiltIns.nothingType, + symbols.throwNullPointerException) + }) + } } return byValueIrFunction } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt index bc2da7010e0..f5758053e79 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumClassGenerator.kt @@ -49,6 +49,7 @@ internal class CEnumClassGenerator( override val irBuiltIns: IrBuiltIns = context.irBuiltIns override val symbolTable: SymbolTable = context.symbolTable override val typeTranslator: TypeTranslator = context.typeTranslator + override val postLinkageSteps: MutableList<() -> Unit> = mutableListOf() private val enumClassMembersGenerator = EnumClassMembersGenerator(DeclarationGenerator(context)) @@ -97,38 +98,46 @@ internal class CEnumClassGenerator( SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, propertyDescriptor, propertyDescriptor.type.toIrType(), DescriptorVisibilities.PRIVATE ).also { - it.initializer = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).run { - irExprBody(irGet(irClass.primaryConstructor!!.valueParameters[0])) + postLinkageSteps.add { + it.initializer = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).run { + irExprBody(irGet(irClass.primaryConstructor!!.valueParameters[0])) + } } } } val getter = irProperty.getter!! getter.correspondingPropertySymbol = irProperty.symbol - getter.body = irBuilder(irBuiltIns, getter.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { - +irReturn( - irGetField( - irGet(getter.dispatchReceiverParameter!!), - irProperty.backingField!! - ) - ) + postLinkageSteps.add { + getter.body = irBuilder(irBuiltIns, getter.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +irReturn( + irGetField( + irGet(getter.dispatchReceiverParameter!!), + irProperty.backingField!! + ) + ) + } } return irProperty } private fun createEnumEntry(enumDescriptor: ClassDescriptor, entryDescriptor: ClassDescriptor): IrEnumEntry { - return symbolTable.declareEnumEntry( + val enumEntry = symbolTable.declareEnumEntry( SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB, entryDescriptor - ).also { enumEntry -> - enumEntry.initializerExpression = IrExpressionBodyImpl(IrEnumConstructorCallImpl.fromSymbolDescriptor( + ) + val constructorSymbol = symbolTable.referenceConstructor(enumDescriptor.unsubstitutedPrimaryConstructor!!) + postLinkageSteps.add { + enumEntry.initializerExpression = IrExpressionBodyImpl(IrEnumConstructorCallImpl( SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, type = irBuiltIns.unitType, - symbol = symbolTable.referenceConstructor(enumDescriptor.unsubstitutedPrimaryConstructor!!), - typeArgumentsCount = 0 // enums can't be generic + symbol = constructorSymbol, + typeArgumentsCount = 0, + valueArgumentsCount = constructorSymbol.owner.valueParameters.size ).also { it.putValueArgument(0, extractEnumEntryValue(entryDescriptor)) }) } + return enumEntry } /** @@ -146,16 +155,23 @@ internal class CEnumClassGenerator( private fun createEnumPrimaryConstructor(descriptor: ClassDescriptor): IrConstructor { val irConstructor = createConstructor(descriptor.unsubstitutedPrimaryConstructor!!) val enumConstructor = context.builtIns.enum.constructors.single() - irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { - +IrEnumConstructorCallImpl.fromSymbolDescriptor( - startOffset, endOffset, - context.irBuiltIns.unitType, - symbolTable.referenceConstructor(enumConstructor), - typeArgumentsCount = 1 // kotlin.Enum has a single type parameter. - ).apply { - putTypeArgument(0, descriptor.defaultType.toIrType()) - } - +irInstanceInitializer(symbolTable.referenceClass(descriptor)) + val constructorSymbol = symbolTable.referenceConstructor(enumConstructor) + val classSymbol = symbolTable.referenceClass(descriptor) + val type = descriptor.defaultType.toIrType() + postLinkageSteps.add { + irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET) + .irBlockBody { + +IrEnumConstructorCallImpl( + startOffset, endOffset, + context.irBuiltIns.unitType, + constructorSymbol, + typeArgumentsCount = 1, // kotlin.Enum has a single type parameter. + valueArgumentsCount = constructorSymbol.owner.valueParameters.size + ).apply { + putTypeArgument(0, type) + } + +irInstanceInitializer(classSymbol) + } } return irConstructor } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumCompanionGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumCompanionGenerator.kt index f90f2ffefd2..27dfbad5ebc 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumCompanionGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumCompanionGenerator.kt @@ -32,6 +32,7 @@ internal class CEnumCompanionGenerator( override val irBuiltIns: IrBuiltIns = context.irBuiltIns override val symbolTable: SymbolTable = context.symbolTable override val typeTranslator: TypeTranslator = context.typeTranslator + override val postLinkageSteps: MutableList<() -> Unit> = mutableListOf() // Depends on already generated `.values()` irFunction. fun generate(enumClass: IrClass): IrClass = @@ -50,13 +51,16 @@ internal class CEnumCompanionGenerator( private fun createCompanionConstructor(companionObjectDescriptor: ClassDescriptor): IrConstructor { val anyPrimaryConstructor = companionObjectDescriptor.builtIns.any.unsubstitutedPrimaryConstructor!! val superConstructorSymbol = symbolTable.referenceConstructor(anyPrimaryConstructor) + val classSymbol = symbolTable.referenceClass(companionObjectDescriptor) return createConstructor(companionObjectDescriptor.unsubstitutedPrimaryConstructor!!).also { - it.body = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { - +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( - startOffset, endOffset, context.irBuiltIns.unitType, - superConstructorSymbol - ) - +irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor)) + postLinkageSteps.add { + it.body = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolOwner( + startOffset, endOffset, context.irBuiltIns.unitType, + superConstructorSymbol + ) + +irInstanceInitializer(classSymbol) + } } } } @@ -88,7 +92,9 @@ internal class CEnumCompanionGenerator( private fun declareEntryAliasProperty(propertyDescriptor: PropertyDescriptor, enumClass: IrClass): IrProperty { val entrySymbol = fundCorrespondingEnumEntrySymbol(propertyDescriptor, enumClass) return createProperty(propertyDescriptor).also { - it.getter!!.body = generateAliasGetterBody(it.getter!!, entrySymbol, enumClass) + postLinkageSteps.add { + it.getter!!.body = generateAliasGetterBody(it.getter!!, entrySymbol, enumClass) + } } } } \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumVarClassGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumVarClassGenerator.kt index 5cea0c767f9..3fa40489289 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumVarClassGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cenum/CEnumVarClassGenerator.kt @@ -34,6 +34,7 @@ internal class CEnumVarClassGenerator( override val irBuiltIns: IrBuiltIns = context.irBuiltIns override val symbolTable: SymbolTable = context.symbolTable override val typeTranslator: TypeTranslator = context.typeTranslator + override val postLinkageSteps: MutableList<() -> Unit> = mutableListOf() fun generate(enumIrClass: IrClass): IrClass { val enumVarClassDescriptor = enumIrClass.descriptor.unsubstitutedMemberScope @@ -56,13 +57,16 @@ internal class CEnumVarClassGenerator( val enumVarConstructorSymbol = symbolTable.referenceConstructor( interopBuiltIns.cEnumVar.unsubstitutedPrimaryConstructor!! ) - irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { - +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( - startOffset, endOffset, context.irBuiltIns.unitType, enumVarConstructorSymbol - ).also { - it.putValueArgument(0, irGet(irConstructor.valueParameters[0])) + val classSymbol = symbolTable.referenceClass(enumVarClass.descriptor) + postLinkageSteps.add { + irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolOwner( + startOffset, endOffset, context.irBuiltIns.unitType, enumVarConstructorSymbol + ).also { + it.putValueArgument(0, irGet(irConstructor.valueParameters[0])) + } + +irInstanceInitializer(classSymbol) } - +irInstanceInitializer(symbolTable.referenceClass(enumVarClass.descriptor)) } return irConstructor } @@ -77,15 +81,18 @@ internal class CEnumVarClassGenerator( private fun createCompanionConstructor(companionObjectDescriptor: ClassDescriptor, typeSize: Int): IrConstructor { val superConstructorSymbol = symbolTable.referenceConstructor(interopBuiltIns.cPrimitiveVarType.unsubstitutedPrimaryConstructor!!) + val classSymbol = symbolTable.referenceClass(companionObjectDescriptor) return createConstructor(companionObjectDescriptor.unsubstitutedPrimaryConstructor!!).also { - it.body = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { - +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( - startOffset, endOffset, context.irBuiltIns.unitType, - superConstructorSymbol - ).also { - it.putValueArgument(0, irInt(typeSize)) + postLinkageSteps.add { + it.body = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolOwner( + startOffset, endOffset, context.irBuiltIns.unitType, + superConstructorSymbol + ).also { + it.putValueArgument(0, irInt(typeSize)) + } + +irInstanceInitializer(classSymbol) } - +irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor)) } } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt index e844c8aa444..bedb27332f4 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarClassGenerator.kt @@ -23,14 +23,14 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext internal class CStructVarClassGenerator( context: GeneratorContext, - private val interopBuiltIns: InteropBuiltIns + private val interopBuiltIns: InteropBuiltIns, + private val companionGenerator: CStructVarCompanionGenerator ) : DescriptorToIrTranslationMixin { override val irBuiltIns: IrBuiltIns = context.irBuiltIns override val symbolTable: SymbolTable = context.symbolTable override val typeTranslator: TypeTranslator = context.typeTranslator - - private val companionGenerator = CStructVarCompanionGenerator(context, interopBuiltIns) + override val postLinkageSteps: MutableList<() -> Unit> = mutableListOf() fun findOrGenerateCStruct(classDescriptor: ClassDescriptor, parent: IrDeclarationContainer): IrClass { val irClassSymbol = symbolTable.referenceClass(classDescriptor) @@ -61,14 +61,16 @@ internal class CStructVarClassGenerator( interopBuiltIns.cStructVar.unsubstitutedPrimaryConstructor!! ) return createConstructor(irClass.descriptor.unsubstitutedPrimaryConstructor!!).also { irConstructor -> - irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { - +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( - startOffset, endOffset, - context.irBuiltIns.unitType, enumVarConstructorSymbol - ).also { - it.putValueArgument(0, irGet(irConstructor.valueParameters[0])) + postLinkageSteps.add { + irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolOwner( + startOffset, endOffset, + context.irBuiltIns.unitType, enumVarConstructorSymbol + ).also { + it.putValueArgument(0, irGet(irConstructor.valueParameters[0])) + } + +irInstanceInitializer(symbolTable.referenceClass(irClass.descriptor)) } - +irInstanceInitializer(symbolTable.referenceClass(irClass.descriptor)) } } } diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarCompanionGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarCompanionGenerator.kt index 133df36ea76..95d1a9defd9 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarCompanionGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/interop/cstruct/CStructVarCompanionGenerator.kt @@ -32,6 +32,7 @@ internal class CStructVarCompanionGenerator( override val irBuiltIns: IrBuiltIns = context.irBuiltIns override val symbolTable: SymbolTable = context.symbolTable override val typeTranslator: TypeTranslator = context.typeTranslator + override val postLinkageSteps: MutableList<() -> Unit> = mutableListOf() fun generate(structDescriptor: ClassDescriptor): IrClass = createClass(structDescriptor.companionObjectDescriptor!!) { companionIrClass -> @@ -45,15 +46,17 @@ internal class CStructVarCompanionGenerator( private fun createCompanionConstructor(companionObjectDescriptor: ClassDescriptor, size: Long, align: Int): IrConstructor { val superConstructorSymbol = symbolTable.referenceConstructor(interopBuiltIns.cStructVarType.unsubstitutedPrimaryConstructor!!) return createConstructor(companionObjectDescriptor.unsubstitutedPrimaryConstructor!!).also { irConstructor -> - irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { - +IrDelegatingConstructorCallImpl.fromSymbolDescriptor( - startOffset, endOffset, context.irBuiltIns.unitType, - superConstructorSymbol - ).also { - it.putValueArgument(0, irLong(size)) - it.putValueArgument(1, irInt(align)) + postLinkageSteps.add { + irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody { + +IrDelegatingConstructorCallImpl.fromSymbolOwner( + startOffset, endOffset, context.irBuiltIns.unitType, + superConstructorSymbol + ).also { + it.putValueArgument(0, irLong(size)) + it.putValueArgument(1, irInt(align)) + } + +irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor)) } - +irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor)) } } }