diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 12f9d7dd1be..22c7cb1d930 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -208,8 +208,9 @@ private inline fun generateFunctionBody( internal object VirtualTablesLookup { private fun FunctionGenerationContext.getInterfaceTableRecord(typeInfo: LLVMValueRef, interfaceId: Int): LLVMValueRef { - val interfaceTableSize = load(structGep(typeInfo, 9 /* interfaceTableSize_ */)) - val interfaceTable = load(structGep(typeInfo, 10 /* interfaceTable_ */)) + val interfaceTableRecordPtrType = pointerType(runtime.interfaceTableRecordType) + val interfaceTableSize = load(llvm.int32Type, structGep(typeInfo, 9 /* interfaceTableSize_ */)) + val interfaceTable = load(interfaceTableRecordPtrType, structGep(typeInfo, 10 /* interfaceTable_ */)) fun fastPath(): LLVMValueRef { // The fastest optimistic version. @@ -231,7 +232,7 @@ internal object VirtualTablesLookup { val takeResBB = basicBlock("take_res", startLocationInfo) condBr(icmpGe(interfaceTableSize, llvm.kImmInt32Zero), fastPathBB, slowPathBB) positionAtEnd(takeResBB) - val resultPhi = phi(pointerType(runtime.interfaceTableRecordType)) + val resultPhi = phi(interfaceTableRecordPtrType) appendingTo(fastPathBB) { val fastValue = fastPath() br(takeResBB) @@ -259,7 +260,7 @@ internal object VirtualTablesLookup { // Essentially: typeInfo.itable[place(interfaceId)].id == interfaceId val interfaceId = dstHierarchyInfo.interfaceId val interfaceTableRecord = getInterfaceTableRecord(objTypeInfo, interfaceId) - icmpEq(load(structGep(interfaceTableRecord, 0 /* id */)), llvm.int32(interfaceId)) + icmpEq(load(llvm.int32Type, structGep(interfaceTableRecord, 0 /* id */)), llvm.int32(interfaceId)) } } @@ -277,23 +278,26 @@ internal object VirtualTablesLookup { val canCallViaVtable = !owner.isInterface val layoutBuilder = generationState.context.getLayoutBuilder(owner) + val functionPtrType = pointerType(codegen.getLlvmFunctionType(irFunction)) + val functionPtrPtrType = pointerType(functionPtrType) val llvmMethod = when { canCallViaVtable -> { val index = layoutBuilder.vtableIndex(irFunction) val vtablePlace = gep(typeInfoPtr, llvm.int32(1)) // typeInfoPtr + 1 val vtable = bitcast(llvm.int8PtrPtrType, vtablePlace) val slot = gep(vtable, llvm.int32(index)) - load(slot) + load(functionPtrType, bitcast(functionPtrPtrType, slot)) } else -> { // Essentially: typeInfo.itable[place(interfaceId)].vtable[method] val itablePlace = layoutBuilder.itablePlace(irFunction) val interfaceTableRecord = getInterfaceTableRecord(typeInfoPtr, itablePlace.interfaceId) - load(gep(load(structGep(interfaceTableRecord, 2 /* vtable */)), llvm.int32(itablePlace.methodIndex))) + val vtable = load(llvm.int8PtrPtrType, structGep(interfaceTableRecord, 2 /* vtable */)) + val slot = gep(vtable, llvm.int32(itablePlace.methodIndex)) + load(functionPtrType, bitcast(functionPtrPtrType, slot)) } } - val functionPtrType = pointerType(codegen.getLlvmFunctionType(irFunction)) return LlvmCallable( bitcast(functionPtrType, llvmMethod), LlvmFunctionSignature(irFunction, this) @@ -707,10 +711,7 @@ internal abstract class FunctionGenerationContext( fun param(index: Int): LLVMValueRef = function.param(index) - fun load(address: LLVMValueRef, name: String = "", - memoryOrder: LLVMAtomicOrdering? = null, alignment: Int? = null - ): LLVMValueRef { - val value = LLVMBuildLoad(builder, address, name)!! + private fun applyMemoryOrderAndAlignment(value: LLVMValueRef, memoryOrder: LLVMAtomicOrdering?, alignment: Int?): LLVMValueRef { memoryOrder?.let { LLVMSetOrdering(value, it) } alignment?.let { LLVMSetAlignment(value, it) } // Use loadSlot() API for that. @@ -718,6 +719,12 @@ internal abstract class FunctionGenerationContext( return value } + fun load(type: LLVMTypeRef, address: LLVMValueRef, name: String = "", + memoryOrder: LLVMAtomicOrdering? = null, alignment: Int? = null + ): LLVMValueRef { + return applyMemoryOrderAndAlignment(LLVMBuildLoad2(builder, type, address, name)!!, memoryOrder, alignment) + } + fun loadSlot(address: LLVMValueRef, isVar: Boolean, resultSlot: LLVMValueRef? = null, name: String = "", memoryOrder: LLVMAtomicOrdering? = null, alignment: Int? = null): LLVMValueRef { val value = LLVMBuildLoad(builder, address, name)!! @@ -1274,13 +1281,14 @@ internal abstract class FunctionGenerationContext( LLVMAtomicOrdering.LLVMAtomicOrderingAcquire } - val typeInfoOrMetaWithFlags = load(typeInfoOrMetaPtr, memoryOrder = memoryOrder) + // TODO: Get rid of the bitcast here by supplying the type in the GEP above. + val typeInfoOrMetaPtrRaw = bitcast(pointerType(codegen.intPtrType), typeInfoOrMetaPtr) + val typeInfoOrMetaWithFlags = load(codegen.intPtrType, typeInfoOrMetaPtrRaw, memoryOrder = memoryOrder) // Clear two lower bits. - val typeInfoOrMetaWithFlagsRaw = ptrToInt(typeInfoOrMetaWithFlags, codegen.intPtrType) - val typeInfoOrMetaRaw = and(typeInfoOrMetaWithFlagsRaw, codegen.immTypeInfoMask) + val typeInfoOrMetaRaw = and(typeInfoOrMetaWithFlags, codegen.immTypeInfoMask) val typeInfoOrMeta = intToPtr(typeInfoOrMetaRaw, kTypeInfoPtr) val typeInfoPtrPtr = structGep(typeInfoOrMeta, 0 /* typeInfo */) - return load(typeInfoPtrPtr, memoryOrder = LLVMAtomicOrdering.LLVMAtomicOrderingMonotonic) + return load(codegen.kTypeInfoPtr, typeInfoPtrPtr, memoryOrder = LLVMAtomicOrdering.LLVMAtomicOrderingMonotonic) } @Suppress("UNUSED_PARAMETER") @@ -1330,9 +1338,9 @@ internal abstract class FunctionGenerationContext( } val classInfo = codegen.kotlinObjCClassInfo(irClass) - val classPointerGlobal = load(structGep(classInfo, KotlinObjCClassInfoGenerator.createdClassFieldIndex)) + val classPointerGlobal = load(llvm.int8PtrPtrType, structGep(classInfo, KotlinObjCClassInfoGenerator.createdClassFieldIndex)) - val storedClass = this.load(classPointerGlobal) + val storedClass = this.load(llvm.int8PtrType, classPointerGlobal) val storedClassIsNotNull = this.icmpNe(storedClass, llvm.kNullInt8Ptr) @@ -1346,7 +1354,7 @@ internal abstract class FunctionGenerationContext( } } - private fun getObjCClass(binaryName: String) = load(codegen.objCDataGenerator!!.genClassRef(binaryName).llvm) + private fun getObjCClass(binaryName: String) = load(llvm.int8PtrType, codegen.objCDataGenerator!!.genClassRef(binaryName).llvm) fun getObjCClassFromNativeRuntime(binaryName: String): LLVMValueRef { generationState.dependenciesTracker.addNativeRuntime() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index 8185471ecc9..ec1a7142126 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -480,7 +480,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv val pointerType = pointerType(callSite.llvmReturnType) val rawPointer = args.last() val pointer = bitcast(pointerType, rawPointer) - return load(pointer) + return load(callSite.llvmReturnType, pointer) } private fun FunctionGenerationContext.emitWritePrimitive(callSite: IrCall, args: List): LLVMValueRef { @@ -509,7 +509,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv val bitsWithPaddingType = LLVMIntTypeInContext(llvm.llvmContext, bitsWithPaddingNum)!! val bitsWithPaddingPtr = bitcast(pointerType(bitsWithPaddingType), gep(ptr, llvm.int64(offset / 8))) - val bitsWithPadding = load(bitsWithPaddingPtr).setUnaligned() + val bitsWithPadding = load(bitsWithPaddingType, bitsWithPaddingPtr).setUnaligned() val bits = shr( shl(bitsWithPadding, suffixBitsNum), @@ -558,7 +558,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv val bitsToStore = if (prefixBitsNum == 0 && suffixBitsNum == 0) { bits } else { - val previousValue = load(bitsWithPaddingPtr).setUnaligned() + val previousValue = load(bitsWithPaddingType, bitsWithPaddingPtr).setUnaligned() val preservedBits = and(previousValue, preservedBitsMask) val bitsWithPadding = shl(zext(bits, bitsWithPaddingType), prefixBitsNum) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 54d7a5adc83..f4c8c6a6958 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -1873,11 +1873,9 @@ internal class CodeGeneratorVisitor( //-------------------------------------------------------------------------// private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: IrField): LLVMValueRef { val fieldInfo = generationState.llvmDeclarations.forField(value) - - val typePtr = pointerType(fieldInfo.classBodyType) - - val typedBodyPtr = functionGenerationContext.bitcast(typePtr, thisPtr) - val fieldPtr = LLVMBuildStructGEP(functionGenerationContext.builder, typedBodyPtr, fieldInfo.index, "") + val classBodyType = fieldInfo.classBodyType + val typedBodyPtr = functionGenerationContext.bitcast(pointerType(classBodyType), thisPtr) + val fieldPtr = LLVMBuildStructGEP2(functionGenerationContext.builder, classBodyType, typedBodyPtr, fieldInfo.index, "") return fieldPtr!! } @@ -2507,7 +2505,7 @@ internal class CodeGeneratorVisitor( val bbExit = basicBlock("label_continue", null) moveBlockAfterEntry(bbExit) moveBlockAfterEntry(bbInit) - val state = load(statePtr, memoryOrder = LLVMAtomicOrdering.LLVMAtomicOrderingAcquire) + val state = load(llvm.int32Type, statePtr, memoryOrder = LLVMAtomicOrdering.LLVMAtomicOrderingAcquire) condBr(icmpEq(state, llvm.int32(FILE_INITIALIZED)), bbExit, bbInit) positionAtEnd(bbInit) call(llvm.callInitGlobalPossiblyLock, listOf(statePtr, initializerPtr), @@ -2529,13 +2527,13 @@ internal class CodeGeneratorVisitor( moveBlockAfterEntry(bbExit) moveBlockAfterEntry(bbCheckLocalState) moveBlockAfterEntry(bbInit) - val globalState = load(globalStatePtr) + val globalState = load(llvm.int32Type, globalStatePtr) LLVMSetVolatile(globalState, 1) // Make sure we're not in the middle of global initializer invocation - // thread locals can be initialized only after all shared globals have been initialized. condBr(icmpNe(globalState, llvm.int32(FILE_INITIALIZED)), bbExit, bbCheckLocalState) positionAtEnd(bbCheckLocalState) - condBr(icmpNe(load(localStatePtr), llvm.int32(FILE_INITIALIZED)), bbInit, bbExit) + condBr(icmpNe(load(llvm.int32Type, localStatePtr), llvm.int32(FILE_INITIALIZED)), bbInit, bbExit) positionAtEnd(bbInit) call(llvm.callInitThreadLocal, listOf(globalStatePtr, localStatePtr, initializerPtr), exceptionHandler = currentCodeContext.exceptionHandler) @@ -2553,7 +2551,7 @@ internal class CodeGeneratorVisitor( val bbExit = basicBlock("label_continue", null) moveBlockAfterEntry(bbExit) moveBlockAfterEntry(bbInit) - condBr(icmpEq(load(statePtr), llvm.int32(FILE_INITIALIZED)), bbExit, bbInit) + condBr(icmpEq(load(llvm.int32Type, statePtr), llvm.int32(FILE_INITIALIZED)), bbExit, bbInit) positionAtEnd(bbInit) call(llvm.callInitThreadLocal, listOf(llvm.kNullInt32Ptr, statePtr, initializerPtr), exceptionHandler = currentCodeContext.exceptionHandler) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt index 08d7a3baff3..bd3f3254bec 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objc/ObjCCodeGenerator.kt @@ -7,6 +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 @@ -24,7 +25,7 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) { fun FunctionGenerationContext.genGetLinkedClass(name: String): LLVMValueRef { val classRef = dataGenerator.genClassRef(name) - return load(classRef.llvm) + return load(llvm.int8PtrType, classRef.llvm) } private val objcMsgSend = llvm.externalNativeRuntimeFunction( @@ -88,5 +89,6 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) { internal fun FunctionGenerationContext.genObjCSelector(selector: String): LLVMValueRef { val selectorRef = codegen.objCDataGenerator!!.genSelectorRef(selector) // TODO: clang emits it with `invariant.load` metadata. - return load(selectorRef.llvm) + // TODO: Propagate the type here without using the typed pointer. + return load(LLVMGetElementType(selectorRef.llvmType)!!, selectorRef.llvm) } \ No newline at end of file diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt index 09315354d20..a0b1aa5bbbb 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/BlockPointerSupport.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.backend.konan.llvm.objcexport import llvm.LLVMLinkage -import llvm.LLVMSetLinkage import llvm.LLVMStoreSizeOfType import llvm.LLVMValueRef import org.jetbrains.kotlin.backend.konan.llvm.* @@ -126,8 +125,9 @@ private fun FunctionGenerationContext.loadBlockInvoke( ): LlvmCallable { val invokePtr = structGep(bitcast(pointerType(codegen.runtime.blockLiteralType), blockPtr), 3) val signature = bridge.blockType.toBlockInvokeLlvmType(llvm) - - return LlvmCallable(bitcast(pointerType(signature.llvmFunctionType), load(invokePtr)), signature) + val functionPointerType = pointerType(signature.llvmFunctionType) + val functionPointer = load(functionPointerType, bitcast(pointerType(functionPointerType), invokePtr)) + return LlvmCallable(functionPointer, signature) } private fun FunctionGenerationContext.allocInstanceWithAssociatedObject( diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index de7630ecfb8..76c83804cd2 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.backend.konan.llvm.objcexport -import kotlinx.cinterop.toCValues import kotlinx.cinterop.toKString import llvm.* import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub @@ -1287,7 +1286,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge( assert(baseMethod.symbol !is IrConstructorSymbol) fun rethrow() { - val error = load(errorOutPtr!!) + val error = load(llvm.int8PtrType, errorOutPtr!!) val exception = callFromBridge( llvm.Kotlin_ObjCExport_NSErrorAsException, listOf(error), @@ -1326,7 +1325,7 @@ private fun ObjCExportCodeGenerator.generateKotlinToObjCBridge( is MethodBridge.ReturnValue.WithError.ZeroForError -> { if (returnBridge.successMayBeZero) { - val error = load(errorOutPtr!!) + val error = load(llvm.int8PtrType, errorOutPtr!!) ifThen(icmpNe(error, llvm.kNullInt8Ptr)) { // error is not null, so targetResult should be null => no need for objc_release on it. rethrow()