[K/N] Refactor staticData to support several llvm modules
This commit is contained in:
+2
-2
@@ -157,7 +157,7 @@ internal interface ContextUtils : RuntimeAware {
|
|||||||
val llvmTargetData: LLVMTargetDataRef
|
val llvmTargetData: LLVMTargetDataRef
|
||||||
get() = runtime.targetData
|
get() = runtime.targetData
|
||||||
|
|
||||||
val staticData: StaticData
|
val staticData: KotlinStaticData
|
||||||
get() = context.llvm.staticData
|
get() = context.llvm.staticData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -427,7 +427,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) : Runti
|
|||||||
|
|
||||||
val additionalProducedBitcodeFiles = mutableListOf<String>()
|
val additionalProducedBitcodeFiles = mutableListOf<String>()
|
||||||
|
|
||||||
val staticData = StaticData(context)
|
val staticData = KotlinStaticData(context)
|
||||||
|
|
||||||
private val target = context.config.target
|
private val target = context.config.target
|
||||||
|
|
||||||
|
|||||||
+126
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 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.llvm
|
||||||
|
|
||||||
|
import kotlinx.cinterop.cValuesOf
|
||||||
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
|
|
||||||
|
private fun ConstPointer.add(index: Int): ConstPointer {
|
||||||
|
return constPointer(LLVMConstGEP(llvm, cValuesOf(Int32(index).llvm), 1)!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class KotlinStaticData(override val context: Context) : ContextUtils, StaticData(context.llvmModule!!) {
|
||||||
|
private val stringLiterals = mutableMapOf<String, ConstPointer>()
|
||||||
|
|
||||||
|
// Must match OBJECT_TAG_PERMANENT_CONTAINER in C++.
|
||||||
|
private fun permanentTag(typeInfo: ConstPointer): ConstPointer {
|
||||||
|
// Only pointer arithmetic via GEP works on constant pointers in LLVM.
|
||||||
|
return typeInfo.bitcast(int8TypePtr).add(1).bitcast(kTypeInfoPtr)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun objHeader(typeInfo: ConstPointer): Struct {
|
||||||
|
return Struct(runtime.objHeaderType, permanentTag(typeInfo))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun arrayHeader(typeInfo: ConstPointer, length: Int): Struct {
|
||||||
|
assert(length >= 0)
|
||||||
|
return Struct(runtime.arrayHeaderType, permanentTag(typeInfo), Int32(length))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createRef(objHeaderPtr: ConstPointer) = objHeaderPtr.bitcast(kObjHeaderPtr)
|
||||||
|
|
||||||
|
private fun createKotlinStringLiteral(value: String): ConstPointer {
|
||||||
|
val elements = value.toCharArray().map(::Char16)
|
||||||
|
val objRef = createConstKotlinArray(context.ir.symbols.string.owner, elements)
|
||||||
|
return objRef
|
||||||
|
}
|
||||||
|
|
||||||
|
fun kotlinStringLiteral(value: String) = stringLiterals.getOrPut(value) { createKotlinStringLiteral(value) }
|
||||||
|
|
||||||
|
fun createConstKotlinArray(arrayClass: IrClass, elements: List<LLVMValueRef>) =
|
||||||
|
createConstKotlinArray(arrayClass, elements.map { constValue(it) }).llvm
|
||||||
|
|
||||||
|
fun createConstKotlinArray(arrayClass: IrClass, elements: List<ConstValue>): ConstPointer {
|
||||||
|
val typeInfo = arrayClass.typeInfoPtr
|
||||||
|
|
||||||
|
val bodyElementType: LLVMTypeRef = elements.firstOrNull()?.llvmType ?: int8Type
|
||||||
|
// (use [0 x i8] as body if there are no elements)
|
||||||
|
val arrayBody = ConstArray(bodyElementType, elements)
|
||||||
|
|
||||||
|
val compositeType = structType(runtime.arrayHeaderType, arrayBody.llvmType)
|
||||||
|
|
||||||
|
val global = this.createGlobal(compositeType, "")
|
||||||
|
|
||||||
|
val objHeaderPtr = global.pointer.getElementPtr(0)
|
||||||
|
val arrayHeader = arrayHeader(typeInfo, elements.size)
|
||||||
|
|
||||||
|
global.setInitializer(Struct(compositeType, arrayHeader, arrayBody))
|
||||||
|
global.setConstant(true)
|
||||||
|
global.setUnnamedAddr(true)
|
||||||
|
|
||||||
|
return createRef(objHeaderPtr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createConstKotlinObject(type: IrClass, vararg fields: ConstValue): ConstPointer {
|
||||||
|
val typeInfo = type.typeInfoPtr
|
||||||
|
val objHeader = objHeader(typeInfo)
|
||||||
|
|
||||||
|
val global = this.placeGlobal("", Struct(objHeader, *fields))
|
||||||
|
global.setUnnamedAddr(true)
|
||||||
|
global.setConstant(true)
|
||||||
|
|
||||||
|
val objHeaderPtr = global.pointer.getElementPtr(0)
|
||||||
|
|
||||||
|
return createRef(objHeaderPtr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createInitializer(type: IrClass, vararg fields: ConstValue): ConstValue =
|
||||||
|
Struct(objHeader(type.typeInfoPtr), *fields)
|
||||||
|
|
||||||
|
fun createUniqueInstance(
|
||||||
|
kind: UniqueKind, bodyType: LLVMTypeRef, typeInfo: ConstPointer): ConstPointer {
|
||||||
|
assert(getStructElements(bodyType).size == 1) // ObjHeader only.
|
||||||
|
val objHeader = when (kind) {
|
||||||
|
UniqueKind.UNIT -> objHeader(typeInfo)
|
||||||
|
UniqueKind.EMPTY_ARRAY -> arrayHeader(typeInfo, 0)
|
||||||
|
}
|
||||||
|
val global = this.placeGlobal(kind.llvmName, objHeader, isExported = true)
|
||||||
|
global.setConstant(true)
|
||||||
|
return global.pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unique(kind: UniqueKind): ConstPointer {
|
||||||
|
val descriptor = when (kind) {
|
||||||
|
UniqueKind.UNIT -> context.ir.symbols.unit.owner
|
||||||
|
UniqueKind.EMPTY_ARRAY -> context.ir.symbols.array.owner
|
||||||
|
}
|
||||||
|
return if (isExternal(descriptor)) {
|
||||||
|
constPointer(importGlobal(
|
||||||
|
kind.llvmName, context.llvm.runtime.objHeaderType, origin = descriptor.llvmSymbolOrigin
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
context.llvmDeclarations.forUnique(kind).pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates static instance of `konan.ImmutableByteArray` with given values of elements.
|
||||||
|
*
|
||||||
|
* @param args data for constant creation.
|
||||||
|
*/
|
||||||
|
fun createImmutableBlob(value: IrConst<String>): LLVMValueRef {
|
||||||
|
val args = value.value.map { Int8(it.code.toByte()).llvm }
|
||||||
|
return createConstKotlinArray(context.ir.symbols.immutableBlob.owner, args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val ContextUtils.theUnitInstanceRef: ConstPointer
|
||||||
|
get() = staticData.unique(UniqueKind.UNIT)
|
||||||
+26
-72
@@ -7,17 +7,16 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides utilities to create static data.
|
* Provides utilities to create static data.
|
||||||
*/
|
*/
|
||||||
internal class StaticData(override val context: Context): ContextUtils {
|
internal open class StaticData(val module: LLVMModuleRef) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the LLVM global variable.
|
* Represents the LLVM global variable.
|
||||||
*/
|
*/
|
||||||
class Global private constructor(val staticData: StaticData, val llvmGlobal: LLVMValueRef) {
|
class Global private constructor(val llvmGlobal: LLVMValueRef) {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private fun createLlvmGlobal(module: LLVMModuleRef,
|
private fun createLlvmGlobal(module: LLVMModuleRef,
|
||||||
@@ -41,20 +40,18 @@ internal class StaticData(override val context: Context): ContextUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun create(staticData: StaticData, type: LLVMTypeRef, name: String, isExported: Boolean): Global {
|
fun create(staticData: StaticData, type: LLVMTypeRef, name: String, isExported: Boolean): Global {
|
||||||
val module = staticData.context.llvmModule
|
|
||||||
|
|
||||||
val isUnnamed = (name == "") // LLVM will select the unique index and represent the global as `@idx`.
|
val isUnnamed = (name == "") // LLVM will select the unique index and represent the global as `@idx`.
|
||||||
if (isUnnamed && isExported) {
|
if (isUnnamed && isExported) {
|
||||||
throw IllegalArgumentException("unnamed global can't be exported")
|
throw IllegalArgumentException("unnamed global can't be exported")
|
||||||
}
|
}
|
||||||
|
|
||||||
val llvmGlobal = createLlvmGlobal(module!!, type, name, isExported)
|
val llvmGlobal = createLlvmGlobal(staticData.module, type, name, isExported)
|
||||||
return Global(staticData, llvmGlobal)
|
return Global(llvmGlobal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(staticData: StaticData, name: String): Global? {
|
fun get(staticData: StaticData, name: String): Global? {
|
||||||
val llvmGlobal = LLVMGetNamedGlobal(staticData.context.llvmModule, name) ?: return null
|
val llvmGlobal = LLVMGetNamedGlobal(staticData.module, name) ?: return null
|
||||||
return Global(staticData, llvmGlobal)
|
return Global(llvmGlobal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,54 +94,7 @@ internal class StaticData(override val context: Context): ContextUtils {
|
|||||||
LLVMSetExternallyInitialized(llvmGlobal, if (value) 1 else 0)
|
LLVMSetExternallyInitialized(llvmGlobal, if (value) 1 else 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val pointer = Pointer.to(this)
|
val pointer : ConstPointer = constPointer(this.llvmGlobal)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the pointer to static data.
|
|
||||||
* It can be a pointer to either a global or any its element.
|
|
||||||
*
|
|
||||||
* TODO: this class is probably should be implemented more optimally
|
|
||||||
*/
|
|
||||||
class Pointer private constructor(val global: Global,
|
|
||||||
private val delegate: ConstPointer,
|
|
||||||
val offsetInGlobal: Long) : ConstPointer by delegate {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun to(global: Global) = Pointer(global, constPointer(global.llvmGlobal), 0L)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getElementOffset(index: Int): Long {
|
|
||||||
val llvmTargetData = global.staticData.llvmTargetData
|
|
||||||
val type = LLVMGetElementType(delegate.llvmType)
|
|
||||||
return when (LLVMGetTypeKind(type)) {
|
|
||||||
LLVMTypeKind.LLVMStructTypeKind -> LLVMOffsetOfElement(llvmTargetData, type, index)
|
|
||||||
LLVMTypeKind.LLVMArrayTypeKind -> LLVMABISizeOfType(llvmTargetData, LLVMGetElementType(type)) * index
|
|
||||||
else -> TODO()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getElementPtr(index: Int): Pointer {
|
|
||||||
return Pointer(global, delegate.getElementPtr(index), offsetInGlobal + this.getElementOffset(index))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the distance from other pointer to this.
|
|
||||||
*
|
|
||||||
* @throws UnsupportedOperationException if it is not possible to represent the distance as [Int] value
|
|
||||||
*/
|
|
||||||
fun sub(other: Pointer): Int {
|
|
||||||
if (this.global != other.global) {
|
|
||||||
throw UnsupportedOperationException("pointers must belong to the same global")
|
|
||||||
}
|
|
||||||
|
|
||||||
val res = this.offsetInGlobal - other.offsetInGlobal
|
|
||||||
if (res.toInt().toLong() != res) {
|
|
||||||
throw UnsupportedOperationException("result doesn't fit into Int")
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.toInt()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,22 +129,26 @@ internal class StaticData(override val context: Context): ContextUtils {
|
|||||||
return global
|
return global
|
||||||
}
|
}
|
||||||
|
|
||||||
private val stringLiterals = mutableMapOf<String, ConstPointer>()
|
|
||||||
private val cStringLiterals = mutableMapOf<String, ConstPointer>()
|
private val cStringLiterals = mutableMapOf<String, ConstPointer>()
|
||||||
|
|
||||||
fun cStringLiteral(value: String) =
|
internal fun placeGlobalConstArray(name: String,
|
||||||
cStringLiterals.getOrPut(value) { placeCStringLiteral(value) }
|
elemType: LLVMTypeRef,
|
||||||
|
elements: List<ConstValue>,
|
||||||
|
isExported: Boolean = false): ConstPointer {
|
||||||
|
if (elements.isNotEmpty() || isExported) {
|
||||||
|
val global = placeGlobalArray(name, elemType, elements, isExported)
|
||||||
|
global.setConstant(true)
|
||||||
|
return global.pointer.getElementPtr(0)
|
||||||
|
} else {
|
||||||
|
return NullPointer(elemType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun kotlinStringLiteral(value: String) =
|
internal fun placeCStringLiteral(value: String) : ConstPointer {
|
||||||
stringLiterals.getOrPut(value) { createKotlinStringLiteral(value) }
|
val chars = value.toByteArray(Charsets.UTF_8).map { Int8(it) } + Int8(0)
|
||||||
|
|
||||||
|
return placeGlobalConstArray("", int8Type, chars)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun cStringLiteral(value: String) = cStringLiterals.getOrPut(value) { placeCStringLiteral(value) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates static instance of `konan.ImmutableByteArray` with given values of elements.
|
|
||||||
*
|
|
||||||
* @param args data for constant creation.
|
|
||||||
*/
|
|
||||||
internal fun StaticData.createImmutableBlob(value: IrConst<String>): LLVMValueRef {
|
|
||||||
val args = value.value.map { Int8(it.code.toByte()).llvm }
|
|
||||||
return createConstKotlinArray(context.ir.symbols.immutableBlob.owner, args)
|
|
||||||
}
|
|
||||||
-38
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 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.llvm
|
|
||||||
|
|
||||||
import llvm.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates const array-typed global with given name and value.
|
|
||||||
* Returns pointer to the first element of the array.
|
|
||||||
*
|
|
||||||
* If [elements] is empty, then null pointer is returned.
|
|
||||||
*/
|
|
||||||
internal fun StaticData.placeGlobalConstArray(name: String,
|
|
||||||
elemType: LLVMTypeRef,
|
|
||||||
elements: List<ConstValue>,
|
|
||||||
isExported: Boolean = false): ConstPointer {
|
|
||||||
if (elements.isNotEmpty() || isExported) {
|
|
||||||
val global = this.placeGlobalArray(name, elemType, elements, isExported)
|
|
||||||
global.setConstant(true)
|
|
||||||
return global.pointer.getElementPtr(0)
|
|
||||||
} else {
|
|
||||||
return NullPointer(elemType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun StaticData.createAlias(name: String, aliasee: ConstPointer): ConstPointer {
|
|
||||||
val alias = LLVMAddAlias(context.llvmModule, aliasee.llvmType, aliasee.llvm, name)!!
|
|
||||||
return constPointer(alias)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun StaticData.placeCStringLiteral(value: String): ConstPointer {
|
|
||||||
val chars = value.toByteArray(Charsets.UTF_8).map { Int8(it) } + Int8(0)
|
|
||||||
|
|
||||||
return placeGlobalConstArray("", int8Type, chars)
|
|
||||||
}
|
|
||||||
-107
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 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.llvm
|
|
||||||
|
|
||||||
import kotlinx.cinterop.cValuesOf
|
|
||||||
import llvm.*
|
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.llvmSymbolOrigin
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
|
||||||
|
|
||||||
private fun ConstPointer.add(index: Int): ConstPointer {
|
|
||||||
return constPointer(LLVMConstGEP(llvm, cValuesOf(Int32(index).llvm), 1)!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must match OBJECT_TAG_PERMANENT_CONTAINER in C++.
|
|
||||||
private fun StaticData.permanentTag(typeInfo: ConstPointer): ConstPointer {
|
|
||||||
// Only pointer arithmetic via GEP works on constant pointers in LLVM.
|
|
||||||
return typeInfo.bitcast(int8TypePtr).add(1).bitcast(kTypeInfoPtr)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun StaticData.objHeader(typeInfo: ConstPointer): Struct {
|
|
||||||
return Struct(runtime.objHeaderType, permanentTag(typeInfo))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun StaticData.arrayHeader(typeInfo: ConstPointer, length: Int): Struct {
|
|
||||||
assert (length >= 0)
|
|
||||||
return Struct(runtime.arrayHeaderType, permanentTag(typeInfo), Int32(length))
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun StaticData.createKotlinStringLiteral(value: String): ConstPointer {
|
|
||||||
val elements = value.toCharArray().map(::Char16)
|
|
||||||
val objRef = createConstKotlinArray(context.ir.symbols.string.owner, elements)
|
|
||||||
return objRef
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun StaticData.createRef(objHeaderPtr: ConstPointer) = objHeaderPtr.bitcast(kObjHeaderPtr)
|
|
||||||
|
|
||||||
internal fun StaticData.createConstKotlinArray(arrayClass: IrClass, elements: List<LLVMValueRef>) =
|
|
||||||
createConstKotlinArray(arrayClass, elements.map { constValue(it) }).llvm
|
|
||||||
|
|
||||||
internal fun StaticData.createConstKotlinArray(arrayClass: IrClass, elements: List<ConstValue>): ConstPointer {
|
|
||||||
val typeInfo = arrayClass.typeInfoPtr
|
|
||||||
|
|
||||||
val bodyElementType: LLVMTypeRef = elements.firstOrNull()?.llvmType ?: int8Type
|
|
||||||
// (use [0 x i8] as body if there are no elements)
|
|
||||||
val arrayBody = ConstArray(bodyElementType, elements)
|
|
||||||
|
|
||||||
val compositeType = structType(runtime.arrayHeaderType, arrayBody.llvmType)
|
|
||||||
|
|
||||||
val global = this.createGlobal(compositeType, "")
|
|
||||||
|
|
||||||
val objHeaderPtr = global.pointer.getElementPtr(0)
|
|
||||||
val arrayHeader = arrayHeader(typeInfo, elements.size)
|
|
||||||
|
|
||||||
global.setInitializer(Struct(compositeType, arrayHeader, arrayBody))
|
|
||||||
global.setConstant(true)
|
|
||||||
global.setUnnamedAddr(true)
|
|
||||||
|
|
||||||
return createRef(objHeaderPtr)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun StaticData.createConstKotlinObject(type: IrClass, vararg fields: ConstValue): ConstPointer {
|
|
||||||
val typeInfo = type.typeInfoPtr
|
|
||||||
val objHeader = objHeader(typeInfo)
|
|
||||||
|
|
||||||
val global = this.placeGlobal("", Struct(objHeader, *fields))
|
|
||||||
global.setUnnamedAddr(true)
|
|
||||||
global.setConstant(true)
|
|
||||||
|
|
||||||
val objHeaderPtr = global.pointer.getElementPtr(0)
|
|
||||||
|
|
||||||
return createRef(objHeaderPtr)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun StaticData.createInitializer(type: IrClass, vararg fields: ConstValue): ConstValue =
|
|
||||||
Struct(objHeader(type.typeInfoPtr), *fields)
|
|
||||||
|
|
||||||
internal fun StaticData.createUniqueInstance(
|
|
||||||
kind: UniqueKind, bodyType: LLVMTypeRef, typeInfo: ConstPointer): ConstPointer {
|
|
||||||
assert (getStructElements(bodyType).size == 1) // ObjHeader only.
|
|
||||||
val objHeader = when (kind) {
|
|
||||||
UniqueKind.UNIT -> objHeader(typeInfo)
|
|
||||||
UniqueKind.EMPTY_ARRAY -> arrayHeader(typeInfo, 0)
|
|
||||||
}
|
|
||||||
val global = this.placeGlobal(kind.llvmName, objHeader, isExported = true)
|
|
||||||
global.setConstant(true)
|
|
||||||
return global.pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun ContextUtils.unique(kind: UniqueKind): ConstPointer {
|
|
||||||
val descriptor = when (kind) {
|
|
||||||
UniqueKind.UNIT -> context.ir.symbols.unit.owner
|
|
||||||
UniqueKind.EMPTY_ARRAY -> context.ir.symbols.array.owner
|
|
||||||
}
|
|
||||||
return if (isExternal(descriptor)) {
|
|
||||||
constPointer(importGlobal(
|
|
||||||
kind.llvmName, context.llvm.runtime.objHeaderType, origin = descriptor.llvmSymbolOrigin
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
context.llvmDeclarations.forUnique(kind).pointer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val ContextUtils.theUnitInstanceRef: ConstPointer
|
|
||||||
get() = this.unique(UniqueKind.UNIT)
|
|
||||||
Reference in New Issue
Block a user