Add global accessors to companion objects.
It fixes IrGetObjectValue evaluation in case of Lazy IR.
This commit is contained in:
committed by
Sergey Bogolepov
parent
88b2955bb3
commit
9f457dce80
-1
@@ -292,7 +292,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
throw Error("Another IrModule in the context.")
|
||||
}
|
||||
field = module!!
|
||||
internalAbi.init(module)
|
||||
ir = KonanIr(this, module)
|
||||
}
|
||||
|
||||
|
||||
+10
-27
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.builders.irBlockBody
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||
@@ -109,37 +110,19 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
||||
|
||||
// We can't move property getter to the top-level scope.
|
||||
// So add a wrapper instead.
|
||||
private fun createValuesGetterWrapper(enumClass: IrClass, isExternal: Boolean): IrSimpleFunction {
|
||||
return WrappedSimpleFunctionDescriptor().let {
|
||||
val valuesType = valuesArrayType(enumClass)
|
||||
val origin = if (isExternal) InternalAbi.INTERNAL_ABI_ORIGIN else DECLARATION_ORIGIN_ENUM
|
||||
val name = context.internalAbi.getMangledNameFor("get-VALUES", enumClass)
|
||||
IrFunctionImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
origin,
|
||||
IrSimpleFunctionSymbolImpl(it),
|
||||
name,
|
||||
DescriptorVisibilities.PUBLIC,
|
||||
Modality.FINAL,
|
||||
valuesType,
|
||||
isInline = false,
|
||||
isExternal = isExternal,
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
isExpect = false,
|
||||
isFakeOverride = false,
|
||||
isOperator = false,
|
||||
isInfix = false
|
||||
).apply {
|
||||
it.bind(this)
|
||||
private fun createValuesGetterWrapper(enumClass: IrClass, isExternal: Boolean): IrSimpleFunction =
|
||||
context.irFactory.buildFun {
|
||||
name = InternalAbi.getEnumValuesAccessorName(enumClass)
|
||||
returnType = valuesArrayType(enumClass)
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
this.isExternal = isExternal
|
||||
}.also {
|
||||
if (isExternal) {
|
||||
context.internalAbi.reference(this, enumClass.module)
|
||||
context.internalAbi.reference(it, enumClass.module)
|
||||
} else {
|
||||
context.internalAbi.declare(this)
|
||||
context.internalAbi.declare(it, enumClass.module)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createExternalLoweredEnum(enumClass: IrClass): ExternalLoweredEnum {
|
||||
val enumEntriesMap = enumEntriesMap(enumClass)
|
||||
|
||||
+28
-18
@@ -10,7 +10,9 @@ import org.jetbrains.kotlin.backend.konan.llvm.llvmSymbolOrigin
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
|
||||
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
|
||||
|
||||
@@ -22,22 +24,24 @@ import org.jetbrains.kotlin.name.Name
|
||||
*/
|
||||
internal class InternalAbi(private val context: Context) {
|
||||
/**
|
||||
* File that stores all internal ABI declarations.
|
||||
* 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 internalAbiFile: IrFile
|
||||
private lateinit var internalAbiFiles: Map<ModuleDescriptor, IrFile>
|
||||
|
||||
/**
|
||||
* Representation of ABI files from external modules.
|
||||
*/
|
||||
private val externalModules = mutableMapOf<ModuleDescriptor, IrFile>()
|
||||
private val externalAbiFiles = mutableMapOf<ModuleDescriptor, IrFile>()
|
||||
|
||||
fun init(module: IrModuleFragment) {
|
||||
internalAbiFile = createAbiFile(module)
|
||||
fun init(modules: List<IrModuleFragment>) {
|
||||
internalAbiFiles = modules.associate { it.descriptor to createAbiFile(it) }
|
||||
}
|
||||
|
||||
private fun createAbiFile(module: IrModuleFragment): IrFile =
|
||||
@@ -49,24 +53,16 @@ internal class InternalAbi(private val context: Context) {
|
||||
fun reference(function: IrFunction, module: ModuleDescriptor) {
|
||||
assert(function.isExternal) { "Function that represents external ABI should be marked as external" }
|
||||
context.llvmImports.add(module.llvmSymbolOrigin)
|
||||
externalModules.getOrPut(module) {
|
||||
externalAbiFiles.getOrPut(module) {
|
||||
createAbiFile(IrModuleFragmentImpl(module, context.irBuiltIns))
|
||||
}.addChild(function)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate name for declaration that will be a part of internal ABI.
|
||||
* Adds [function] to a list of [module]'s publicly available symbols.
|
||||
*/
|
||||
fun getMangledNameFor(declarationName: String, parent: IrDeclarationParent): Name {
|
||||
val prefix = parent.fqNameForIrSerialization
|
||||
return "$prefix.$declarationName".synthesizedName
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds [function] to a list of publicly available symbols.
|
||||
*/
|
||||
fun declare(function: IrFunction) {
|
||||
internalAbiFile.addChild(function)
|
||||
fun declare(function: IrFunction, module: ModuleDescriptor) {
|
||||
internalAbiFiles.getValue(module).addChild(function)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -74,5 +70,19 @@ internal class InternalAbi(private val context: Context) {
|
||||
* 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)
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -157,6 +157,8 @@ internal fun Context.psiToIr(symbolTable: SymbolTable) {
|
||||
// Note: coupled with [shouldLower] below.
|
||||
irModules = linker.modules.filterValues { llvmModuleSpecification.containsModule(it) }
|
||||
|
||||
internalAbi.init(irModules.values + irModule!!)
|
||||
|
||||
ir.symbols = symbols
|
||||
|
||||
functionIrClassFactory.module =
|
||||
|
||||
+78
-25
@@ -3,19 +3,9 @@ package org.jetbrains.kotlin.backend.konan
|
||||
import org.jetbrains.kotlin.backend.common.CheckDeclarationParentsVisitor
|
||||
import org.jetbrains.kotlin.backend.common.IrValidator
|
||||
import org.jetbrains.kotlin.backend.common.IrValidatorConfig
|
||||
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
|
||||
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideChecker
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.phaser.*
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker
|
||||
import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter
|
||||
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumAndCStructStubs
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||
@@ -23,23 +13,22 @@ import org.jetbrains.kotlin.backend.konan.serialization.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin
|
||||
import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.builders.irBlockBody
|
||||
import org.jetbrains.kotlin.ir.builders.irGetObjectValue
|
||||
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import java.util.Collections.emptySet
|
||||
|
||||
internal fun moduleValidationCallback(state: ActionState, module: IrModuleFragment, context: Context) {
|
||||
@@ -320,6 +309,67 @@ internal val entryPointPhase = makeCustomPhase<Context, IrModuleFragment>(
|
||||
}
|
||||
)
|
||||
|
||||
internal val exportInternalAbiPhase = makeKonanModuleOpPhase(
|
||||
name = "exportInternalAbi",
|
||||
description = "Add accessors to private entities",
|
||||
prerequisite = emptySet(),
|
||||
op = { context, module ->
|
||||
val visitor = object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
if (declaration.isCompanion) {
|
||||
val function = context.irFactory.buildFun {
|
||||
name = InternalAbi.getCompanionObjectAccessorName(declaration)
|
||||
origin = InternalAbi.INTERNAL_ABI_ORIGIN
|
||||
returnType = declaration.defaultType
|
||||
}
|
||||
context.createIrBuilder(function.symbol).apply {
|
||||
function.body = irBlockBody {
|
||||
+irReturn(irGetObjectValue(declaration.defaultType, declaration.symbol))
|
||||
}
|
||||
}
|
||||
context.internalAbi.declare(function, declaration.module)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
module.acceptChildrenVoid(visitor)
|
||||
}
|
||||
)
|
||||
|
||||
internal val useInternalAbiPhase = makeKonanModuleOpPhase(
|
||||
name = "useInternalAbi",
|
||||
description = "Use internal ABI functions to access private entities",
|
||||
prerequisite = emptySet(),
|
||||
op = { context, module ->
|
||||
val accessors = mutableMapOf<IrClass, IrSimpleFunction>()
|
||||
val transformer = object : IrElementTransformerVoid() {
|
||||
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
||||
val irClass = expression.symbol.owner
|
||||
if (!irClass.isCompanion || context.llvmModuleSpecification.containsDeclaration(irClass)) {
|
||||
return expression
|
||||
}
|
||||
val accessor = accessors.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)
|
||||
}
|
||||
}
|
||||
module.transformChildrenVoid(transformer)
|
||||
}
|
||||
)
|
||||
|
||||
internal val bitcodePhase = NamedCompilerPhase(
|
||||
name = "Bitcode",
|
||||
description = "LLVM Bitcode generation",
|
||||
@@ -346,6 +396,8 @@ private val backendCodegen = namedUnitPhase(
|
||||
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
||||
// With that we guarantee that inline functions are unlowered while being inlined.
|
||||
entryPointPhase then
|
||||
exportInternalAbiPhase then
|
||||
useInternalAbiPhase then
|
||||
bitcodePhase then
|
||||
verifyBitcodePhase then
|
||||
printBitcodePhase then
|
||||
@@ -395,6 +447,7 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
|
||||
disableUnless(serializerPhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||
disableIf(dependenciesLowerPhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||
disableUnless(entryPointPhase, config.produce == CompilerOutputKind.PROGRAM)
|
||||
disableUnless(exportInternalAbiPhase, config.produce.isCache)
|
||||
disableIf(bitcodePhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||
disableUnless(bitcodeOptimizationPhase, config.produce.involvesLinkStage)
|
||||
disableUnless(linkBitcodeDependenciesPhase, config.produce.involvesLinkStage)
|
||||
|
||||
Reference in New Issue
Block a user