[K/N] LLVM: Transition to opaque pointers

This commit is contained in:
Troels Bjerre Lund
2023-10-19 11:03:22 +02:00
committed by Space Cloud
parent c1f72de6e5
commit b059754f64
22 changed files with 133 additions and 116 deletions
@@ -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
@@ -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)!!))
@@ -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,
@@ -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)
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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)
}
@@ -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,
@@ -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)
}
}
@@ -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 {
@@ -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)
)
}
}
@@ -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)
}
@@ -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)
)
@@ -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)
}
@@ -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)
}
}
@@ -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 {
@@ -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))
@@ -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
}
+2 -1
View File
@@ -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