diff --git a/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt b/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt index 194cc7435c5..ae03e5b8d38 100644 --- a/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt +++ b/Interop/Indexer/prebuilt/nativeInteropStubs/kotlin/clang/clang.kt @@ -4723,4 +4723,4 @@ private external fun kniBridge335(p0: NativePtr, p1: Int, p2: NativePtr): Unit private external fun kniBridge336(p0: NativePtr): Int private external fun kniBridge337(p0: NativePtr): Int private external fun kniBridge338(p0: NativePtr): Int -private val loadLibrary = System.loadLibrary("clangstubs") +private val loadLibrary = loadKonanLibrary("clangstubs") \ No newline at end of file diff --git a/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmCallbacks.kt b/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmCallbacks.kt index 58b84fd0c48..9dcb2397f3e 100644 --- a/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmCallbacks.kt +++ b/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmCallbacks.kt @@ -371,11 +371,7 @@ private class CEnumType(private val rawValueCType: CType) : CType(ra private typealias FfiClosureImpl = LongConsumer private typealias UserData = FfiClosureImpl -private fun loadCallbacksLibrary() { - System.loadLibrary("callbacks") -} - -private val topLevelInitializer = loadCallbacksLibrary() +private val topLevelInitializer = loadKonanLibrary("callbacks") /** diff --git a/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmUtils.kt b/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmUtils.kt index 6bbdc788180..3502988c57d 100644 --- a/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmUtils.kt +++ b/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmUtils.kt @@ -16,6 +16,10 @@ package kotlinx.cinterop +import java.io.File +import java.nio.file.Files +import java.nio.file.Paths + internal fun decodeFromUtf8(bytes: ByteArray) = String(bytes) internal fun encodeToUtf8(str: String) = str.toByteArray() @@ -82,4 +86,23 @@ inline fun Long.narrow(): R = when (R::class.java) { inline fun Number.invalidNarrowing(): R { throw Error("unable to narrow ${this.javaClass.simpleName} \"${this}\" to ${R::class.java.simpleName}") +} + +fun loadKonanLibrary(name: String) { + try { + System.loadLibrary(name) + } catch (e: UnsatisfiedLinkError) { + val fullLibraryName = System.mapLibraryName(name) + val dir = "${System.getProperty("konan.home")}/konan/nativelib" + try { + System.load("$dir/$fullLibraryName") + } catch (e: UnsatisfiedLinkError) { + val tempDir = createTempDir(directory = File(dir)).absolutePath + Files.createLink(Paths.get(tempDir, fullLibraryName), Paths.get(dir, fullLibraryName)) + // TODO: Does not work on Windows. May be use FILE_FLAG_DELETE_ON_CLOSE? + File(tempDir).deleteOnExit() + File("$tempDir/$fullLibraryName").deleteOnExit() + System.load("$tempDir/$fullLibraryName") + } + } } \ No newline at end of file diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt index c167e1277e7..a544321e005 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt @@ -180,9 +180,8 @@ class StubIrTextEmitter( emitKotlinFileHeader() stubLines.forEach(out) nativeBridges.kotlinLines.forEach(out) - if (context.platform == KotlinPlatform.JVM) { - out("private val loadLibrary = System.loadLibrary(\"${context.libName}\")") - } + if (context.platform == KotlinPlatform.JVM) + out("private val loadLibrary = loadKonanLibrary(\"${context.libName}\")") } } private val printer = object : StubIrVisitor { diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index f12711ec447..a16469d097d 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -233,6 +233,12 @@ class K2Native : CLICompiler() { doMain(K2Native(), args) } } + @JvmStatic fun mainNoExit(args: Array) { + profile("Total compiler main()") { + if (CLITool.doMainNoExit(K2Native(), args) != ExitCode.OK) + throw KonanCompilationException("Compilation finished with errors") + } + } } } @@ -341,4 +347,4 @@ private fun parseLibrariesToCache( } fun main(args: Array) = K2Native.main(args) - +fun mainNoExit(args: Array) = K2Native.mainNoExit(args) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt index dbff0265866..49914c8d2f2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/CAdapterGenerator.kt @@ -233,8 +233,8 @@ private class ExportedElement(val kind: ElementKind, cname = "_konan_function_${owner.nextFunctionIndex()}" // Produce type getter. val getTypeFunction = LLVMAddFunction(context.llvmModule, "${cname}_type", owner.kGetTypeFuncType)!! - val builder = LLVMCreateBuilder()!! - val bb = LLVMAppendBasicBlock(getTypeFunction, "")!! + val builder = LLVMCreateBuilderInContext(llvmContext)!! + val bb = LLVMAppendBasicBlockInContext(llvmContext, getTypeFunction, "")!! LLVMPositionBuilderAtEnd(builder, bb) LLVMBuildRet(builder, irClass.typeInfoPtr.llvm) LLVMDisposeBuilder(builder) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 232eb9709ad..b10a4a6d5a9 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -5,8 +5,7 @@ package org.jetbrains.kotlin.backend.konan -import llvm.LLVMDumpModule -import llvm.LLVMModuleRef +import llvm.* import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor @@ -328,6 +327,20 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { lateinit var bitcodeFileName: String lateinit var library: KonanLibraryLayout + private var llvmDisposed = false + + fun disposeLlvm() { + if (llvmDisposed) return + if (::debugInfo.isInitialized) + DIDispose(debugInfo.builder) + if (llvmModule != null) + LLVMDisposeModule(llvmModule) + if (::llvm.isInitialized) + LLVMDisposeModule(llvm.runtime.llvmModule) + tryDisposeLLVMContext() + llvmDisposed = true + } + val cStubsManager = CStubsManager(config.target) val coverage = CoverageManager(this) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt index a0b77c4b06d..8aae81d13f5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/InlineClasses.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.backend.konan.ir.containsNull +import org.jetbrains.kotlin.backend.konan.ir.getSuperClassNotAny import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass @@ -211,11 +212,6 @@ private val implicitInlineClasses = KonanFqNames.nativePtr + InteropFqNames.cPointer).toSet() -private val superQualifierTable = mutableMapOf>() -private fun IrClass.getAllSuperClassifiers(): List = superQualifierTable.getOrPut(this) { - listOf(this) + this.superTypes.flatMap { (it.classifierOrFail.owner as IrClass).getAllSuperClassifiers() } -} - internal object KotlinTypeInlineClassesSupport : InlineClassesSupport() { override fun isNullable(type: KotlinType): Boolean = type.isNullable() @@ -272,8 +268,12 @@ private object IrTypeInlineClassesSupport : InlineClassesSupport).invokeToplevel(context.phaseConfig, context, Unit) + try { + (toplevelPhase as CompilerPhase).invokeToplevel(context.phaseConfig, context, Unit) + } finally { + context.disposeLlvm() + } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index f47dd2cf255..5ed7aa77473 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -378,12 +378,13 @@ internal val entryPointPhase = SameTypeNamedPhaseWrapper( internal val bitcodePhase = namedIrModulePhase( name = "Bitcode", description = "LLVM Bitcode generation", - lower = buildDFGPhase then + lower = contextLLVMSetupPhase then + buildDFGPhase then serializeDFGPhase then deserializeDFGPhase then devirtualizationPhase then dcePhase then - contextLLVMSetupPhase then + createLLVMDeclarationsPhase then ghaPhase then RTTIPhase then generateDebugInfoHeaderPhase then @@ -418,6 +419,7 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase( verifyBitcodePhase then printBitcodePhase then produceOutputPhase then + disposeLLVMPhase then unitSink() ) then linkPhase diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt index c624cb40861..3559ed6d20a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/BitcodePhases.kt @@ -26,15 +26,30 @@ internal val contextLLVMSetupPhase = makeKonanModuleOpPhase( // (see Llvm class in ContextUtils) // Which in turn is determined by the clang flags // used to compile runtime.bc. - val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose + llvmContext = LLVMContextCreate()!! + val llvmModule = LLVMModuleCreateWithNameInContext("out", llvmContext)!! context.llvmModule = llvmModule context.debugInfo.builder = DICreateBuilder(llvmModule) + } +) + +internal val createLLVMDeclarationsPhase = makeKonanModuleOpPhase( + name = "CreateLLVMDeclarations", + description = "Map IR declarations to LLVM", + prerequisite = setOf(contextLLVMSetupPhase), + op = { context, _ -> context.llvmDeclarations = createLlvmDeclarations(context) context.lifetimes = mutableMapOf() context.codegenVisitor = CodeGeneratorVisitor(context, context.lifetimes) } ) +internal val disposeLLVMPhase = makeKonanModuleOpPhase( + name = "DisposeLLVM", + description = "Dispose LLVM", + op = { context, _ -> context.disposeLlvm() } +) + internal val RTTIPhase = makeKonanModuleOpPhase( name = "RTTI", description = "RTTI generation", diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index f48fea7ef6d..9cd1c0f4d6c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -23,7 +23,7 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { fun llvmFunction(function: IrFunction): LLVMValueRef = llvmFunctionOrNull(function) ?: error("no function ${function.name} in ${function.file.fqName}") fun llvmFunctionOrNull(function: IrFunction): LLVMValueRef? = function.llvmFunctionOrNull - val intPtrType = LLVMIntPtrType(llvmTargetData)!! + val intPtrType = LLVMIntPtrTypeInContext(llvmContext, llvmTargetData)!! internal val immOneIntPtrType = LLVMConstInt(intPtrType, 1, 1)!! // Keep in sync with OBJECT_TAG_MASK in C++. internal val immTypeInfoMask = LLVMConstNot(LLVMConstInt(intPtrType, 3, 0)!!)!! @@ -120,12 +120,17 @@ internal inline fun generateFunction(codegen: CodeGenerator, code: FunctionGenerationContext.(FunctionGenerationContext) -> R) { val llvmFunction = codegen.llvmFunction(function) - generateFunctionBody(FunctionGenerationContext( + val functionGenerationContext = FunctionGenerationContext( llvmFunction, codegen, startLocation, endLocation, - function), code) + function) + try { + generateFunctionBody(functionGenerationContext, code) + } finally { + functionGenerationContext.dispose() + } // To perform per-function validation. if (false) @@ -135,7 +140,12 @@ internal inline fun generateFunction(codegen: CodeGenerator, internal inline fun generateFunction(codegen: CodeGenerator, function: LLVMValueRef, code:FunctionGenerationContext.(FunctionGenerationContext) -> R) { - generateFunctionBody(FunctionGenerationContext(function, codegen, null, null), code) + val functionGenerationContext = FunctionGenerationContext(function, codegen, null, null) + try { + generateFunctionBody(functionGenerationContext, code) + } finally { + functionGenerationContext.dispose() + } } internal inline fun generateFunction( @@ -218,14 +228,18 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, } } + fun dispose() { + currentPositionHolder.dispose() + } + private fun basicBlockInFunction(name: String, locationInfo: LocationInfo?): LLVMBasicBlockRef { - val bb = LLVMAppendBasicBlock(function, name)!! + val bb = LLVMAppendBasicBlockInContext(llvmContext, function, name)!! update(bb, locationInfo) return bb } fun basicBlock(name:String = "label_", startLocationInfo:LocationInfo?, endLocationInfo: LocationInfo? = startLocationInfo): LLVMBasicBlockRef { - val result = LLVMInsertBasicBlock(this.currentBlock, name)!! + val result = LLVMInsertBasicBlockInContext(llvmContext, this.currentBlock, name)!! update(result, startLocationInfo, endLocationInfo) LLVMMoveBasicBlockAfter(result, this.currentBlock) return result @@ -1076,7 +1090,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, * This class is introduced to workaround unreachable code handling. */ inner class PositionHolder { - private val builder: LLVMBuilderRef = LLVMCreateBuilder()!! + private val builder: LLVMBuilderRef = LLVMCreateBuilderInContext(llvmContext)!! fun getBuilder(): LLVMBuilderRef { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt index cb35d426e3e..0cdaf77f1a8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/ContextUtils.kt @@ -296,14 +296,12 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { } private fun importMemset(): LLVMValueRef { - val parameterTypes = cValuesOf(int8TypePtr, int8Type, int32Type, int1Type) - val functionType = LLVMFunctionType(LLVMVoidType(), parameterTypes, 4, 0) + val functionType = functionType(voidType, false, int8TypePtr, int8Type, int32Type, int1Type) return LLVMAddFunction(llvmModule, "llvm.memset.p0i8.i32", functionType)!! } private fun importMemcpy(): LLVMValueRef { - val parameterTypes = cValuesOf(int8TypePtr, int8TypePtr, int32Type, int1Type) - val functionType = LLVMFunctionType(LLVMVoidType(), parameterTypes, 4, 0) + val functionType = functionType(voidType, false, int8TypePtr, int8TypePtr, int32Type, int1Type) return LLVMAddFunction(llvmModule, "llvm.memcpy.p0i8.p0i8.i32", functionType)!! } @@ -550,12 +548,12 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { override fun getValue(thisRef: Llvm, property: KProperty<*>): LLVMValueRef = value } } - val llvmInt8 = LLVMInt8Type()!! - val llvmInt16 = LLVMInt16Type()!! - val llvmInt32 = LLVMInt32Type()!! - val llvmInt64 = LLVMInt64Type()!! - val llvmFloat = LLVMFloatType()!! - val llvmDouble = LLVMDoubleType()!! + val llvmInt8 = int8Type + val llvmInt16 = int16Type + val llvmInt32 = int32Type + val llvmInt64 = int64Type + val llvmFloat = floatType + val llvmDouble = doubleType } class IrStaticInitializer(val file: IrFile, val initializer: LLVMValueRef) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt index 61ee36e41e6..b5b24deb764 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DataLayout.kt @@ -12,23 +12,20 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.types.isUnit -private val primitiveToLlvm = PrimitiveBinaryType.values().associate { - it to when (it) { - PrimitiveBinaryType.BOOLEAN -> LLVMInt1Type() - PrimitiveBinaryType.BYTE -> LLVMInt8Type() - PrimitiveBinaryType.SHORT -> LLVMInt16Type() - PrimitiveBinaryType.INT -> LLVMInt32Type() - PrimitiveBinaryType.LONG -> LLVMInt64Type() - PrimitiveBinaryType.FLOAT -> LLVMFloatType() - PrimitiveBinaryType.DOUBLE -> LLVMDoubleType() +private fun RuntimeAware.getLlvmType(primitiveBinaryType: PrimitiveBinaryType?) = when (primitiveBinaryType) { + null -> this.kObjHeaderPtr - PrimitiveBinaryType.POINTER -> int8TypePtr - }!! + PrimitiveBinaryType.BOOLEAN -> int1Type + PrimitiveBinaryType.BYTE -> int8Type + PrimitiveBinaryType.SHORT -> int16Type + PrimitiveBinaryType.INT -> int32Type + PrimitiveBinaryType.LONG -> int64Type + PrimitiveBinaryType.FLOAT -> floatType + PrimitiveBinaryType.DOUBLE -> doubleType + + PrimitiveBinaryType.POINTER -> int8TypePtr } -private fun RuntimeAware.getLlvmType(primitiveBinaryType: PrimitiveBinaryType?) = - primitiveBinaryType?.let { primitiveToLlvm[it]!! } ?: this.kObjHeaderPtr - internal fun RuntimeAware.getLLVMType(type: IrType): LLVMTypeRef = getLlvmType(type.computePrimitiveBinaryTypeOrNull()) @@ -37,7 +34,7 @@ internal fun RuntimeAware.getLLVMType(type: DataFlowIR.Type) = internal fun RuntimeAware.getLLVMReturnType(type: IrType): LLVMTypeRef { return when { - type.isUnit() || type.isNothing() -> LLVMVoidType()!! + type.isUnit() || type.isNothing() -> voidType else -> getLLVMType(type) } } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt index 30ed649a30d..4ad186fb27c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/DebugUtils.kt @@ -26,8 +26,8 @@ import org.jetbrains.kotlin.konan.file.File internal object DWARF { val producer = "konanc ${KonanVersion.CURRENT} / kotlin-compiler: ${KotlinVersion.CURRENT}" /* TODO: from LLVM sources is unclear what runtimeVersion corresponds to term in terms of dwarf specification. */ - val dwarfVersionMetaDataNodeName = "Dwarf Version".mdString() - val dwarfDebugInfoMetaDataNodeName = "Debug Info Version".mdString() + val dwarfVersionMetaDataNodeName get() = "Dwarf Version".mdString() + val dwarfDebugInfoMetaDataNodeName get() = "Debug Info Version".mdString() const val debugInfoVersion = 3 /* TODO: configurable? */ /** * This is the value taken from [DIFlags.FlagFwdDecl], to mark type declaration as @@ -80,7 +80,7 @@ internal class DebugInfo internal constructor(override val context: Context):Con context.irBuiltIns.doubleType to context.llvm.llvmDouble) val llvmTypeSizes = llvmTypes.map { it.key to LLVMSizeOfTypeInBits(llvmTargetData, it.value) }.toMap() val llvmTypeAlignments = llvmTypes.map {it.key to LLVMPreferredAlignmentOfType(llvmTargetData, it.value)}.toMap() - val otherLlvmType = LLVMPointerType(LLVMInt64Type(), 0)!! + val otherLlvmType = LLVMPointerType(int64Type, 0)!! val otherTypeSize = LLVMSizeOfTypeInBits(llvmTargetData, otherLlvmType) val otherTypeAlignment = LLVMPreferredAlignmentOfType(llvmTargetData, otherLlvmType) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt index b6b1e2a0437..39d4f971f50 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IntrinsicGenerator.kt @@ -344,7 +344,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv // Note: LLVM allows to read without padding tail up to byte boundary, but the result seems to be incorrect. val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum - val bitsWithPaddingType = LLVMIntType(bitsWithPaddingNum)!! + val bitsWithPaddingType = LLVMIntTypeInContext(llvmContext, bitsWithPaddingNum)!! val bitsWithPaddingPtr = bitcast(org.jetbrains.kotlin.backend.konan.llvm.pointerType(bitsWithPaddingType), gep(ptr, org.jetbrains.kotlin.backend.konan.llvm.Int64(offset / 8).llvm)) val bitsWithPadding = load(bitsWithPaddingPtr).setUnaligned() @@ -370,13 +370,13 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv val value = args[3] assert(value.type == int64Type) - val bitsType = LLVMIntType(size)!! + val bitsType = LLVMIntTypeInContext(llvmContext, size)!! val prefixBitsNum = (offset % 8).toInt() val suffixBitsNum = (8 - ((size + offset) % 8).toInt()) % 8 val bitsWithPaddingNum = prefixBitsNum + size + suffixBitsNum - val bitsWithPaddingType = LLVMIntType(bitsWithPaddingNum)!! + val bitsWithPaddingType = LLVMIntTypeInContext(llvmContext, bitsWithPaddingNum)!! // 0011111000: val discardBitsMask = LLVMConstShl( @@ -443,8 +443,8 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv } // TODO: Find better place for these guys. - private val kImmZero = LLVMConstInt(LLVMInt32Type(), 0, 1)!! - private val kImmOne = LLVMConstInt(LLVMInt32Type(), 1, 1)!! + private val kImmZero = LLVMConstInt(int32Type, 0, 1)!! + private val kImmOne = LLVMConstInt(int32Type, 1, 1)!! private fun FunctionGenerationContext.emitGetObjCClass(callSite: IrCall): LLVMValueRef { val descriptor = callSite.descriptor.original @@ -487,7 +487,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv return when (val typeKind = LLVMGetTypeKind(first.type)) { llvm.LLVMTypeKind.LLVMFloatTypeKind, llvm.LLVMTypeKind.LLVMDoubleTypeKind -> { val numBits = llvm.LLVMSizeOfTypeInBits(codegen.llvmTargetData, first.type).toInt() - val integerType = llvm.LLVMIntType(numBits)!! + val integerType = LLVMIntTypeInContext(llvmContext, numBits)!! icmpEq(bitcast(integerType, first), bitcast(integerType, second)) } llvm.LLVMTypeKind.LLVMIntegerTypeKind, llvm.LLVMTypeKind.LLVMPointerTypeKind -> icmpEq(first, second) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 03c8a785b18..2f6724d7e60 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -65,9 +65,10 @@ val IrField.isMainOnlyNonPrimitive get() = when { internal fun verifyModule(llvmModule: LLVMModuleRef, current: String = "") { memScoped { val errorRef = allocPointerTo() - // TODO: use LLVMDisposeMessage() on errorRef, once possible in interop. - if (LLVMVerifyModule( - llvmModule, LLVMVerifierFailureAction.LLVMPrintMessageAction, errorRef.ptr) == 1) { + val verificationResult = LLVMVerifyModule( + llvmModule, LLVMVerifierFailureAction.LLVMPrintMessageAction, errorRef.ptr) + LLVMDisposeMessage(errorRef.value) + if (verificationResult == 1) { if (current.isNotEmpty()) println("Error in $current") LLVMDumpModule(llvmModule) @@ -349,8 +350,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map return kTrue false -> return kFalse } - IrConstKind.Char -> return LLVMConstInt(LLVMInt16Type(), (value.value as Char).toLong(), 0)!! - IrConstKind.Byte -> return LLVMConstInt(LLVMInt8Type(), (value.value as Byte).toLong(), 1)!! - IrConstKind.Short -> return LLVMConstInt(LLVMInt16Type(), (value.value as Short).toLong(), 1)!! - IrConstKind.Int -> return LLVMConstInt(LLVMInt32Type(), (value.value as Int).toLong(), 1)!! - IrConstKind.Long -> return LLVMConstInt(LLVMInt64Type(), value.value as Long, 1)!! + IrConstKind.Char -> return Char16(value.value as Char).llvm + IrConstKind.Byte -> return Int8(value.value as Byte).llvm + IrConstKind.Short -> return Int16(value.value as Short).llvm + IrConstKind.Int -> return Int32(value.value as Int).llvm + IrConstKind.Long -> return Int64(value.value as Long).llvm IrConstKind.String -> return evaluateStringConst(value as IrConst) - IrConstKind.Float -> return LLVMConstRealOfString(LLVMFloatType(), (value.value as Float).toString())!! - IrConstKind.Double -> return LLVMConstRealOfString(LLVMDoubleType(), (value.value as Double).toString())!! + IrConstKind.Float -> return LLVMConstRealOfString(floatType, (value.value as Float).toString())!! + IrConstKind.Double -> return LLVMConstRealOfString(doubleType, (value.value as Double).toString())!! } TODO(ir2string(value)) } @@ -2150,10 +2151,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { @@ -2317,13 +2318,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map() +internal var llvmContext: LLVMContextRef + get() = llvmContextHolder.get() + set(value) { llvmContextHolder.set(value) } + +internal fun tryDisposeLLVMContext() { + val llvmContext = llvmContextHolder.get() + if (llvmContext != null) + LLVMContextDispose(llvmContext) + llvmContextHolder.remove() +} + +internal val LLVMTypeRef.context: LLVMContextRef + get() = LLVMGetTypeContext(this)!! + +internal val List.context: LLVMContextRef + get() { + val context = this[0].context + for (i in 1 until this.size) + assert(this[i].context == context) { + "Expected the same context for all types in a list" + } + return context + } + internal val LLVMValueRef.type: LLVMTypeRef get() = LLVMTypeOf(this)!! @@ -77,32 +102,47 @@ internal open class Struct(val type: LLVMTypeRef?, val elements: List): LLVMTypeRef = - LLVMStructType(types.toCValues(), types.size, 0)!! + LLVMStructTypeInContext(llvmContext, types.toCValues(), types.size, 0)!! internal fun ContextUtils.numParameters(functionType: LLVMTypeRef) : Int { // Note that type is usually function pointer, so we have to dereference it. @@ -273,7 +302,7 @@ fun parseBitcodeFile(path: String): LLVMModuleRef = memScoped { try { val moduleRef = alloc() - val parseRes = LLVMParseBitcode2(memoryBuffer, moduleRef.ptr) + val parseRes = LLVMParseBitcodeInContext2(llvmContext, memoryBuffer, moduleRef.ptr) if (parseRes != 0) { throw Error(parseRes.toString()) } @@ -347,8 +376,8 @@ fun addFunctionSignext(function: LLVMValueRef, index: Int, type: LLVMTypeRef?) { } } -internal fun String.mdString() = LLVMMDString(this, this.length)!! -internal fun node(vararg it:LLVMValueRef) = LLVMMDNode(it.toList().toCValues(), it.size) +internal fun String.mdString() = LLVMMDStringInContext(llvmContext, this, this.length)!! +internal fun node(vararg it:LLVMValueRef) = LLVMMDNodeInContext(llvmContext, it.toList().toCValues(), it.size) internal fun LLVMValueRef.setUnaligned() = apply { LLVMSetAlignment(this, 1) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt index 80eb602b63d..66df8bb3a53 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/RTTIGenerator.kt @@ -149,30 +149,30 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils { private val arrayClasses = mapOf( "kotlin.Array" to kObjHeaderPtr, - "kotlin.ByteArray" to LLVMInt8Type()!!, - "kotlin.CharArray" to LLVMInt16Type()!!, - "kotlin.ShortArray" to LLVMInt16Type()!!, - "kotlin.IntArray" to LLVMInt32Type()!!, - "kotlin.LongArray" to LLVMInt64Type()!!, - "kotlin.FloatArray" to LLVMFloatType()!!, - "kotlin.DoubleArray" to LLVMDoubleType()!!, - "kotlin.BooleanArray" to LLVMInt8Type()!!, - "kotlin.String" to LLVMInt16Type()!!, - "kotlin.native.ImmutableBlob" to LLVMInt8Type()!!, + "kotlin.ByteArray" to int8Type, + "kotlin.CharArray" to int16Type, + "kotlin.ShortArray" to int16Type, + "kotlin.IntArray" to int32Type, + "kotlin.LongArray" to int64Type, + "kotlin.FloatArray" to floatType, + "kotlin.DoubleArray" to doubleType, + "kotlin.BooleanArray" to int8Type, + "kotlin.String" to int16Type, + "kotlin.native.ImmutableBlob" to int8Type, "kotlin.native.internal.NativePtrArray" to kInt8Ptr ) // Keep in sync with Konan_RuntimeType. private val runtimeTypeMap = mapOf( kObjHeaderPtr to 1, - LLVMInt8Type()!! to 2, - LLVMInt16Type()!! to 3, - LLVMInt32Type()!! to 4, - LLVMInt64Type()!! to 5, - LLVMFloatType()!! to 6, - LLVMDoubleType()!! to 7, + int8Type to 2, + int16Type to 3, + int32Type to 4, + int64Type to 5, + floatType to 6, + doubleType to 7, kInt8Ptr to 8, - LLVMInt1Type()!! to 9 + int1Type to 9 ) private fun getInstanceSize(classType: LLVMTypeRef?, className: FqName) : Int { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt index b75a4a275bd..e9e17695063 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/objcexport/ObjCExportCodeGenerator.kt @@ -1310,8 +1310,8 @@ private val ObjCValueType.llvmType: LLVMTypeRef get() = when (this) { ObjCValueType.UNSIGNED_SHORT -> int16Type ObjCValueType.UNSIGNED_INT -> int32Type ObjCValueType.UNSIGNED_LONG_LONG -> int64Type - ObjCValueType.FLOAT -> LLVMFloatType()!! - ObjCValueType.DOUBLE -> LLVMDoubleType()!! + ObjCValueType.FLOAT -> floatType + ObjCValueType.DOUBLE -> doubleType ObjCValueType.POINTER -> kInt8Ptr } diff --git a/backend.native/llvm.def b/backend.native/llvm.def index 2badbd5071e..640f86e5af2 100644 --- a/backend.native/llvm.def +++ b/backend.native/llvm.def @@ -74,10 +74,15 @@ linkerOpts.mingw = -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lL # ld: -r and -shared may not be used together excludedFunctions.mingw = LLVMDumpType - +# Functions from LLVMIntPtrType to LLVMModuleCreateWithName are excluded because they work with the GlobalContext. +# This might not be safe if the compiler is called from a daemon process. excludedFunctions = LLVMInitializeAllAsmParsers LLVMInitializeAllAsmPrinters LLVMInitializeAllDisassemblers \ LLVMInitializeAllTargetInfos LLVMInitializeAllTargetMCs LLVMInitializeAllTargets LLVMInitializeNativeTarget \ LLVMInitializeNativeAsmParser LLVMInitializeNativeAsmPrinter LLVMInitializeNativeDisassembler \ - LLVMConstInBoundsGEP2 LLVMConstGEP2 + LLVMConstInBoundsGEP2 LLVMConstGEP2 LLVMIntPtrType LLVMIntPtrTypeForAS LLVMGetMDKindID LLVMInt1Type LLVMInt8Type \ + LLVMInt16Type LLVMInt32Type LLVMInt64Type LLVMInt128Type LLVMIntType LLVMHalfType LLVMFloatType LLVMDoubleType \ + LLVMX86FP80Type LLVMFP128Type LLVMPPCFP128Type LLVMX86MMXType LLVMStructType LLVMVoidType LLVMLabelType \ + LLVMMDString LLVMMDNode LLVMConstString LLVMConstStruct LLVMAppendBasicBlock LLVMInsertBasicBlock LLVMCreateBuilder \ + LLVMParseBitcode LLVMParseBitcode2 LLVMGetBitcodeModule LLVMGetBitcodeModule2 LLVMGetGlobalContext LLVMModuleCreateWithName strictEnums = LLVMIntPredicate LLVMOpcode LLVMDLLStorageClass LLVMCallConv LLVMThreadLocalMode LLVMAtomicOrdering diff --git a/llvmDebugInfoC/src/main/cpp/DebugInfoC.cpp b/llvmDebugInfoC/src/main/cpp/DebugInfoC.cpp index c3527decf01..8e025020846 100644 --- a/llvmDebugInfoC/src/main/cpp/DebugInfoC.cpp +++ b/llvmDebugInfoC/src/main/cpp/DebugInfoC.cpp @@ -59,6 +59,10 @@ DIBuilderRef DICreateBuilder(LLVMModuleRef module) { void DIFinalize(DIBuilderRef builder) { auto diBuilder = llvm::unwrap(builder); diBuilder->finalize(); +} + +void DIDispose(DIBuilderRef builder) { + auto diBuilder = llvm::unwrap(builder); delete diBuilder; } diff --git a/llvmDebugInfoC/src/main/include/DebugInfoC.h b/llvmDebugInfoC/src/main/include/DebugInfoC.h index ddc9d7ed667..59079a24397 100644 --- a/llvmDebugInfoC/src/main/include/DebugInfoC.h +++ b/llvmDebugInfoC/src/main/include/DebugInfoC.h @@ -40,6 +40,7 @@ typedef struct DIExpression *DIExpressionRef; DIBuilderRef DICreateBuilder(LLVMModuleRef module); void DIFinalize(DIBuilderRef builder); +void DIDispose(DIBuilderRef builder); DICompileUnitRef DICreateCompilationUnit(DIBuilderRef builder, unsigned int lang, const char *File, const char* dir, const char * producer, int isOptimized, const char * flags, unsigned int rv); diff --git a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/main.kt b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/main.kt index 0e27cc33ba7..7b5111d4714 100644 --- a/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/main.kt +++ b/utilities/src/main/kotlin/org/jetbrains/kotlin/cli/utilities/main.kt @@ -7,8 +7,9 @@ package org.jetbrains.kotlin.cli.utilities import org.jetbrains.kotlin.native.interop.gen.defFileDependencies import org.jetbrains.kotlin.cli.bc.main as konancMain import org.jetbrains.kotlin.cli.klib.main as klibMain +import org.jetbrains.kotlin.cli.bc.mainNoExit as konancMainNoExit -fun main(args: Array) { +private fun mainImpl(args: Array, konancMain: (Array) -> Unit) { val utilityName = args[0] val utilityArgs = args.drop(1).toTypedArray() when (utilityName) { @@ -31,3 +32,7 @@ fun main(args: Array) { } } +fun main(args: Array) = mainImpl(args, ::konancMain) + +fun daemonMain(args: Array) = mainImpl(args, ::konancMainNoExit) +