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.allParameters
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
||||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanPhase
|
|
||||||
import org.jetbrains.kotlin.backend.konan.library.LinkData
|
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.descriptors.*
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
|
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 kVoidFuncType = LLVMFunctionType(LLVMVoidType(), null, 0, 0)
|
||||||
|
val kInitFuncType = LLVMFunctionType(LLVMVoidType(), cValuesOf(LLVMInt32Type()), 1, 0)
|
||||||
val kNodeInitType = LLVMGetTypeByName(context.llvmModule, "struct.InitNode")!!
|
val kNodeInitType = LLVMGetTypeByName(context.llvmModule, "struct.InitNode")!!
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun createInitBody(initName: String): LLVMValueRef {
|
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)
|
codegen.prologue(initFunction, voidType)
|
||||||
using(FunctionScope(initFunction)) {
|
using(FunctionScope(initFunction)) {
|
||||||
context.llvm.fileInitializers.forEach {
|
val bbInit = codegen.basicBlock("init")
|
||||||
val irField = it as IrField
|
val bbDeinit = codegen.basicBlock("deinit")
|
||||||
val descriptor = irField.descriptor
|
codegen.condBr(codegen.icmpEq(LLVMGetParam(initFunction, 0)!!, kImmZero), bbDeinit, bbInit)
|
||||||
val initialization = evaluateExpression(irField.initializer!!.expression)
|
|
||||||
val globalPtr = context.llvmDeclarations.forStaticField(descriptor).storage
|
codegen.appendingTo(bbDeinit) {
|
||||||
codegen.storeAnyGlobal(initialization, globalPtr)
|
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()
|
codegen.epilogue()
|
||||||
|
|
||||||
@@ -392,7 +409,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
using(FileScope(declaration)) {
|
using(FileScope(declaration)) {
|
||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
|
|
||||||
if (context.llvm.fileInitializers.isEmpty())
|
if (context.llvm.fileInitializers.isEmpty() && objects.isEmpty())
|
||||||
return
|
return
|
||||||
|
|
||||||
// Create global initialization records.
|
// Create global initialization records.
|
||||||
@@ -456,7 +473,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
if (constructorDescriptor.isPrimary) {
|
if (constructorDescriptor.isPrimary) {
|
||||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||||
if (!classDescriptor.isUnit()) {
|
if (!classDescriptor.isUnit()) {
|
||||||
val objectPtr = objectPtrByName(classDescriptor)
|
val objectPtr = getObjectInstanceStorage(classDescriptor)
|
||||||
|
|
||||||
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
||||||
}
|
}
|
||||||
@@ -722,7 +739,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
return codegen.theUnitInstanceRef.llvm
|
return codegen.theUnitInstanceRef.llvm
|
||||||
}
|
}
|
||||||
|
|
||||||
var objectPtr = objectPtrByName(value.descriptor)
|
var objectPtr = getObjectInstanceStorage(value.descriptor)
|
||||||
val bbCurrent = codegen.currentBlock
|
val bbCurrent = codegen.currentBlock
|
||||||
val bbInit = codegen.basicBlock("label_init")
|
val bbInit = codegen.basicBlock("label_init")
|
||||||
val bbExit = codegen.basicBlock("label_continue")
|
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())
|
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)
|
val llvmType = codegen.getLLVMType(descriptor.defaultType)
|
||||||
codegen.importGlobal(descriptor.objectInstanceFieldSymbolName, llvmType,
|
codegen.importGlobal(descriptor.objectInstanceFieldSymbolName, llvmType,
|
||||||
threadLocal = true)
|
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 kImmOne = LLVMConstInt(LLVMInt32Type(), 1, 1)!!
|
||||||
private val kTrue = LLVMConstInt(LLVMInt1Type(), 1, 1)!!
|
private val kTrue = LLVMConstInt(LLVMInt1Type(), 1, 1)!!
|
||||||
private val kFalse = LLVMConstInt(LLVMInt1Type(), 0, 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 {
|
private fun evaluateOperatorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
context.log{"evaluateCall : origin:${ir2string(callee)}"}
|
context.log{"evaluateCall : origin:${ir2string(callee)}"}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct RuntimeState {
|
|||||||
MemoryState* memoryState;
|
MemoryState* memoryState;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*Initializer)();
|
typedef void (*Initializer)(int initialize);
|
||||||
struct InitNode {
|
struct InitNode {
|
||||||
Initializer init;
|
Initializer init;
|
||||||
InitNode* next;
|
InitNode* next;
|
||||||
@@ -37,10 +37,10 @@ namespace {
|
|||||||
InitNode* initHeadNode = nullptr;
|
InitNode* initHeadNode = nullptr;
|
||||||
InitNode* initTailNode = nullptr;
|
InitNode* initTailNode = nullptr;
|
||||||
|
|
||||||
void InitGlobalVariables() {
|
void InitOrDeinitGlobalVariables(int initialize) {
|
||||||
InitNode *currNode = initHeadNode;
|
InitNode *currNode = initHeadNode;
|
||||||
while (currNode != nullptr) {
|
while (currNode != nullptr) {
|
||||||
currNode->init();
|
currNode->init(initialize);
|
||||||
currNode = currNode->next;
|
currNode = currNode->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ RuntimeState* InitRuntime() {
|
|||||||
RuntimeState* result = new RuntimeState();
|
RuntimeState* result = new RuntimeState();
|
||||||
result->memoryState = InitMemory();
|
result->memoryState = InitMemory();
|
||||||
// Keep global variables in state as well.
|
// Keep global variables in state as well.
|
||||||
InitGlobalVariables();
|
InitOrDeinitGlobalVariables(true);
|
||||||
#if KONAN_WINDOWS
|
#if KONAN_WINDOWS
|
||||||
// Note that this code enforces UTF-8 console output, so we may want to rethink
|
// 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.
|
// 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) {
|
void DeinitRuntime(RuntimeState* state) {
|
||||||
if (state != nullptr) {
|
if (state != nullptr) {
|
||||||
|
InitOrDeinitGlobalVariables(false);
|
||||||
DeinitMemory(state->memoryState);
|
DeinitMemory(state->memoryState);
|
||||||
delete state;
|
delete state;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user