Added nullifying all globals on deinitialization of runtime
This commit is contained in:
+40
-21
@@ -21,11 +21,8 @@ import llvm.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.allParameters
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||
import org.jetbrains.kotlin.backend.konan.KonanPhase
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
||||
import org.jetbrains.kotlin.backend.konan.PhaseManager
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
|
||||
@@ -340,21 +337,41 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
val kVoidFuncType = LLVMFunctionType(LLVMVoidType(), null, 0, 0)
|
||||
val kInitFuncType = LLVMFunctionType(LLVMVoidType(), cValuesOf(LLVMInt32Type()), 1, 0)
|
||||
val kNodeInitType = LLVMGetTypeByName(context.llvmModule, "struct.InitNode")!!
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun createInitBody(initName: String): LLVMValueRef {
|
||||
val initFunction = LLVMAddFunction(context.llvmModule, initName, kVoidFuncType)!! // create LLVM function
|
||||
val initFunction = LLVMAddFunction(context.llvmModule, initName, kInitFuncType)!! // create LLVM function
|
||||
codegen.prologue(initFunction, voidType)
|
||||
using(FunctionScope(initFunction)) {
|
||||
context.llvm.fileInitializers.forEach {
|
||||
val irField = it as IrField
|
||||
val descriptor = irField.descriptor
|
||||
val initialization = evaluateExpression(irField.initializer!!.expression)
|
||||
val globalPtr = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||
codegen.storeAnyGlobal(initialization, globalPtr)
|
||||
val bbInit = codegen.basicBlock("init")
|
||||
val bbDeinit = codegen.basicBlock("deinit")
|
||||
codegen.condBr(codegen.icmpEq(LLVMGetParam(initFunction, 0)!!, kImmZero), bbDeinit, bbInit)
|
||||
|
||||
codegen.appendingTo(bbDeinit) {
|
||||
context.llvm.fileInitializers.forEach {
|
||||
val irField = it as IrField
|
||||
val descriptor = irField.descriptor
|
||||
if (descriptor.type.isValueType())
|
||||
return@forEach // Is not a subject for memory management.
|
||||
val globalPtr = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||
codegen.storeAnyGlobal(codegen.kNullObjHeaderPtr, globalPtr)
|
||||
}
|
||||
objects.forEach { codegen.storeAnyGlobal(codegen.kNullObjHeaderPtr, it) }
|
||||
codegen.ret(null)
|
||||
}
|
||||
|
||||
codegen.appendingTo(bbInit) {
|
||||
context.llvm.fileInitializers.forEach {
|
||||
val irField = it as IrField
|
||||
val descriptor = irField.descriptor
|
||||
val initialization = evaluateExpression(irField.initializer!!.expression)
|
||||
val globalPtr = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||
codegen.storeAnyGlobal(initialization, globalPtr)
|
||||
}
|
||||
codegen.ret(null)
|
||||
}
|
||||
codegen.ret(null)
|
||||
}
|
||||
codegen.epilogue()
|
||||
|
||||
@@ -392,7 +409,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
using(FileScope(declaration)) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
|
||||
if (context.llvm.fileInitializers.isEmpty())
|
||||
if (context.llvm.fileInitializers.isEmpty() && objects.isEmpty())
|
||||
return
|
||||
|
||||
// Create global initialization records.
|
||||
@@ -456,7 +473,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
if (constructorDescriptor.isPrimary) {
|
||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||
if (!classDescriptor.isUnit()) {
|
||||
val objectPtr = objectPtrByName(classDescriptor)
|
||||
val objectPtr = getObjectInstanceStorage(classDescriptor)
|
||||
|
||||
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
||||
}
|
||||
@@ -722,7 +739,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
return codegen.theUnitInstanceRef.llvm
|
||||
}
|
||||
|
||||
var objectPtr = objectPtrByName(value.descriptor)
|
||||
var objectPtr = getObjectInstanceStorage(value.descriptor)
|
||||
val bbCurrent = codegen.currentBlock
|
||||
val bbInit = codegen.basicBlock("label_init")
|
||||
val bbExit = codegen.basicBlock("label_continue")
|
||||
@@ -1283,15 +1300,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun objectPtrByName(descriptor: ClassDescriptor): LLVMValueRef {
|
||||
private val objects = mutableSetOf<LLVMValueRef>()
|
||||
|
||||
private fun getObjectInstanceStorage(descriptor: ClassDescriptor): LLVMValueRef {
|
||||
assert (!descriptor.isUnit())
|
||||
return if (codegen.isExternal(descriptor)) {
|
||||
val llvmGlobal = if (!codegen.isExternal(descriptor)) {
|
||||
context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef
|
||||
} else {
|
||||
val llvmType = codegen.getLLVMType(descriptor.defaultType)
|
||||
codegen.importGlobal(descriptor.objectInstanceFieldSymbolName, llvmType,
|
||||
threadLocal = true)
|
||||
} else {
|
||||
context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef
|
||||
}
|
||||
objects += llvmGlobal
|
||||
return llvmGlobal
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -1942,8 +1963,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
private val kImmOne = LLVMConstInt(LLVMInt32Type(), 1, 1)!!
|
||||
private val kTrue = LLVMConstInt(LLVMInt1Type(), 1, 1)!!
|
||||
private val kFalse = LLVMConstInt(LLVMInt1Type(), 0, 1)!!
|
||||
private val kIntPtrZero = LLVMConstInt(codegen.intPtrType, 0, 1)!!
|
||||
|
||||
|
||||
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
context.log{"evaluateCall : origin:${ir2string(callee)}"}
|
||||
|
||||
@@ -26,7 +26,7 @@ struct RuntimeState {
|
||||
MemoryState* memoryState;
|
||||
};
|
||||
|
||||
typedef void (*Initializer)();
|
||||
typedef void (*Initializer)(int initialize);
|
||||
struct InitNode {
|
||||
Initializer init;
|
||||
InitNode* next;
|
||||
@@ -37,10 +37,10 @@ namespace {
|
||||
InitNode* initHeadNode = nullptr;
|
||||
InitNode* initTailNode = nullptr;
|
||||
|
||||
void InitGlobalVariables() {
|
||||
void InitOrDeinitGlobalVariables(int initialize) {
|
||||
InitNode *currNode = initHeadNode;
|
||||
while (currNode != nullptr) {
|
||||
currNode->init();
|
||||
currNode->init(initialize);
|
||||
currNode = currNode->next;
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ RuntimeState* InitRuntime() {
|
||||
RuntimeState* result = new RuntimeState();
|
||||
result->memoryState = InitMemory();
|
||||
// Keep global variables in state as well.
|
||||
InitGlobalVariables();
|
||||
InitOrDeinitGlobalVariables(true);
|
||||
#if KONAN_WINDOWS
|
||||
// Note that this code enforces UTF-8 console output, so we may want to rethink
|
||||
// how we perform console IO, if it turns out, that UTF-16 is better output format.
|
||||
@@ -78,6 +78,7 @@ RuntimeState* InitRuntime() {
|
||||
|
||||
void DeinitRuntime(RuntimeState* state) {
|
||||
if (state != nullptr) {
|
||||
InitOrDeinitGlobalVariables(false);
|
||||
DeinitMemory(state->memoryState);
|
||||
delete state;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user