Support memory model compiler selection switch.

This commit is contained in:
Nikolay Igotti
2019-06-24 16:26:25 +03:00
committed by Nikolay Igotti
parent 9156cbd758
commit b8ea28cea8
11 changed files with 43 additions and 61 deletions
@@ -177,6 +177,18 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
put(ENABLE_ASSERTIONS, arguments.enableAssertions)
put(MEMORY_MODEL, when (arguments.memoryModel) {
"relaxed" -> {
configuration.report(STRONG_WARNING, "Relaxed memory model is not yet functional")
MemoryModel.RELAXED
}
"strict" -> MemoryModel.STRICT
else -> {
configuration.report(ERROR, "Unsupported memory model ${arguments.memoryModel}")
return
}
})
when {
arguments.generateWorkerTestRunner -> put(GENERATE_TEST_RUNNER, TestRunnerKind.WORKER)
arguments.generateTestRunner -> put(GENERATE_TEST_RUNNER, TestRunnerKind.MAIN_THREAD)
@@ -48,7 +48,10 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@Argument(value = "-manifest", valueDescription = "<path>", description = "Provide a maniferst addend file")
var manifestFile: String? = null
@Argument(value="-module-name", deprecatedName = "-module_name", valueDescription = "<name>", description = "Spicify a name for the compilation module")
@Argument(value="-memory-model", valueDescription = "<model>", description = "Memory model to use, 'strict' and 'relaxed' are currently supported")
var memoryModel: String? = "strict"
@Argument(value="-module-name", deprecatedName = "-module_name", valueDescription = "<name>", description = "Specify a name for the compilation module")
var moduleName: String? = null
@Argument(value = "-native-library", deprecatedName = "-nativelibrary", shortName = "-nl", valueDescription = "<path>", description = "Include the native bitcode library")
@@ -450,6 +450,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
fun shouldOptimize() = config.configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)
val memoryModel = config.memoryModel
override var inVerbosePhase = false
override fun log(message: () -> String) {
if (inVerbosePhase) {
@@ -46,6 +46,8 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
val debug: Boolean get() = configuration.getBoolean(KonanConfigKeys.DEBUG)
val memoryModel: MemoryModel get() = configuration.get(KonanConfigKeys.MEMORY_MODEL)!!
init {
if (!platformManager.isEnabled(target)) {
error("Target ${target.visibleName} is not available on the ${HostManager.hostName} host")
@@ -52,6 +52,8 @@ class KonanConfigKeys {
= CompilerConfigurationKey.create("list available targets")
val MANIFEST_FILE: CompilerConfigurationKey<String?>
= CompilerConfigurationKey.create("provide manifest addend file")
val MEMORY_MODEL: CompilerConfigurationKey<MemoryModel>
= CompilerConfigurationKey.create("memory model")
val META_INFO: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("generate metadata")
val MODULE_KIND: CompilerConfigurationKey<ModuleKind>
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
enum class MemoryModel(val suffix: String) {
STRICT("Strict"),
RELAXED("Relaxed)")
}
@@ -2,8 +2,6 @@
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
enum class TestRunnerKind {
@@ -307,12 +307,18 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
}
private fun updateReturnRef(value: LLVMValueRef, address: LLVMValueRef) {
store(value, address)
if (context.memoryModel == MemoryModel.STRICT)
store(value, address)
else
call(context.llvm.updateReturnRefFunction, listOf(address, value))
}
private fun updateRef(value: LLVMValueRef, address: LLVMValueRef, onStack: Boolean) {
if (onStack) {
store(value, address)
if (context.memoryModel == MemoryModel.STRICT)
store(value, address)
else
call(context.llvm.updateStackRefFunction, listOf(address, value))
} else {
call(context.llvm.updateHeapRefFunction, listOf(address, value))
}
@@ -340,24 +346,6 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
SlotType.ANONYMOUS -> vars.createAnonymousSlot()
SlotType.RETURN_IF_ARENA -> returnSlot.let {
if (it != null)
call(context.llvm.getReturnSlotIfArenaFunction, listOf(it, vars.createAnonymousSlot()))
else {
// Return type is not an object type - can allocate locally.
localAllocs++
arenaSlot!!
}
}
is SlotType.PARAM_IF_ARENA ->
if (LLVMTypeOf(vars.load(resultLifetime.slotType.parameter)) != codegen.runtime.objHeaderPtrType)
vars.createAnonymousSlot()
else {
call(context.llvm.getParamSlotIfArenaFunction,
listOf(vars.load(resultLifetime.slotType.parameter), vars.createAnonymousSlot()))
}
else -> throw Error("Incorrect slot type: ${resultLifetime.slotType}")
}
args + resultSlot
@@ -958,7 +946,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
releaseVars()
LLVMBuildRet(builder, returnPhi)
}
// Do nothing, all paths throw.
// Do nothing, all paths throw.
else -> LLVMBuildUnreachable(builder)
}
}
@@ -426,10 +426,10 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
val initInstanceFunction = importRtFunction("InitInstance")
val initSharedInstanceFunction = importRtFunction("InitSharedInstance")
val updateHeapRefFunction = importRtFunction("UpdateHeapRef")
val updateStackRefFunction = importRtFunction("UpdateStackRef")
val updateReturnRefFunction = importRtFunction("UpdateReturnRef")
val enterFrameFunction = importRtFunction("EnterFrame")
val leaveFrameFunction = importRtFunction("LeaveFrame")
val getReturnSlotIfArenaFunction = importRtFunction("GetReturnSlotIfArena")
val getParamSlotIfArenaFunction = importRtFunction("GetParamSlotIfArena")
val lookupOpenMethodFunction = importRtFunction("LookupOpenMethod")
val isInstanceFunction = importRtFunction("IsInstance")
val checkInstanceFunction = importRtFunction("CheckInstance")
@@ -1484,39 +1484,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
}
//-------------------------------------------------------------------------//
/*
in C:
struct ObjHeader *header = (struct ObjHeader *)ptr;
struct T* obj = (T*)&header[1];
return &obj->fieldX;
in llvm ir:
%struct.ObjHeader = type { i32, i32 }
%struct.Object = type { i32, i32 }
; Function Attrs: nounwind ssp uwtable
define i32 @fooField2(i8*) #0 {
%2 = alloca i8*, align 8
%3 = alloca %struct.ObjHeader*, align 8
%4 = alloca %struct.Object*, align 8
store i8* %0, i8** %2, align 8
%5 = load i8*, i8** %2, align 8
%6 = bitcast i8* %5 to %struct.ObjHeader*
store %struct.ObjHeader* %6, %struct.ObjHeader** %3, align 8
%7 = load %struct.ObjHeader*, %struct.ObjHeader** %3, align 8
%8 = getelementptr inbounds %struct.ObjHeader, %struct.ObjHeader* %7, i64 1; <- (T*)&header[1];
%9 = bitcast %struct.ObjHeader* %8 to %struct.Object*
store %struct.Object* %9, %struct.Object** %4, align 8
%10 = load %struct.Object*, %struct.Object** %4, align 8
%11 = getelementptr inbounds %struct.Object, %struct.Object* %10, i32 0, i32 0 <- &obj->fieldX
%12 = load i32, i32* %11, align 4
ret i32 %12
}
*/
private fun fieldPtrOfClass(thisPtr: LLVMValueRef, value: IrField): LLVMValueRef {
val fieldInfo = context.llvmDeclarations.forField(value)
-2
View File
@@ -2365,8 +2365,6 @@ KBoolean Konan_ensureAcyclicAndSet(ObjHeader* where, KInt index, ObjHeader* what
return true;
}
void Kotlin_Any_share(ObjHeader* obj) {
auto* container = obj->container();
if (Shareable(container)) return;