[K/N][IR] Reworked caches ABI lowering
This commit is contained in:
+5
-5
@@ -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>()
|
||||
|
||||
+21
-41
@@ -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 {
|
||||
|
||||
-103
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
@@ -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")
|
||||
}
|
||||
|
||||
-1
@@ -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() }
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
-2
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
+137
-112
@@ -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
|
||||
|
||||
+2
-1
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user