[K/N] LLVM: Transition to opaque pointers
This commit is contained in:
committed by
Space Cloud
parent
c1f72de6e5
commit
b059754f64
+11
-4
@@ -5,9 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import llvm.LLVMArrayType
|
||||
import llvm.LLVMConstInt
|
||||
import llvm.LLVMTypeRef
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.getOrPut
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.ConstValue
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.StaticData
|
||||
@@ -183,7 +181,16 @@ internal fun IrConstantPrimitive.toBoxCacheValue(generationState: NativeGenerati
|
||||
val (start, end) = generationState.config.target.getBoxCacheRange(cacheType)
|
||||
return if (value in start..end) {
|
||||
generationState.llvm.let { llvm ->
|
||||
llvm.boxCacheGlobals[cacheType]?.pointer?.getElementPtr(llvm, value.toInt() - start)?.getElementPtr(llvm, 0)
|
||||
val llvmType = llvm.structType(llvm.runtime.objHeaderType, when (cacheType) {
|
||||
BoxCache.BOOLEAN -> llvm.int1Type
|
||||
BoxCache.BYTE -> llvm.int8Type
|
||||
BoxCache.SHORT -> llvm.int16Type
|
||||
BoxCache.CHAR -> llvm.int16Type
|
||||
BoxCache.INT -> llvm.int32Type
|
||||
BoxCache.LONG -> llvm.int64Type
|
||||
})
|
||||
val llvmArrayType = LLVMArrayType(llvmType, end - start + 1)!!
|
||||
llvm.boxCacheGlobals[cacheType]?.pointer?.getElementPtr(llvm, llvmArrayType, value.toInt() - start)?.getElementPtr(llvm, llvmType, 0)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
|
||||
+2
-1
@@ -127,7 +127,8 @@ private class CallsChecker(generationState: NativeGenerationState, goodFunctions
|
||||
callSiteDescription = "$functionName (over objc_msgSendSuper2)"
|
||||
calledName = null
|
||||
val superStruct = LLVMGetArgOperand(call, 0)
|
||||
val superClassPtrPtr = LLVMBuildGEP(builder, superStruct, listOf(llvm.int32(0), llvm.int32(1)).toCValues(), 2, "")
|
||||
val superStructType = llvm.structType(llvm.int8PtrType, llvm.int8PtrType)
|
||||
val superClassPtrPtr = LLVMBuildStructGEP2(builder, superStructType, superStruct, 1, "")
|
||||
val superClassPtr = LLVMBuildLoad2(builder, llvm.int8PtrType, superClassPtrPtr, "")!!
|
||||
val classPtr = getSuperClass.buildCall(builder, listOf(superClassPtr))
|
||||
val calledPtrLlvmFunPtr = getMethodImpl.buildCall(builder, listOf(classPtr, LLVMGetArgOperand(call, 1)!!))
|
||||
|
||||
+2
-1
@@ -148,7 +148,8 @@ internal fun insertAliasToEntryPoint(context: PhaseContext, module: LLVMModuleRe
|
||||
val entryPointName = config.entryPointName
|
||||
val entryPoint = LLVMGetNamedFunction(module, entryPointName)
|
||||
?: error("Module doesn't contain `$entryPointName`")
|
||||
LLVMAddAlias(module, LLVMTypeOf(entryPoint)!!, entryPoint, "main")
|
||||
val programAddressSpace = LLVMGetProgramAddressSpace(module)
|
||||
LLVMAddAlias2(module, getGlobalFunctionType(entryPoint), programAddressSpace, entryPoint, "main")
|
||||
}
|
||||
|
||||
internal fun linkBitcodeDependencies(generationState: NativeGenerationState,
|
||||
|
||||
+30
-26
@@ -209,13 +209,13 @@ private inline fun <T : FunctionGenerationContext> generateFunctionBody(
|
||||
internal object VirtualTablesLookup {
|
||||
private fun FunctionGenerationContext.getInterfaceTableRecord(typeInfo: LLVMValueRef, interfaceId: Int): LLVMValueRef {
|
||||
val interfaceTableRecordPtrType = pointerType(runtime.interfaceTableRecordType)
|
||||
val interfaceTableSize = load(llvm.int32Type, structGep(typeInfo, 9 /* interfaceTableSize_ */))
|
||||
val interfaceTable = load(interfaceTableRecordPtrType, structGep(typeInfo, 10 /* interfaceTable_ */))
|
||||
val interfaceTableSize = load(llvm.int32Type, structGep(runtime.typeInfoType, typeInfo, 9 /* interfaceTableSize_ */))
|
||||
val interfaceTable = load(interfaceTableRecordPtrType, structGep(runtime.typeInfoType, typeInfo, 10 /* interfaceTable_ */))
|
||||
|
||||
fun fastPath(): LLVMValueRef {
|
||||
// The fastest optimistic version.
|
||||
val interfaceTableIndex = and(interfaceTableSize, llvm.int32(interfaceId))
|
||||
return gep(interfaceTable, interfaceTableIndex)
|
||||
return gep(runtime.interfaceTableRecordType, interfaceTable, interfaceTableIndex)
|
||||
}
|
||||
|
||||
// See details in ClassLayoutBuilder.
|
||||
@@ -260,7 +260,7 @@ internal object VirtualTablesLookup {
|
||||
// Essentially: typeInfo.itable[place(interfaceId)].id == interfaceId
|
||||
val interfaceId = dstHierarchyInfo.interfaceId
|
||||
val interfaceTableRecord = getInterfaceTableRecord(objTypeInfo, interfaceId)
|
||||
icmpEq(load(llvm.int32Type, structGep(interfaceTableRecord, 0 /* id */)), llvm.int32(interfaceId))
|
||||
icmpEq(load(llvm.int32Type, structGep(runtime.interfaceTableRecordType, interfaceTableRecord, 0 /* id */)), llvm.int32(interfaceId))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,14 +278,15 @@ internal object VirtualTablesLookup {
|
||||
val canCallViaVtable = !owner.isInterface
|
||||
val layoutBuilder = generationState.context.getLayoutBuilder(owner)
|
||||
|
||||
val functionPtrType = pointerType(codegen.getLlvmFunctionType(irFunction))
|
||||
val functionType = codegen.getLlvmFunctionType(irFunction)
|
||||
val functionPtrType = pointerType(functionType)
|
||||
val functionPtrPtrType = pointerType(functionPtrType)
|
||||
val llvmMethod = when {
|
||||
canCallViaVtable -> {
|
||||
val index = layoutBuilder.vtableIndex(irFunction)
|
||||
val vtablePlace = gep(typeInfoPtr, llvm.int32(1)) // typeInfoPtr + 1
|
||||
val vtablePlace = gep(runtime.typeInfoType, typeInfoPtr, llvm.int32(1)) // typeInfoPtr + 1
|
||||
val vtable = bitcast(llvm.int8PtrPtrType, vtablePlace)
|
||||
val slot = gep(vtable, llvm.int32(index))
|
||||
val slot = gep(llvm.int8PtrType, vtable, llvm.int32(index))
|
||||
load(functionPtrType, bitcast(functionPtrPtrType, slot))
|
||||
}
|
||||
|
||||
@@ -293,12 +294,13 @@ internal object VirtualTablesLookup {
|
||||
// Essentially: typeInfo.itable[place(interfaceId)].vtable[method]
|
||||
val itablePlace = layoutBuilder.itablePlace(irFunction)
|
||||
val interfaceTableRecord = getInterfaceTableRecord(typeInfoPtr, itablePlace.interfaceId)
|
||||
val vtable = load(llvm.int8PtrPtrType, structGep(interfaceTableRecord, 2 /* vtable */))
|
||||
val slot = gep(vtable, llvm.int32(itablePlace.methodIndex))
|
||||
val vtable = load(llvm.int8PtrPtrType, structGep(runtime.interfaceTableRecordType, interfaceTableRecord, 2 /* vtable */))
|
||||
val slot = gep(llvm.int8PtrType, vtable, llvm.int32(itablePlace.methodIndex))
|
||||
load(functionPtrType, bitcast(functionPtrPtrType, slot))
|
||||
}
|
||||
}
|
||||
return LlvmCallable(
|
||||
functionType,
|
||||
bitcast(functionPtrType, llvmMethod),
|
||||
LlvmFunctionSignature(irFunction, this)
|
||||
)
|
||||
@@ -418,7 +420,7 @@ internal class StackLocalsManagerImpl(
|
||||
|
||||
memset(bitcast(llvm.int8PtrType, stackSlot), 0, LLVMSizeOfTypeInBits(codegen.llvmTargetData, type).toInt() / 8)
|
||||
|
||||
val objectHeader = structGep(stackSlot, 0, "objHeader")
|
||||
val objectHeader = structGep(type, stackSlot, 0, "objHeader")
|
||||
val typeInfo = codegen.typeInfoForAllocation(irClass)
|
||||
setTypeInfoForLocalObject(objectHeader, typeInfo)
|
||||
val gcRootSetSlot = createRootSetSlot()
|
||||
@@ -472,12 +474,12 @@ internal class StackLocalsManagerImpl(
|
||||
val typeInfo = codegen.typeInfoValue(irClass)
|
||||
val arraySlot = LLVMBuildAlloca(builder, arrayType, "")!!
|
||||
// Set array size in ArrayHeader.
|
||||
val arrayHeaderSlot = structGep(arraySlot, 0, "arrayHeader")
|
||||
val arrayHeaderSlot = structGep(arrayType, arraySlot, 0, "arrayHeader")
|
||||
setTypeInfoForLocalObject(arrayHeaderSlot, typeInfo)
|
||||
val sizeField = structGep(arrayHeaderSlot, 1, "count_")
|
||||
val sizeField = structGep(runtime.arrayHeaderType, arrayHeaderSlot, 1, "count_")
|
||||
store(count, sizeField)
|
||||
|
||||
memset(bitcast(llvm.int8PtrType, structGep(arraySlot, 1, "arrayBody")),
|
||||
memset(bitcast(llvm.int8PtrType, structGep(arrayType, arraySlot, 1, "arrayBody")),
|
||||
0,
|
||||
constCount * LLVMSizeOfTypeInBits(codegen.llvmTargetData, arrayToElementType[irClass.symbol]).toInt() / 8
|
||||
)
|
||||
@@ -503,9 +505,10 @@ internal class StackLocalsManagerImpl(
|
||||
if (stackLocal.irClass.symbol == context.ir.symbols.array) {
|
||||
call(llvm.zeroArrayRefsFunction, listOf(stackLocal.objHeaderPtr))
|
||||
} else if (!refsOnly) {
|
||||
memset(bitcast(llvm.int8PtrType, structGep(stackLocal.stackAllocationPtr, 1, "arrayBody")),
|
||||
val arrayType = localArrayType(stackLocal.irClass, stackLocal.arraySize!!)
|
||||
memset(bitcast(llvm.int8PtrType, structGep(arrayType, stackLocal.stackAllocationPtr, 1, "arrayBody")),
|
||||
0,
|
||||
stackLocal.arraySize!! * LLVMSizeOfTypeInBits(codegen.llvmTargetData, arrayToElementType[stackLocal.irClass.symbol]).toInt() / 8
|
||||
stackLocal.arraySize * LLVMSizeOfTypeInBits(codegen.llvmTargetData, arrayToElementType[stackLocal.irClass.symbol]).toInt() / 8
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -515,7 +518,7 @@ internal class StackLocalsManagerImpl(
|
||||
val fieldType = LLVMStructGetTypeAtIndex(type, fieldIndex)!!
|
||||
|
||||
if (isObjectType(fieldType)) {
|
||||
val fieldPtr = LLVMBuildStructGEP(builder, stackLocal.stackAllocationPtr, fieldIndex, "")!!
|
||||
val fieldPtr = structGep(type, stackLocal.stackAllocationPtr, fieldIndex, "")
|
||||
if (refsOnly)
|
||||
storeHeapRef(kNullObjHeaderPtr, fieldPtr)
|
||||
else
|
||||
@@ -538,7 +541,7 @@ internal class StackLocalsManagerImpl(
|
||||
}
|
||||
|
||||
private fun setTypeInfoForLocalObject(objectHeader: LLVMValueRef, typeInfoPointer: LLVMValueRef) = with(functionGenerationContext) {
|
||||
val typeInfo = structGep(objectHeader, 0, "typeInfoOrMeta_")
|
||||
val typeInfo = structGep(runtime.objHeaderType, objectHeader, 0, "typeInfoOrMeta_")
|
||||
// Set tag OBJECT_TAG_PERMANENT_CONTAINER | OBJECT_TAG_NONTRIVIAL_CONTAINER.
|
||||
val typeInfoValue = intToPtr(or(ptrToInt(typeInfoPointer, codegen.intPtrType),
|
||||
codegen.immThreeIntPtrType), kTypeInfoPtr)
|
||||
@@ -681,7 +684,7 @@ internal abstract class FunctionGenerationContext(
|
||||
fun alloca(type: LLVMTypeRef?, name: String = "", variableLocation: VariableDebugLocation? = null): LLVMValueRef {
|
||||
if (isObjectType(type!!)) {
|
||||
appendingTo(localsInitBb) {
|
||||
val slotAddress = gep(slotsPhi!!, llvm.int32(slotCount), name)
|
||||
val slotAddress = gep(type, slotsPhi!!, llvm.int32(slotCount), name)
|
||||
variableLocation?.let {
|
||||
slotToVariableLocation[slotCount] = it
|
||||
}
|
||||
@@ -1036,11 +1039,12 @@ internal abstract class FunctionGenerationContext(
|
||||
|
||||
fun intToPtr(value: LLVMValueRef?, DestTy: LLVMTypeRef, Name: String = "") = LLVMBuildIntToPtr(builder, value, DestTy, Name)!!
|
||||
fun ptrToInt(value: LLVMValueRef?, DestTy: LLVMTypeRef, Name: String = "") = LLVMBuildPtrToInt(builder, value, DestTy, Name)!!
|
||||
fun gep(base: LLVMValueRef, index: LLVMValueRef, name: String = ""): LLVMValueRef {
|
||||
return LLVMBuildGEP(builder, base, cValuesOf(index), 1, name)!!
|
||||
}
|
||||
fun structGep(base: LLVMValueRef, index: Int, name: String = ""): LLVMValueRef =
|
||||
LLVMBuildStructGEP(builder, base, index, name)!!
|
||||
|
||||
fun gep(type: LLVMTypeRef, base: LLVMValueRef, index: LLVMValueRef, name: String = ""): LLVMValueRef =
|
||||
LLVMBuildGEP2(builder, type, base, cValuesOf(index), 1, name)!!
|
||||
|
||||
fun structGep(type: LLVMTypeRef, base: LLVMValueRef, index: Int, name: String = ""): LLVMValueRef =
|
||||
LLVMBuildStructGEP2(builder, type, base, index, name)!!
|
||||
|
||||
fun extractValue(aggregate: LLVMValueRef, index: Int, name: String = ""): LLVMValueRef =
|
||||
LLVMBuildExtractValue(builder, aggregate, index, name)!!
|
||||
@@ -1276,7 +1280,7 @@ internal abstract class FunctionGenerationContext(
|
||||
}
|
||||
|
||||
fun loadTypeInfo(objPtr: LLVMValueRef): LLVMValueRef {
|
||||
val typeInfoOrMetaPtr = structGep(objPtr, 0 /* typeInfoOrMeta_ */)
|
||||
val typeInfoOrMetaPtr = structGep(runtime.objHeaderType, objPtr, 0 /* typeInfoOrMeta_ */)
|
||||
|
||||
val memoryOrder = if (context.config.targetHasAddressDependency) {
|
||||
/**
|
||||
@@ -1294,7 +1298,7 @@ internal abstract class FunctionGenerationContext(
|
||||
// Clear two lower bits.
|
||||
val typeInfoOrMetaRaw = and(typeInfoOrMetaWithFlags, codegen.immTypeInfoMask)
|
||||
val typeInfoOrMeta = intToPtr(typeInfoOrMetaRaw, kTypeInfoPtr)
|
||||
val typeInfoPtrPtr = structGep(typeInfoOrMeta, 0 /* typeInfo */)
|
||||
val typeInfoPtrPtr = structGep(runtime.typeInfoType, typeInfoOrMeta, 0 /* typeInfo */)
|
||||
return load(codegen.kTypeInfoPtr, typeInfoPtrPtr, memoryOrder = LLVMAtomicOrdering.LLVMAtomicOrderingMonotonic)
|
||||
}
|
||||
|
||||
@@ -1345,7 +1349,7 @@ internal abstract class FunctionGenerationContext(
|
||||
}
|
||||
|
||||
val classInfo = codegen.kotlinObjCClassInfo(irClass)
|
||||
val classPointerGlobal = load(llvm.int8PtrPtrType, structGep(classInfo, KotlinObjCClassInfoGenerator.createdClassFieldIndex))
|
||||
val classPointerGlobal = load(llvm.int8PtrPtrType, structGep(runtime.kotlinObjCClassInfo, classInfo, KotlinObjCClassInfoGenerator.createdClassFieldIndex))
|
||||
|
||||
val storedClass = this.load(llvm.int8PtrType, classPointerGlobal)
|
||||
|
||||
|
||||
+7
-6
@@ -327,12 +327,12 @@ internal class CodegenLlvmHelpers(private val generationState: NativeGenerationS
|
||||
|
||||
val attributesCopier = LlvmFunctionAttributeProvider.copyFromExternal(externalFunction)
|
||||
|
||||
val functionType = getFunctionType(externalFunction)
|
||||
val functionType = getGlobalFunctionType(externalFunction)
|
||||
val function = LLVMAddFunction(module, name, functionType)!!
|
||||
|
||||
attributesCopier.addFunctionAttributes(function)
|
||||
|
||||
return LlvmCallable(function, attributesCopier)
|
||||
return LlvmCallable(functionType, function, attributesCopier)
|
||||
}
|
||||
|
||||
private fun importGlobal(name: String, otherModule: LLVMModuleRef): LLVMValueRef {
|
||||
@@ -358,7 +358,7 @@ internal class CodegenLlvmHelpers(private val generationState: NativeGenerationS
|
||||
val kindId = getLlvmAttributeKindId(it)
|
||||
addLlvmFunctionEnumAttribute(result, kindId)
|
||||
}
|
||||
return LlvmCallable(result, LlvmFunctionAttributeProvider.copyFromExternal(result))
|
||||
return LlvmCallable(type, result, LlvmFunctionAttributeProvider.copyFromExternal(result))
|
||||
}
|
||||
|
||||
internal fun externalFunction(llvmFunctionProto: LlvmFunctionProto): LlvmCallable {
|
||||
@@ -367,12 +367,13 @@ internal class CodegenLlvmHelpers(private val generationState: NativeGenerationS
|
||||
}
|
||||
val found = LLVMGetNamedFunction(module, llvmFunctionProto.name)
|
||||
if (found != null) {
|
||||
require(getFunctionType(found) == llvmFunctionProto.signature.llvmFunctionType) {
|
||||
require(getGlobalFunctionType(found) == llvmFunctionProto.signature.llvmFunctionType) {
|
||||
"Expected: ${LLVMPrintTypeToString(llvmFunctionProto.signature.llvmFunctionType)!!.toKString()} " +
|
||||
"found: ${LLVMPrintTypeToString(getFunctionType(found))!!.toKString()}"
|
||||
"found: ${LLVMPrintTypeToString(getGlobalFunctionType(found))!!.toKString()}"
|
||||
}
|
||||
require(LLVMGetLinkage(found) == llvmFunctionProto.linkage)
|
||||
return LlvmCallable(found, llvmFunctionProto.signature)
|
||||
val functionType = getGlobalFunctionType(found)
|
||||
return LlvmCallable(functionType, found, llvmFunctionProto.signature)
|
||||
} else {
|
||||
return llvmFunctionProto.createLlvmFunction(context, module)
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,6 +1,5 @@
|
||||
package org.jetbrains.kotlin.backend.konan.llvm
|
||||
|
||||
import kotlinx.cinterop.cValuesOf
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.KonanFqNames
|
||||
import org.jetbrains.kotlin.backend.konan.MemoryModel
|
||||
@@ -447,7 +446,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
llvm.kNullInt8Ptr
|
||||
|
||||
private fun FunctionGenerationContext.emitNativePtrPlusLong(args: List<LLVMValueRef>): LLVMValueRef =
|
||||
gep(args[0], args[1])
|
||||
gep(llvm.int8Type, args[0], args[1])
|
||||
|
||||
private fun FunctionGenerationContext.emitNativePtrToLong(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val intPtrValue = ptrToInt(args.single(), codegen.intPtrType)
|
||||
@@ -508,7 +507,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum
|
||||
val bitsWithPaddingType = LLVMIntTypeInContext(llvm.llvmContext, bitsWithPaddingNum)!!
|
||||
|
||||
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, llvm.int64(offset / 8)))
|
||||
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(llvm.int8Type, ptr, llvm.int64(offset / 8)))
|
||||
val bitsWithPadding = load(bitsWithPaddingType, bitsWithPaddingPtr).setUnaligned()
|
||||
|
||||
val bits = shr(
|
||||
@@ -551,7 +550,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
|
||||
val preservedBitsMask = LLVMConstNot(discardBitsMask)!!
|
||||
|
||||
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, llvm.int64(offset / 8)))
|
||||
val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(llvm.int8Type, ptr, llvm.int64(offset / 8)))
|
||||
|
||||
val bits = trunc(value, bitsType)
|
||||
|
||||
@@ -581,8 +580,8 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
|
||||
val structType = llvm.structType(llvm.int8PtrType, llvm.int8PtrType)
|
||||
val ptr = alloca(structType)
|
||||
store(receiver, LLVMBuildGEP(builder, ptr, cValuesOf(llvm.kImmInt32Zero, llvm.kImmInt32Zero), 2, "")!!)
|
||||
store(superClass, LLVMBuildGEP(builder, ptr, cValuesOf(llvm.kImmInt32Zero, llvm.kImmInt32One), 2, "")!!)
|
||||
store(receiver, structGep(structType, ptr, 0, ""))
|
||||
store(superClass, structGep(structType, ptr, 1, ""))
|
||||
return bitcast(llvm.int8PtrType, ptr)
|
||||
}
|
||||
|
||||
|
||||
+9
-6
@@ -11,8 +11,12 @@ import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
|
||||
private fun ConstPointer.add(index: LLVMValueRef): ConstPointer {
|
||||
return constPointer(LLVMConstGEP(llvm, cValuesOf(index), 1)!!)
|
||||
private fun ConstPointer.addBits(llvm: CodegenLlvmHelpers, type: LLVMTypeRef, bits: Int): ConstPointer {
|
||||
val rawPtr = LLVMConstBitCast(this.llvm, llvm.int8PtrType)
|
||||
// Only pointer arithmetic via GEP works on constant pointers in LLVM.
|
||||
val withBits = LLVMConstGEP2(llvm.int8Type, rawPtr, cValuesOf(llvm.int32(bits)), 1)!!
|
||||
val withType = LLVMConstBitCast(withBits, type)!!
|
||||
return constPointer(withType)
|
||||
}
|
||||
|
||||
internal class KotlinStaticData(override val generationState: NativeGenerationState, override val llvm: CodegenLlvmHelpers, module: LLVMModuleRef) : ContextUtils, StaticData(module, llvm) {
|
||||
@@ -20,8 +24,7 @@ internal class KotlinStaticData(override val generationState: NativeGenerationSt
|
||||
|
||||
// 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(llvm.int8PtrType).add(llvm.int32(1)).bitcast(kTypeInfoPtr)
|
||||
return typeInfo.addBits(llvm, kTypeInfoPtr, 1)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +61,7 @@ internal class KotlinStaticData(override val generationState: NativeGenerationSt
|
||||
|
||||
val global = this.createGlobal(compositeType, "")
|
||||
|
||||
val objHeaderPtr = global.pointer.getElementPtr(llvm, 0)
|
||||
val objHeaderPtr = global.pointer.getElementPtr(llvm, compositeType, 0)
|
||||
val arrayHeader = arrayHeader(typeInfo, elements.size)
|
||||
|
||||
global.setInitializer(Struct(compositeType, arrayHeader, arrayBody))
|
||||
@@ -73,7 +76,7 @@ internal class KotlinStaticData(override val generationState: NativeGenerationSt
|
||||
global.setUnnamedAddr(true)
|
||||
global.setConstant(true)
|
||||
|
||||
val objHeaderPtr = global.pointer.getElementPtr(llvm, 0)
|
||||
val objHeaderPtr = global.pointer.bitcast(llvm.runtime.objHeaderPtrType)
|
||||
|
||||
return createRef(objHeaderPtr)
|
||||
}
|
||||
|
||||
+6
-10
@@ -14,7 +14,7 @@ import llvm.*
|
||||
* @todo This class mixes "something that can be called" and function abstractions.
|
||||
* Some of it's methods make sense only for functions. Probably, LlvmFunction sub-class should be extracted.
|
||||
*/
|
||||
class LlvmCallable(private val llvmValue: LLVMValueRef, private val attributeProvider: LlvmFunctionAttributeProvider) {
|
||||
class LlvmCallable(val functionType: LLVMTypeRef, private val llvmValue: LLVMValueRef, private val attributeProvider: LlvmFunctionAttributeProvider) {
|
||||
val returnType: LLVMTypeRef by lazy {
|
||||
LLVMGetReturnType(functionType)!!
|
||||
}
|
||||
@@ -23,12 +23,8 @@ class LlvmCallable(private val llvmValue: LLVMValueRef, private val attributePro
|
||||
llvmValue.name
|
||||
}
|
||||
|
||||
val functionType: LLVMTypeRef by lazy {
|
||||
getFunctionType(llvmValue)
|
||||
}
|
||||
|
||||
val numParams by lazy {
|
||||
LLVMCountParams(llvmValue)
|
||||
LLVMCountParamTypes(functionType)
|
||||
}
|
||||
|
||||
val pgoFunctionNameVar by lazy {
|
||||
@@ -40,12 +36,12 @@ class LlvmCallable(private val llvmValue: LLVMValueRef, private val attributePro
|
||||
}
|
||||
|
||||
fun buildCall(builder: LLVMBuilderRef, args: List<LLVMValueRef>, name: String = "") =
|
||||
LLVMBuildCall(builder, llvmValue, args.toCValues(), args.size, name)!!.also {
|
||||
attributeProvider.addCallSiteAttributes(it)
|
||||
}
|
||||
LLVMBuildCall2(builder, functionType, llvmValue, args.toCValues(), args.size, name)!!.also {
|
||||
attributeProvider.addCallSiteAttributes(it)
|
||||
}
|
||||
|
||||
fun buildInvoke(builder: LLVMBuilderRef, args: List<LLVMValueRef>, success: LLVMBasicBlockRef, catch: LLVMBasicBlockRef, name: String = "") =
|
||||
LLVMBuildInvoke(builder, llvmValue, args.toCValues(), args.size, success, catch, name)!!.also {
|
||||
LLVMBuildInvoke2(builder, functionType, llvmValue, args.toCValues(), args.size, success, catch, name)!!.also {
|
||||
attributeProvider.addCallSiteAttributes(it)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -305,7 +305,7 @@ private class DeclarationsGeneratorVisitor(override val generationState: NativeG
|
||||
typeInfoGlobal.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
}
|
||||
|
||||
typeInfoPtr = typeInfoGlobal.pointer.getElementPtr(llvm, 0)
|
||||
typeInfoPtr = typeInfoGlobal.pointer.getElementPtr(llvm, typeInfoWithVtableType, 0)
|
||||
|
||||
} else {
|
||||
typeInfoGlobal = staticData.createGlobal(runtime.typeInfoType,
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ internal class LlvmFunctionProto(
|
||||
addTargetCpuAndFeaturesAttributes(context, function)
|
||||
signature.addFunctionAttributes(function)
|
||||
LLVMSetLinkage(function, linkage)
|
||||
return LlvmCallable(function, signature)
|
||||
return LlvmCallable(signature.llvmFunctionType, function, signature)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-10
@@ -23,7 +23,8 @@ internal val ConstValue.llvmType: LLVMTypeRef
|
||||
get() = this.llvm.type
|
||||
|
||||
internal interface ConstPointer : ConstValue {
|
||||
fun getElementPtr(llvm: CodegenLlvmHelpers, index: Int): ConstPointer = ConstGetElementPtr(llvm, this, index)
|
||||
fun getElementPtr(llvm: CodegenLlvmHelpers, pointeeType: LLVMTypeRef, index: Int): ConstPointer =
|
||||
ConstGetElementPtr(llvm, pointeeType, this, index)
|
||||
}
|
||||
|
||||
internal fun constPointer(value: LLVMValueRef) = object : ConstPointer {
|
||||
@@ -34,8 +35,8 @@ internal fun constPointer(value: LLVMValueRef) = object : ConstPointer {
|
||||
override val llvm = value
|
||||
}
|
||||
|
||||
private class ConstGetElementPtr(llvm: CodegenLlvmHelpers, pointer: ConstPointer, index: Int) : ConstPointer {
|
||||
override val llvm = LLVMConstInBoundsGEP(pointer.llvm, cValuesOf(llvm.int32(0), llvm.int32(index)), 2)!!
|
||||
private class ConstGetElementPtr(llvm: CodegenLlvmHelpers, pointeeType: LLVMTypeRef, pointer: ConstPointer, index: Int) : ConstPointer {
|
||||
override val llvm = LLVMConstInBoundsGEP2(pointeeType, pointer.llvm, cValuesOf(llvm.int32(0), llvm.int32(index)), 2)!!
|
||||
// TODO: squash multiple GEPs
|
||||
}
|
||||
|
||||
@@ -116,11 +117,6 @@ internal val RuntimeAware.kNothingFakeValue: LLVMValueRef
|
||||
|
||||
internal fun pointerType(pointeeType: LLVMTypeRef) = LLVMPointerType(pointeeType, 0)!!
|
||||
|
||||
internal fun ContextUtils.numParameters(functionType: LLVMTypeRef) : Int {
|
||||
// Note that type is usually function pointer, so we have to dereference it.
|
||||
return LLVMCountParamTypes(LLVMGetElementType(functionType))
|
||||
}
|
||||
|
||||
fun extractConstUnsignedInt(value: LLVMValueRef): Long {
|
||||
assert(LLVMIsConstant(value) != 0)
|
||||
return LLVMConstIntGetZExtValue(value)
|
||||
@@ -150,12 +146,12 @@ internal fun LLVMValueRef.getAsCString() : String {
|
||||
}
|
||||
|
||||
|
||||
internal fun getFunctionType(ptrToFunction: LLVMValueRef): LLVMTypeRef {
|
||||
internal fun getGlobalFunctionType(ptrToFunction: LLVMValueRef): LLVMTypeRef {
|
||||
return getGlobalType(ptrToFunction)
|
||||
}
|
||||
|
||||
internal fun getGlobalType(ptrToGlobal: LLVMValueRef): LLVMTypeRef {
|
||||
return LLVMGetElementType(ptrToGlobal.type)!!
|
||||
return LLVMGlobalGetValueType(ptrToGlobal)!!
|
||||
}
|
||||
|
||||
internal fun ContextUtils.addGlobal(name: String, type: LLVMTypeRef, isExported: Boolean): LLVMValueRef {
|
||||
|
||||
+5
-4
@@ -404,7 +404,7 @@ internal class RTTIGenerator(
|
||||
private val debugOperations: ConstValue by lazy {
|
||||
if (debugRuntimeOrNull != null) {
|
||||
val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!!
|
||||
val local = LLVMAddGlobal(llvm.module, LLVMGetElementType(LLVMTypeOf(external)),"Konan_debugOperationsList")!!
|
||||
val local = LLVMAddGlobal(llvm.module, LLVMGlobalGetValueType(external),"Konan_debugOperationsList")!!
|
||||
constPointer(LLVMConstBitCast(local, llvm.int8PtrPtrType)!!)
|
||||
} else {
|
||||
Zero(llvm.int8PtrPtrType)
|
||||
@@ -414,7 +414,7 @@ internal class RTTIGenerator(
|
||||
val debugOperationsSize: ConstValue by lazy {
|
||||
if (debugRuntimeOrNull != null) {
|
||||
val external = LLVMGetNamedGlobal(debugRuntimeOrNull, "Konan_debugOperationsList")!!
|
||||
llvm.constInt32(LLVMGetArrayLength(LLVMGetElementType(LLVMTypeOf(external))))
|
||||
llvm.constInt32(LLVMGetArrayLength(LLVMGlobalGetValueType(external)))
|
||||
} else
|
||||
llvm.constInt32(0)
|
||||
}
|
||||
@@ -531,7 +531,7 @@ internal class RTTIGenerator(
|
||||
val vtable = vtable(superClass)
|
||||
val typeInfoWithVtableType = llvm.structType(runtime.typeInfoType, vtable.llvmType)
|
||||
val typeInfoWithVtableGlobal = staticData.createGlobal(typeInfoWithVtableType, "", isExported = false)
|
||||
val result = typeInfoWithVtableGlobal.pointer.getElementPtr(llvm, 0)
|
||||
val result = typeInfoWithVtableGlobal.pointer.getElementPtr(llvm, typeInfoWithVtableType, 0)
|
||||
val typeHierarchyInfo = if (!context.ghaEnabled())
|
||||
ClassGlobalHierarchyInfo.DUMMY
|
||||
else
|
||||
@@ -546,10 +546,11 @@ internal class RTTIGenerator(
|
||||
} else {
|
||||
val vtableEntries = layoutBuilder.interfaceVTableEntries.map { methodImpls[it]!!.bitcast(llvm.int8PtrType) }
|
||||
val interfaceVTable = staticData.placeGlobalArray("", llvm.int8PtrType, vtableEntries)
|
||||
val interfaceVTableType = LLVMArrayType(llvm.int8PtrType, vtableEntries.size)!!
|
||||
InterfaceTableRecord(
|
||||
llvm.constInt32(layoutBuilder.classId),
|
||||
llvm.constInt32(layoutBuilder.interfaceVTableEntries.size),
|
||||
interfaceVTable.pointer.getElementPtr(llvm, 0)
|
||||
interfaceVTable.pointer.getElementPtr(llvm, interfaceVTableType, 0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ internal open class StaticData(val module: LLVMModuleRef, private val llvm: Code
|
||||
if (elements.isNotEmpty() || isExported) {
|
||||
val global = placeGlobalArray(name, elemType, elements, isExported)
|
||||
global.setConstant(true)
|
||||
return global.pointer.getElementPtr(llvm, 0)
|
||||
return global.pointer.getElementPtr(llvm, LLVMArrayType(elemType, elements.size)!!, 0)
|
||||
} else {
|
||||
return NullPointer(elemType)
|
||||
}
|
||||
|
||||
+2
-5
@@ -4,11 +4,7 @@
|
||||
*/
|
||||
package org.jetbrains.kotlin.backend.konan.llvm.coverage
|
||||
|
||||
import llvm.LLVMConstBitCast
|
||||
import llvm.LLVMCreatePGOFunctionNameVar
|
||||
import llvm.LLVMInstrProfIncrement
|
||||
import llvm.LLVMValueRef
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.NativeGenerationState
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -31,6 +27,7 @@ internal class LLVMCoverageInstrumentation(
|
||||
private val instrProfIncrement by lazy {
|
||||
val incrementFun = LLVMInstrProfIncrement(llvm.module)!!
|
||||
LlvmCallable(
|
||||
getGlobalFunctionType(incrementFun),
|
||||
incrementFun,
|
||||
LlvmFunctionAttributeProvider.copyFromExternal(incrementFun)
|
||||
)
|
||||
|
||||
+10
-11
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.backend.konan.llvm.objc
|
||||
|
||||
import kotlinx.cinterop.signExtend
|
||||
import kotlinx.cinterop.toCValues
|
||||
import llvm.LLVMGetElementType
|
||||
import llvm.LLVMGetInlineAsm
|
||||
import llvm.LLVMInlineAsmDialect
|
||||
import llvm.LLVMValueRef
|
||||
import llvm.*
|
||||
import org.jetbrains.kotlin.backend.konan.getARCRetainAutoreleasedReturnValueMarker
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||
|
||||
@@ -79,16 +76,18 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
}
|
||||
|
||||
// TODO: this doesn't support stret.
|
||||
fun msgSender(functionType: LlvmFunctionSignature): LlvmCallable =
|
||||
LlvmCallable(
|
||||
objcMsgSend.bitcast(pointerType(functionType.llvmFunctionType)).llvm,
|
||||
functionType
|
||||
)
|
||||
fun msgSender(functionType: LlvmFunctionSignature): LlvmCallable {
|
||||
val llvmType = functionType.llvmFunctionType
|
||||
return LlvmCallable(
|
||||
llvmType,
|
||||
objcMsgSend.bitcast(pointerType(llvmType)).llvm,
|
||||
functionType)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun FunctionGenerationContext.genObjCSelector(selector: String): LLVMValueRef {
|
||||
val selectorRef = codegen.objCDataGenerator!!.genSelectorRef(selector)
|
||||
val selectorRef = codegen.objCDataGenerator!!.genSelectorRef(selector).llvm
|
||||
// TODO: clang emits it with `invariant.load` metadata.
|
||||
// TODO: Propagate the type here without using the typed pointer.
|
||||
return load(LLVMGetElementType(selectorRef.llvmType)!!, selectorRef.llvm)
|
||||
return load(LLVMGlobalGetValueType(selectorRef)!!, selectorRef)
|
||||
}
|
||||
+1
-1
@@ -254,7 +254,7 @@ internal class ObjCDataGenerator(val codegen: CodeGenerator) {
|
||||
fun get(value: String) = literals.getOrPut(value) {
|
||||
val globalPointer = generator.generate(llvm.module, llvm, value)
|
||||
llvm.compilerUsedGlobals += globalPointer.llvm
|
||||
globalPointer.getElementPtr(llvm, 0)
|
||||
globalPointer.bitcast(llvm.int8PtrType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ private fun patchLiteral(
|
||||
) {
|
||||
val module = LLVMGetGlobalParent(global)!!
|
||||
|
||||
val newFirstCharPtr = generator.generate(module, llvm, newValue).getElementPtr(llvm, 0).llvm
|
||||
val newFirstCharPtr = generator.generate(module, llvm, newValue).bitcast(llvm.int8PtrType).llvm
|
||||
|
||||
generateSequence(LLVMGetFirstUse(global), { LLVMGetNextUse(it) }).forEach { use ->
|
||||
val firstCharPtr = LLVMGetUser(use)!!.also {
|
||||
|
||||
+13
-12
@@ -41,7 +41,7 @@ internal fun ObjCExportCodeGeneratorBase.generateBlockToKotlinFunctionConverter(
|
||||
val thisRef = param(0)
|
||||
val associatedObjectHolder = if (useSeparateHolder) {
|
||||
val bodyPtr = bitcast(pointerType(bodyType), thisRef)
|
||||
loadSlot(codegen.kObjHeaderPtr, structGep(bodyPtr, 1), isVar = false)
|
||||
loadSlot(codegen.kObjHeaderPtr, structGep(bodyType, bodyPtr, 1), isVar = false)
|
||||
} else {
|
||||
thisRef
|
||||
}
|
||||
@@ -109,7 +109,7 @@ internal fun ObjCExportCodeGeneratorBase.generateBlockToKotlinFunctionConverter(
|
||||
retainedBlockPtr,
|
||||
Lifetime.ARGUMENT
|
||||
)
|
||||
storeHeapRef(holder, structGep(bodyPtr, 1))
|
||||
storeHeapRef(holder, structGep(bodyType, bodyPtr, 1))
|
||||
result
|
||||
} else {
|
||||
allocInstanceWithAssociatedObject(typeInfo, retainedBlockPtr, Lifetime.RETURN_VALUE)
|
||||
@@ -123,11 +123,12 @@ private fun FunctionGenerationContext.loadBlockInvoke(
|
||||
blockPtr: LLVMValueRef,
|
||||
bridge: BlockPointerBridge
|
||||
): LlvmCallable {
|
||||
val invokePtr = structGep(bitcast(pointerType(codegen.runtime.blockLiteralType), blockPtr), 3)
|
||||
val invokePtr = structGep(codegen.runtime.blockLiteralType, bitcast(pointerType(codegen.runtime.blockLiteralType), blockPtr), 3)
|
||||
val signature = bridge.blockType.toBlockInvokeLlvmType(llvm)
|
||||
val functionPointerType = pointerType(signature.llvmFunctionType)
|
||||
val functionType = signature.llvmFunctionType
|
||||
val functionPointerType = pointerType(functionType)
|
||||
val functionPointer = load(functionPointerType, bitcast(pointerType(functionPointerType), invokePtr))
|
||||
return LlvmCallable(functionPointer, signature)
|
||||
return LlvmCallable(functionType, functionPointer, signature)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.allocInstanceWithAssociatedObject(
|
||||
@@ -180,7 +181,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
switchToRunnable = true
|
||||
) {
|
||||
val blockPtr = bitcast(pointerType(blockLiteralType), param(0))
|
||||
val refHolder = structGep(blockPtr, 1)
|
||||
val refHolder = structGep(blockLiteralType, blockPtr, 1)
|
||||
call(llvm.kRefSharedHolderDispose, listOf(refHolder))
|
||||
|
||||
ret(null)
|
||||
@@ -200,10 +201,10 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
copyProto,
|
||||
) {
|
||||
val dstBlockPtr = bitcast(pointerType(blockLiteralType), param(0))
|
||||
val dstRefHolder = structGep(dstBlockPtr, 1)
|
||||
val dstRefHolder = structGep(blockLiteralType, dstBlockPtr, 1)
|
||||
|
||||
val srcBlockPtr = bitcast(pointerType(blockLiteralType), param(1))
|
||||
val srcRefHolder = structGep(srcBlockPtr, 1)
|
||||
val srcRefHolder = structGep(blockLiteralType, srcBlockPtr, 1)
|
||||
|
||||
// Note: in current implementation copy helper is invoked only for stack-allocated blocks from the same thread,
|
||||
// so it is technically not necessary to check owner.
|
||||
@@ -267,7 +268,7 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
val blockPtr = bitcast(pointerType(blockLiteralType), param(0))
|
||||
val kotlinObject = call(
|
||||
llvm.kRefSharedHolderRef,
|
||||
listOf(structGep(blockPtr, 1)),
|
||||
listOf(structGep(blockLiteralType, blockPtr, 1)),
|
||||
exceptionHandler = ExceptionHandler.Caller,
|
||||
verbatim = true
|
||||
)
|
||||
@@ -335,13 +336,13 @@ internal class BlockGenerator(private val codegen: CodeGenerator) {
|
||||
val descriptor = blockDescriptor.llvmGlobal
|
||||
|
||||
val blockOnStack = alloca(blockLiteralType)
|
||||
val blockOnStackBase = structGep(blockOnStack, 0)
|
||||
val refHolder = structGep(blockOnStack, 1)
|
||||
val blockOnStackBase = structGep(blockLiteralType, blockOnStack, 0)
|
||||
val refHolder = structGep(blockLiteralType, blockOnStack, 1)
|
||||
|
||||
listOf(bitcast(llvm.int8PtrType, isa), flags, reserved, invoke, descriptor).forEachIndexed { index, value ->
|
||||
// Although value is actually on the stack, it's not in normal slot area, so we cannot handle it
|
||||
// as if it was on the stack.
|
||||
store(value, structGep(blockOnStackBase, index))
|
||||
store(value, structGep(codegen.runtime.blockLiteralType, blockOnStackBase, index))
|
||||
}
|
||||
|
||||
call(llvm.kRefSharedHolderInitLocal, listOf(refHolder, kotlinRef))
|
||||
|
||||
+10
-7
@@ -177,13 +177,13 @@ internal fun ObjCExportFunctionGenerationContext.callAndMaybeRetainAutoreleased(
|
||||
forbidRuntime = true // Don't emit safe points, frame management etc.
|
||||
|
||||
val actualArgs = signature.parameterTypes.indices.map { param(it) }
|
||||
val actualCallable = if (functionIsPassedAsLastParameter) LlvmCallable(param(signature.parameterTypes.size), signature) else function
|
||||
val actualCallable = if (functionIsPassedAsLastParameter) LlvmCallable(signature.llvmFunctionType, param(signature.parameterTypes.size), signature) else function
|
||||
|
||||
// Use LLVMBuildCall instead of call, because the latter enforces using exception handler, which is exactly what we have to avoid.
|
||||
val result = actualCallable.buildCall(builder, actualArgs).let { callResult ->
|
||||
// Simplified version of emitAutoreleasedReturnValueMarker in Clang:
|
||||
objCExportCodegen.objcRetainAutoreleasedReturnValueMarker?.let {
|
||||
LLVMBuildCall(arg0 = builder, Fn = it, Args = null, NumArgs = 0, Name = "")
|
||||
LLVMBuildCall2(arg0 = builder, functionType(llvm.voidType), Fn = it, Args = null, NumArgs = 0, Name = "")
|
||||
}
|
||||
|
||||
call(objCExportCodegen.objcRetainAutoreleasedReturnValue, listOf(callResult)).also {
|
||||
@@ -217,8 +217,9 @@ internal open class ObjCExportCodeGeneratorBase(codegen: CodeGenerator) : ObjCCo
|
||||
resultLifetime: Lifetime = Lifetime.IRRELEVANT
|
||||
): LLVMValueRef {
|
||||
val llvmDeclarations = LlvmCallable(
|
||||
llvmFunction,
|
||||
getGlobalFunctionType(llvmFunction),
|
||||
// llvmFunction could be a function pointer here, and we can't infer attributes from it.
|
||||
llvmFunction,
|
||||
LlvmFunctionAttributeProvider.makeEmpty()
|
||||
)
|
||||
return callFromBridge(llvmDeclarations, args, resultLifetime)
|
||||
@@ -831,11 +832,12 @@ private fun ObjCExportBlockCodeGenerator.emitBlockToKotlinFunctionConverters() {
|
||||
} ?: NullPointer(objCToKotlinFunctionType)
|
||||
}
|
||||
|
||||
val type = pointerType(objCToKotlinFunctionType)
|
||||
val ptr = staticData.placeGlobalArray(
|
||||
"",
|
||||
pointerType(objCToKotlinFunctionType),
|
||||
type,
|
||||
converters
|
||||
).pointer.getElementPtr(llvm, 0)
|
||||
).pointer.getElementPtr(llvm, LLVMArrayType(type, converters.size)!!, 0)
|
||||
|
||||
// Note: defining globals declared in runtime.
|
||||
staticData.placeGlobal("Kotlin_ObjCExport_blockToFunctionConverters", ptr, isExported = true)
|
||||
@@ -1628,9 +1630,10 @@ private fun ObjCExportCodeGenerator.createTypeAdapter(
|
||||
}
|
||||
|
||||
val vtable = if (!irClass.isInterface && !irClass.typeInfoHasVtableAttached) {
|
||||
staticData.placeGlobal("", rttiGenerator.vtable(irClass)).also {
|
||||
val table = rttiGenerator.vtable(irClass)
|
||||
staticData.placeGlobal("", table).also {
|
||||
it.setConstant(true)
|
||||
}.pointer.getElementPtr(llvm, 0)
|
||||
}.pointer.getElementPtr(llvm, LLVMArrayType(llvm.int8PtrType, table.elements.size)!!, 0)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ excludedFunctions = LLVMInitializeAllAsmParsers LLVMInitializeAllAsmPrinters LLV
|
||||
LLVMX86FP80Type LLVMFP128Type LLVMPPCFP128Type LLVMX86MMXType LLVMStructType LLVMVoidType LLVMLabelType \
|
||||
LLVMMDString LLVMMDNode LLVMConstString LLVMConstStruct LLVMAppendBasicBlock LLVMInsertBasicBlock LLVMCreateBuilder \
|
||||
LLVMParseBitcode LLVMParseBitcode2 LLVMGetBitcodeModule LLVMGetBitcodeModule2 LLVMGetGlobalContext LLVMModuleCreateWithName \
|
||||
LLVMBuildLoad
|
||||
LLVMBuildLoad LLVMBuildGEP LLVMBuildStructGEP LLVMConstGEP LLVMConstInBoundsGEP LLVMAddAlias LLVMBuildInvoke LLVMBuildCall \
|
||||
LLVMGetElementType
|
||||
|
||||
strictEnums = LLVMIntPredicate LLVMOpcode LLVMDLLStorageClass LLVMCallConv LLVMThreadLocalMode LLVMAtomicOrdering
|
||||
|
||||
@@ -34,4 +34,9 @@ LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
|
||||
NumIndices);
|
||||
Constant *Val = unwrap<Constant>(ConstantVal);
|
||||
return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned LLVMGetProgramAddressSpace(LLVMModuleRef moduleRef) {
|
||||
auto module = unwrap(moduleRef);
|
||||
return module ? module->getDataLayout().getProgramAddressSpace() : 0;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ LLVMValueRef LLVMAddAlias2(LLVMModuleRef M, LLVMTypeRef ValueTy,
|
||||
unsigned AddrSpace, LLVMValueRef Aliasee,
|
||||
const char *Name);
|
||||
|
||||
unsigned LLVMGetProgramAddressSpace(LLVMModuleRef moduleRef);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
Reference in New Issue
Block a user