[K/N][IR] Reworked caches ABI lowering

This commit is contained in:
Igor Chevdar
2022-08-16 16:19:21 +03:00
committed by Space
parent c1d63fa6dd
commit 85379159be
9 changed files with 167 additions and 268 deletions
@@ -66,6 +66,10 @@ internal class NativeMapping : DefaultMapping() {
val bridges = mutableMapOf<BridgeKey, IrSimpleFunction>()
val notLoweredInlineFunctions = mutableMapOf<IrFunctionSymbol, IrFunction>()
val loweredInlineFunctions = mutableMapOf<IrFunction, InlineFunctionOriginInfo>()
val companionObjectCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
val outerThisCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
val lateinitPropertyCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrProperty, IrSimpleFunction>()
val enumValuesCacheAccessors = DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
}
internal class Context(config: KonanConfig) : KonanBackendContext(config) {
@@ -106,6 +110,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
val bridgesSupport by lazy { BridgesSupport(mapping, irBuiltIns, irFactory) }
val inlineFunctionsSupport by lazy { InlineFunctionsSupport(mapping) }
val enumsSupport by lazy { EnumsSupport(mapping, ir.symbols, irBuiltIns, irFactory) }
val cachesAbiSupport by lazy { CachesAbiSupport(mapping, ir.symbols, irFactory) }
open class LazyMember<T>(val initializer: Context.() -> T) {
operator fun getValue(thisRef: Context, property: KProperty<*>): T = thisRef.getValue(this)
@@ -361,11 +366,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
val declaredLocalArrays: MutableMap<String, LLVMTypeRef> = HashMap()
/**
* Manages internal ABI references and declarations.
*/
val internalAbi = InternalAbi(this)
lateinit var irLinker: KonanIrLinker
val inlineFunctionBodies = mutableListOf<SerializedInlineFunctionReference>()
@@ -8,21 +8,20 @@ package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.ir.util.irCatch
import org.jetbrains.kotlin.name.Name
internal object DECLARATION_ORIGIN_ENTRY_POINT : IrDeclarationOriginImpl("ENTRY_POINT")
internal fun makeEntryPoint(context: Context): IrFunction {
val actualMain = context.ir.symbols.entryPoint!!.owner
// TODO: Do we need to do something with the offsets if <main> is in a cached library?
@@ -34,46 +33,27 @@ internal fun makeEntryPoint(context: Context): IrFunction {
actualMain.endOffset
else
SYNTHETIC_OFFSET
val entryPoint = IrFunctionImpl(
startOffset,
endOffset,
IrDeclarationOrigin.DEFINED,
IrSimpleFunctionSymbolImpl(),
Name.identifier("Konan_start"),
DescriptorVisibilities.PRIVATE,
Modality.FINAL,
context.irBuiltIns.intType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = false,
isExpect = false,
isFakeOverride = false,
isOperator = false,
isInfix = false
).also { function ->
function.valueParameters = listOf(
IrValueParameterImpl(
startOffset, endOffset,
IrDeclarationOrigin.DEFINED,
IrValueParameterSymbolImpl(),
Name.identifier("args"),
index = 0,
varargElementType = null,
isCrossinline = false,
type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.stringType),
isNoinline = false,
isHidden = false,
isAssignable = false
).apply {
parent = function
})
val entryPoint = context.irFactory.buildFun {
this.startOffset = startOffset
this.endOffset = endOffset
origin = DECLARATION_ORIGIN_ENTRY_POINT
name = Name.identifier("Konan_start")
visibility = DescriptorVisibilities.PRIVATE
returnType = context.irBuiltIns.intType
}.apply {
addValueParameter {
this.startOffset = startOffset
this.endOffset = endOffset
origin = DECLARATION_ORIGIN_ENTRY_POINT
name = Name.identifier("args")
type = context.irBuiltIns.arrayClass.typeWith(context.irBuiltIns.stringType)
}
}
entryPoint.annotations += buildSimpleAnnotation(context.irBuiltIns,
startOffset, endOffset,
context.ir.symbols.exportForCppRuntime.owner, "Konan_start")
val builder = context.createIrBuilder(entryPoint.symbol)
val builder = context.createIrBuilder(entryPoint.symbol, startOffset, endOffset)
entryPoint.body = builder.irBlockBody(entryPoint) {
+IrTryImpl(startOffset, endOffset, context.irBuiltIns.nothingType).apply {
tryResult = irBlock {
@@ -1,103 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.ir.util.addChild
import org.jetbrains.kotlin.ir.util.addFile
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
/**
* Sometimes we need to reference symbols that are not declared in metadata.
* For example, symbol might be declared during lowering.
* In case of compiler caches, this means that it is not accessible as Lazy IR
* and we have to explicitly add an external declaration.
*/
internal class InternalAbi(private val context: Context) {
/**
* Files that stores all internal ABI declarations.
* We use per-module files so that global initializer will be stored
* in the appropriate modules.
*
* We have to store such declarations in top-level to avoid mangling that
* makes referencing harder.
* A bit better solution is to add files with proper packages, but it is impossible
* during FileLowering (hello, ConcurrentModificationException).
*/
private lateinit var internalAbiFiles: Map<ModuleDescriptor, IrFile>
/**
* Representation of ABI files from external modules.
*/
private val externalAbiFiles = mutableMapOf<ModuleDescriptor, IrExternalPackageFragment>()
fun init(modules: List<IrModuleFragment>) {
internalAbiFiles = modules.associate { it.descriptor to createAbiFile(it) }
}
private fun createAbiFile(module: IrModuleFragment): IrFile =
module.addFile(NaiveSourceBasedFileEntryImpl("internal"), KonanFqNames.cachesInternalAbi)
private fun createExternalAbiFile(module: ModuleDescriptor, fqName: FqName): IrExternalPackageFragment {
val packageFragmentDescriptor = object : PackageFragmentDescriptorImpl(module, fqName) {
override fun getMemberScope(): MemberScope = MemberScope.Empty
}
return IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(packageFragmentDescriptor), fqName)
}
/**
* Adds external [function] from [module] to a list of external references.
*/
fun reference(function: IrFunction, module: ModuleDescriptor) {
assert(function.isExternal) { "Function that represents external ABI should be marked as external" }
context.llvmImports.add(module.llvmSymbolOrigin)
val externalAbiFile = externalAbiFiles.getOrPut(module) { createExternalAbiFile(module, KonanFqNames.cachesInternalAbi) }
externalAbiFile.addChild(function)
}
/**
* Adds [function] to a list of [module]'s publicly available symbols.
*/
fun declare(function: IrFunction, module: ModuleDescriptor) {
internalAbiFiles.getValue(module).addChild(function)
}
companion object {
/**
* Allows to distinguish external declarations to internal ABI.
*/
val INTERNAL_ABI_ORIGIN = object : IrDeclarationOriginImpl("INTERNAL_ABI") {}
fun getCompanionObjectAccessorName(companion: IrClass): Name =
getMangledNameFor("globalAccessor", companion)
fun getEnumValuesAccessorName(enum: IrClass): Name =
getMangledNameFor("getValues", enum)
fun getInnerClassOuterThisAccessorName(innerClass: IrClass): Name =
getMangledNameFor("outerThis", innerClass)
fun getLateinitPropertyFieldAccessorName(property: IrProperty): Name =
getMangledNameFor("${property.name}_field", property.parent)
/**
* Generate name for declaration that will be a part of internal ABI.
*/
private fun getMangledNameFor(declarationName: String, parent: IrDeclarationParent): Name {
val prefix = parent.fqNameForIrSerialization
return "$prefix.$declarationName".synthesizedName
}
}
}
@@ -39,5 +39,4 @@ object KonanFqNames {
val noReorderFields = FqName("kotlin.native.internal.NoReorderFields")
val objCName = FqName("kotlin.native.ObjCName")
val reflectionPackageName = FqName("kotlin.native.internal.ReflectionPackageName")
val cachesInternalAbi = FqName("kotlin.native.caches.abi")
}
@@ -242,7 +242,6 @@ internal fun Context.psiToIr(
if (this.stdlibModule in modulesWithoutDCE) {
(functionIrClassFactory as? BuiltInFictitiousFunctionIrClassFactory)?.buildAllClasses()
}
internalAbi.init(irModules.values + irModule!!)
(functionIrClassFactory as? BuiltInFictitiousFunctionIrClassFactory)?.module =
(modules.values + irModule!!).single { it.descriptor.isNativeStdlib() }
}
@@ -363,7 +363,7 @@ internal val entryPointPhase = makeCustomPhase<Context, IrModuleFragment>(
} else {
// `main` function is compiled to other LLVM module.
// For example, test running support uses `main` defined in stdlib.
context.irModule!!.addFile(NaiveSourceBasedFileEntryImpl("entryPointOwner"), FqName("kotlin.native.caches.abi"))
context.irModule!!.addFile(NaiveSourceBasedFileEntryImpl("entryPointOwner"), FqName("kotlin.native.internal.abi"))
}
file.addChild(makeEntryPoint(context))
@@ -425,12 +425,12 @@ private val backendCodegen = namedUnitPhase(
name = "Backend codegen",
description = "Backend code generation",
lower = takeFromContext<Context, Unit, IrModuleFragment> { it.irModule!! } then
entryPointPhase then
functionsWithoutBoundCheck then
allLoweringsPhase then // Lower current module first.
dependenciesLowerPhase then // Then lower all libraries in topological order.
// With that we guarantee that inline functions are unlowered while being inlined.
dumpTestsPhase then
entryPointPhase then
exportInternalAbiPhase then
useInternalAbiPhase then
bitcodePhase then
@@ -298,8 +298,6 @@ fun IrFunction.externalSymbolOrThrow(): String? {
if (annotations.hasAnnotation(RuntimeNames.cCall)) return null
if (origin == InternalAbi.INTERNAL_ABI_ORIGIN) return null
throw Error("external function ${this.longName} must have @TypedIntrinsic, @SymbolName, @GCUnsafeCall or @ObjCMethod annotation")
}
@@ -5,22 +5,23 @@
package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.getOrPut
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.InternalAbi
import org.jetbrains.kotlin.backend.konan.NativeMapping
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin
import org.jetbrains.kotlin.backend.konan.isObjCClass
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetField
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -29,42 +30,135 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
/**
* Allows to distinguish external declarations to internal ABI.
*/
internal object INTERNAL_ABI_ORIGIN : IrDeclarationOriginImpl("INTERNAL_ABI")
/**
* Sometimes we need to reference symbols that are not declared in metadata.
* For example, symbol might be declared during lowering.
* In case of compiler caches, this means that it is not accessible as Lazy IR
* and we have to explicitly add an external declaration.
*/
internal class CachesAbiSupport(mapping: NativeMapping, symbols: KonanSymbols, private val irFactory: IrFactory) {
private val companionObjectAccessors = mapping.companionObjectCacheAccessors
private val outerThisAccessors = mapping.outerThisCacheAccessors
private val lateinitPropertyAccessors = mapping.lateinitPropertyCacheAccessors
private val enumValuesAccessors = mapping.enumValuesCacheAccessors
private val lateInitFieldToNullableField = mapping.lateInitFieldToNullableField
private val array = symbols.array
fun getCompanionObjectAccessor(irClass: IrClass): IrSimpleFunction {
require(irClass.isCompanion) { "Expected a companion object but was: ${irClass.render()}" }
return companionObjectAccessors.getOrPut(irClass) {
irFactory.buildFun {
name = getMangledNameFor("globalAccessor", irClass)
origin = INTERNAL_ABI_ORIGIN
returnType = irClass.defaultType
}.apply {
parent = irClass.getPackageFragment()
}
}
}
fun getOuterThisAccessor(irClass: IrClass): IrSimpleFunction {
require(irClass.isInner) { "Expected an inner class but was: ${irClass.render()}" }
return outerThisAccessors.getOrPut(irClass) {
irFactory.buildFun {
name = getMangledNameFor("outerThis", irClass)
origin = INTERNAL_ABI_ORIGIN
returnType = irClass.parentAsClass.defaultType
}.apply {
parent = irClass.getPackageFragment()
addValueParameter {
name = Name.identifier("innerClass")
origin = INTERNAL_ABI_ORIGIN
type = irClass.defaultType
}
}
}
}
fun getLateinitPropertyAccessor(irProperty: IrProperty): IrSimpleFunction {
require(irProperty.isLateinit) { "Expected a lateinit property but was: ${irProperty.render()}" }
return lateinitPropertyAccessors.getOrPut(irProperty) {
val backingField = irProperty.backingField ?: error("Lateinit property ${irProperty.render()} should have a backing field")
val actualField = lateInitFieldToNullableField[backingField] ?: backingField
val owner = irProperty.parent
irFactory.buildFun {
name = getMangledNameFor("${irProperty.name}_field", owner)
origin = INTERNAL_ABI_ORIGIN
returnType = actualField.type
}.apply {
parent = irProperty.getPackageFragment()
(owner as? IrClass)?.let {
addValueParameter {
name = Name.identifier("owner")
origin = INTERNAL_ABI_ORIGIN
type = it.defaultType
}
}
}
}
}
fun getEnumValuesAccessor(irClass: IrClass): IrSimpleFunction {
require(irClass.isEnumClass) { "Expected a enum class but was: ${irClass.render()}" }
return enumValuesAccessors.getOrPut(irClass) {
irFactory.buildFun {
name = getMangledNameFor("getValues", irClass)
returnType = array.typeWith(irClass.defaultType)
origin = INTERNAL_ABI_ORIGIN
}.apply {
parent = irClass.getPackageFragment()
}
}
}
/**
* Generate name for declaration that will be a part of internal ABI.
*/
private fun getMangledNameFor(declarationName: String, parent: IrDeclarationParent): Name {
val prefix = parent.fqNameForIrSerialization
return "$prefix.$declarationName".synthesizedName
}
}
internal class ExportCachesAbiVisitor(val context: Context) : IrElementVisitorVoid {
private val cachesAbiSupport = context.cachesAbiSupport
private val addedFunctions = mutableListOf<IrFunction>()
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitFile(declaration: IrFile) {
declaration.acceptChildrenVoid(this)
declaration.addChildren(addedFunctions)
addedFunctions.clear()
}
override fun visitClass(declaration: IrClass) {
declaration.acceptChildrenVoid(this)
if (declaration.isLocal) return
if (declaration.isCompanion) {
val function = context.irFactory.buildFun {
name = InternalAbi.getCompanionObjectAccessorName(declaration)
origin = InternalAbi.INTERNAL_ABI_ORIGIN
returnType = declaration.defaultType
}
val function = cachesAbiSupport.getCompanionObjectAccessor(declaration)
context.createIrBuilder(function.symbol).apply {
function.body = irBlockBody {
+irReturn(irGetObjectValue(declaration.defaultType, declaration.symbol))
}
}
context.internalAbi.declare(function, declaration.module)
addedFunctions.add(function)
}
if (declaration.isInner) {
val function = context.irFactory.buildFun {
name = InternalAbi.getInnerClassOuterThisAccessorName(declaration)
origin = InternalAbi.INTERNAL_ABI_ORIGIN
returnType = declaration.parentAsClass.defaultType
}
function.addValueParameter {
name = Name.identifier("innerClass")
origin = InternalAbi.INTERNAL_ABI_ORIGIN
type = declaration.defaultType
}
val function = cachesAbiSupport.getOuterThisAccessor(declaration)
context.createIrBuilder(function.symbol).apply {
function.body = irBlockBody {
+irReturn(irGetField(
@@ -73,22 +167,17 @@ internal class ExportCachesAbiVisitor(val context: Context) : IrElementVisitorVo
)
}
}
context.internalAbi.declare(function, declaration.module)
addedFunctions.add(function)
}
if (declaration.isEnumClass) {
val function = context.irFactory.buildFun {
name = InternalAbi.getEnumValuesAccessorName(declaration)
returnType = context.ir.symbols.array.typeWith(declaration.defaultType)
origin = InternalAbi.INTERNAL_ABI_ORIGIN
}
val function = cachesAbiSupport.getEnumValuesAccessor(declaration)
context.createIrBuilder(function.symbol).run {
function.body = irBlockBody {
+irReturn(with(this@ExportCachesAbiVisitor.context.enumsSupport) { irGetValuesField(declaration) })
}
}
context.internalAbi.declare(function, declaration.module)
addedFunctions.add(function)
}
}
@@ -100,33 +189,20 @@ internal class ExportCachesAbiVisitor(val context: Context) : IrElementVisitorVo
return
val backingField = declaration.backingField ?: error("Lateinit property ${declaration.render()} should have a backing field")
val function = context.irFactory.buildFun {
name = InternalAbi.getLateinitPropertyFieldAccessorName(declaration)
origin = InternalAbi.INTERNAL_ABI_ORIGIN
returnType = backingField.type
}
val ownerClass = declaration.parentClassOrNull
if (ownerClass != null)
function.addValueParameter {
name = Name.identifier("owner")
origin = InternalAbi.INTERNAL_ABI_ORIGIN
type = ownerClass.defaultType
}
val function = cachesAbiSupport.getLateinitPropertyAccessor(declaration)
context.createIrBuilder(function.symbol).apply {
function.body = irBlockBody {
+irReturn(irGetField(ownerClass?.let { irGet(function.valueParameters[0]) }, backingField))
}
}
context.internalAbi.declare(function, declaration.module)
addedFunctions.add(function)
}
}
internal class ImportCachesAbiTransformer(val context: Context) : IrElementTransformerVoid() {
private val companionObjectAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
private val outerThisAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
private val lateinitPropertyAccessors = mutableMapOf<IrProperty, IrSimpleFunction>()
private val enumValuesAccessors = mutableMapOf<IrClass, IrSimpleFunction>()
private val cachesAbiSupport = context.cachesAbiSupport
private val enumsSupport = context.enumsSupport
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
expression.transformChildrenVoid(this)
@@ -140,17 +216,9 @@ internal class ImportCachesAbiTransformer(val context: Context) : IrElementTrans
// Access to Obj-C metaclass is done via intrinsic.
return expression
}
val accessor = companionObjectAccessors.getOrPut(irClass) {
context.irFactory.buildFun {
name = InternalAbi.getCompanionObjectAccessorName(irClass)
returnType = irClass.defaultType
origin = InternalAbi.INTERNAL_ABI_ORIGIN
isExternal = true
}.also {
context.internalAbi.reference(it, irClass.module)
}
}
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size)
val accessor = cachesAbiSupport.getCompanionObjectAccessor(irClass)
context.llvmImports.add(irClass.llvmSymbolOrigin)
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList())
}
override fun visitGetField(expression: IrGetField): IrExpression {
@@ -164,54 +232,17 @@ internal class ImportCachesAbiTransformer(val context: Context) : IrElementTrans
context.llvmModuleSpecification.containsDeclaration(field) -> expression
irClass?.isInner == true && context.innerClassesSupport.getOuterThisField(irClass) == field -> {
val accessor = outerThisAccessors.getOrPut(irClass) {
context.irFactory.buildFun {
name = InternalAbi.getInnerClassOuterThisAccessorName(irClass)
returnType = irClass.parentAsClass.defaultType
origin = InternalAbi.INTERNAL_ABI_ORIGIN
isExternal = true
}.also { function ->
context.internalAbi.reference(function, irClass.module)
function.addValueParameter {
name = Name.identifier("innerClass")
origin = InternalAbi.INTERNAL_ABI_ORIGIN
type = irClass.defaultType
}
}
}
return IrCallImpl(
expression.startOffset, expression.endOffset,
expression.type, accessor.symbol,
accessor.typeParameters.size, accessor.valueParameters.size
).apply {
val accessor = cachesAbiSupport.getOuterThisAccessor(irClass)
context.llvmImports.add(irClass.llvmSymbolOrigin)
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()).apply {
putValueArgument(0, expression.receiver)
}
}
property?.isLateinit == true -> {
val accessor = lateinitPropertyAccessors.getOrPut(property) {
context.irFactory.buildFun {
name = InternalAbi.getLateinitPropertyFieldAccessorName(property)
returnType = field.type
origin = InternalAbi.INTERNAL_ABI_ORIGIN
isExternal = true
}.also { function ->
context.internalAbi.reference(function, property.module)
if (irClass != null)
function.addValueParameter {
name = Name.identifier("owner")
origin = InternalAbi.INTERNAL_ABI_ORIGIN
type = irClass.defaultType
}
}
}
return IrCallImpl(
expression.startOffset, expression.endOffset,
expression.type, accessor.symbol,
accessor.typeParameters.size, accessor.valueParameters.size
).apply {
val accessor = cachesAbiSupport.getLateinitPropertyAccessor(property)
context.llvmImports.add(property.llvmSymbolOrigin)
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList()).apply {
if (irClass != null)
putValueArgument(0, expression.receiver)
}
@@ -221,17 +252,11 @@ internal class ImportCachesAbiTransformer(val context: Context) : IrElementTrans
val enumClass = irClass?.parentClassOrNull
require(enumClass != null) { "Unexpected usage of enum VALUES field" }
require(enumClass.isEnumClass) { "Expected a enum class: ${enumClass.render()}" }
val accessor = enumValuesAccessors.getOrPut(enumClass) {
context.irFactory.buildFun {
name = InternalAbi.getEnumValuesAccessorName(enumClass)
returnType = context.ir.symbols.array.typeWith(enumClass.defaultType)
origin = InternalAbi.INTERNAL_ABI_ORIGIN
isExternal = true
}.also {
context.internalAbi.reference(it, enumClass.module)
}
}
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, accessor.symbol, accessor.typeParameters.size, accessor.valueParameters.size)
require(enumsSupport.getImplObject(enumClass) == irClass) { "Expected a enum's impl object: ${irClass.render()}" }
require(field == enumsSupport.getValuesField(irClass)) { "Expected VALUES field: ${field.render()}" }
val accessor = cachesAbiSupport.getEnumValuesAccessor(enumClass)
context.llvmImports.add(enumClass.llvmSymbolOrigin)
return irCall(expression.startOffset, expression.endOffset, accessor, emptyList())
}
else -> expression
@@ -8,6 +8,7 @@ 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.konan.Context
import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENTRY_POINT
import org.jetbrains.kotlin.backend.konan.KonanFqNames
import org.jetbrains.kotlin.backend.konan.llvm.FieldStorageKind
import org.jetbrains.kotlin.backend.konan.llvm.needsGCRegistration
@@ -81,7 +82,7 @@ internal class FileInitializersLowering(val context: Context) : FileLoweringPass
else null
irFile.simpleFunctions()
.filterNot { it.isModuleInitializer }
.filterNot { it.isModuleInitializer || it.origin == DECLARATION_ORIGIN_ENTRY_POINT }
.forEach {
val body = it.body ?: return@forEach
val statements = (body as IrBlockBody).statements