Fix object init/deinit bug, refactoring (#1000)
This commit is contained in:
+15
-4
@@ -156,10 +156,14 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
|||||||
internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||||
lateinit var moduleDescriptor: ModuleDescriptor
|
lateinit var moduleDescriptor: ModuleDescriptor
|
||||||
|
|
||||||
override val builtIns: KonanBuiltIns by lazy(PUBLICATION) { moduleDescriptor.builtIns as KonanBuiltIns }
|
override val builtIns: KonanBuiltIns by lazy(PUBLICATION) {
|
||||||
|
moduleDescriptor.builtIns as KonanBuiltIns
|
||||||
|
}
|
||||||
|
|
||||||
val specialDeclarationsFactory = SpecialDeclarationsFactory(this)
|
val specialDeclarationsFactory = SpecialDeclarationsFactory(this)
|
||||||
override val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) { ReflectionTypes(moduleDescriptor, FqName("konan.internal")) }
|
override val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) {
|
||||||
|
ReflectionTypes(moduleDescriptor, FqName("konan.internal"))
|
||||||
|
}
|
||||||
private val vtableBuilders = mutableMapOf<ClassDescriptor, ClassVtablesBuilder>()
|
private val vtableBuilders = mutableMapOf<ClassDescriptor, ClassVtablesBuilder>()
|
||||||
|
|
||||||
fun getVtableBuilder(classDescriptor: ClassDescriptor) = vtableBuilders.getOrPut(classDescriptor) {
|
fun getVtableBuilder(classDescriptor: ClassDescriptor) = vtableBuilders.getOrPut(classDescriptor) {
|
||||||
@@ -182,9 +186,16 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
config.librariesWithDependencies(moduleDescriptor)
|
config.librariesWithDependencies(moduleDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun needGlobalInit(field: IrField): Boolean {
|
||||||
|
if (field.descriptor.containingDeclaration !is PackageFragmentDescriptor) return false
|
||||||
|
// TODO: add some smartness here. Maybe if package of the field is in never accessed
|
||||||
|
// assume its global init can be actually omitted.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: make lateinit?
|
// TODO: make lateinit?
|
||||||
var irModule: IrModuleFragment? = null
|
var irModule: IrModuleFragment? = null
|
||||||
set(module: IrModuleFragment?) {
|
set(module) {
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
throw Error("Another IrModule in the context.")
|
throw Error("Another IrModule in the context.")
|
||||||
}
|
}
|
||||||
@@ -203,7 +214,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var llvmModule: LLVMModuleRef? = null
|
var llvmModule: LLVMModuleRef? = null
|
||||||
set(module: LLVMModuleRef?) {
|
set(module) {
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
throw Error("Another LLVMModule in the context.")
|
throw Error("Another LLVMModule in the context.")
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-10
@@ -195,7 +195,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
val value = LLVMBuildLoad(builder, address, name)!!
|
val value = LLVMBuildLoad(builder, address, name)!!
|
||||||
if (isObjectRef(value) && isVar) {
|
if (isObjectRef(value) && isVar) {
|
||||||
val slot = alloca(LLVMTypeOf(value), variableLocation = null)
|
val slot = alloca(LLVMTypeOf(value), variableLocation = null)
|
||||||
storeAnyLocal(value, slot)
|
storeAny(value, slot)
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
@@ -206,15 +206,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
LLVMBuildStore(builder, value, ptr)
|
LLVMBuildStore(builder, value, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun storeAnyLocal(value: LLVMValueRef, ptr: LLVMValueRef) {
|
fun storeAny(value: LLVMValueRef, ptr: LLVMValueRef) {
|
||||||
if (isObjectRef(value)) {
|
|
||||||
updateRef(value, ptr)
|
|
||||||
} else {
|
|
||||||
LLVMBuildStore(builder, value, ptr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun storeAnyGlobal(value: LLVMValueRef, ptr: LLVMValueRef) {
|
|
||||||
if (isObjectRef(value)) {
|
if (isObjectRef(value)) {
|
||||||
updateRef(value, ptr)
|
updateRef(value, ptr)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-2
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
@@ -343,5 +343,5 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
|||||||
|
|
||||||
val usedFunctions = mutableListOf<LLVMValueRef>()
|
val usedFunctions = mutableListOf<LLVMValueRef>()
|
||||||
val staticInitializers = mutableListOf<LLVMValueRef>()
|
val staticInitializers = mutableListOf<LLVMValueRef>()
|
||||||
val fileInitializers = mutableListOf<IrElement>()
|
val fileInitializers = mutableListOf<IrField>()
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-33
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.ir.declarations.*
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptorBase
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
@@ -286,7 +285,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val kNodeInitType = LLVMGetTypeByName(context.llvmModule, "struct.InitNode")!!
|
val kNodeInitType = LLVMGetTypeByName(context.llvmModule, "struct.InitNode")!!
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun createInitBody(initName: String): LLVMValueRef {
|
private fun createInitBody(initName: String): LLVMValueRef {
|
||||||
val initFunction = LLVMAddFunction(context.llvmModule, initName, kInitFuncType)!! // create LLVM function
|
val initFunction = LLVMAddFunction(context.llvmModule, initName, kInitFuncType)!! // create LLVM function
|
||||||
generateFunction(codegen, initFunction) {
|
generateFunction(codegen, initFunction) {
|
||||||
using(FunctionScope(initFunction, it)) {
|
using(FunctionScope(initFunction, it)) {
|
||||||
@@ -296,26 +295,24 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
appendingTo(bbDeinit) {
|
appendingTo(bbDeinit) {
|
||||||
context.llvm.fileInitializers.forEach {
|
context.llvm.fileInitializers.forEach {
|
||||||
val irField = it as IrField
|
val descriptor = it.descriptor
|
||||||
val descriptor = irField.descriptor
|
|
||||||
if (descriptor.type.isValueType())
|
if (descriptor.type.isValueType())
|
||||||
return@forEach // Is not a subject for memory management.
|
return@forEach // Is not a subject for memory management.
|
||||||
val globalPtr = context.llvmDeclarations.forStaticField(descriptor).storage
|
val address = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||||
storeAnyGlobal(codegen.kNullObjHeaderPtr, globalPtr)
|
storeAny(codegen.kNullObjHeaderPtr, address)
|
||||||
}
|
}
|
||||||
objects.forEach { storeAnyGlobal(codegen.kNullObjHeaderPtr, it) }
|
objects.forEach { storeAny(codegen.kNullObjHeaderPtr, it) }
|
||||||
ret(null)
|
ret(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
appendingTo(bbInit) {
|
appendingTo(bbInit) {
|
||||||
context.llvm.fileInitializers
|
context.llvm.fileInitializers
|
||||||
.map { it as IrField }
|
|
||||||
.filterNot { it.initializer is IrConst<*> }
|
|
||||||
.forEach {
|
.forEach {
|
||||||
val descriptor = it.descriptor
|
if (it.initializer?.expression !is IrConst<*>?) {
|
||||||
val initialization = evaluateExpression(it.initializer!!.expression)
|
val initialization = evaluateExpression(it.initializer!!.expression)
|
||||||
val globalPtr = context.llvmDeclarations.forStaticField(descriptor).storage
|
val address = context.llvmDeclarations.forStaticField(it.descriptor).storage
|
||||||
storeAnyGlobal(initialization, globalPtr)
|
storeAny(initialization, address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret(null)
|
ret(null)
|
||||||
}
|
}
|
||||||
@@ -327,7 +324,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
// Creates static struct InitNode $nodeName = {$initName, NULL};
|
// Creates static struct InitNode $nodeName = {$initName, NULL};
|
||||||
|
|
||||||
fun createInitNode(initFunction: LLVMValueRef, nodeName: String): LLVMValueRef {
|
private fun createInitNode(initFunction: LLVMValueRef, nodeName: String): LLVMValueRef {
|
||||||
val nextInitNode = LLVMConstNull(pointerType(kNodeInitType)) // Set InitNode.next = NULL.
|
val nextInitNode = LLVMConstNull(pointerType(kNodeInitType)) // Set InitNode.next = NULL.
|
||||||
val argList = cValuesOf(initFunction, nextInitNode) // Construct array of args.
|
val argList = cValuesOf(initFunction, nextInitNode) // Construct array of args.
|
||||||
val initNode = LLVMConstNamedStruct(kNodeInitType, argList, 2)!! // Create static object of class InitNode.
|
val initNode = LLVMConstNamedStruct(kNodeInitType, argList, 2)!! // Create static object of class InitNode.
|
||||||
@@ -336,7 +333,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun createInitCtor(ctorName: String, initNodePtr: LLVMValueRef) {
|
private fun createInitCtor(ctorName: String, initNodePtr: LLVMValueRef) {
|
||||||
val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!! // Create constructor function.
|
val ctorFunction = LLVMAddFunction(context.llvmModule, ctorName, kVoidFuncType)!! // Create constructor function.
|
||||||
generateFunction(codegen, ctorFunction) {
|
generateFunction(codegen, ctorFunction) {
|
||||||
call(context.llvm.appendToInitalizersTail, listOf(initNodePtr)) // Add node to the tail of initializers list.
|
call(context.llvm.appendToInitalizersTail, listOf(initNodePtr)) // Add node to the tail of initializers list.
|
||||||
@@ -348,8 +345,9 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitFile(declaration: IrFile) {
|
override fun visitFile(declaration: IrFile) {
|
||||||
|
// TODO: collect those two in one place.
|
||||||
context.llvm.fileInitializers.clear()
|
context.llvm.fileInitializers.clear()
|
||||||
|
objects.clear()
|
||||||
|
|
||||||
using(FileScope(declaration)) {
|
using(FileScope(declaration)) {
|
||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
@@ -361,8 +359,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
val fileName = declaration.name.takeLastWhile { it != '/' }.dropLastWhile { it != '.' }.dropLast(1)
|
val fileName = declaration.name.takeLastWhile { it != '/' }.dropLastWhile { it != '.' }.dropLast(1)
|
||||||
val initName = "${fileName}_init_${context.llvm.globalInitIndex}"
|
val initName = "${fileName}_init_${context.llvm.globalInitIndex}"
|
||||||
val nodeName = "${fileName}_node_${context.llvm.globalInitIndex}"
|
val nodeName = "${fileName}_node_${context.llvm.globalInitIndex}"
|
||||||
// Make the name prefix easily parsable for the platforms lacking
|
// Make the name prefix easily parsable for the platforms lacking
|
||||||
// llvm.global_ctors mechanism (such as wasm).
|
// llvm.global_ctors mechanism (such as WASM).
|
||||||
val ctorName = "Konan_global_ctor_${fileName}_${context.llvm.globalInitIndex++}"
|
val ctorName = "Konan_global_ctor_${fileName}_${context.llvm.globalInitIndex++}"
|
||||||
|
|
||||||
val initFunction = createInitBody(initName)
|
val initFunction = createInitBody(initName)
|
||||||
@@ -630,7 +628,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
context.log{"visitField : ${ir2string(declaration)}"}
|
context.log{"visitField : ${ir2string(declaration)}"}
|
||||||
debugFieldDeclaration(declaration)
|
debugFieldDeclaration(declaration)
|
||||||
val descriptor = declaration.descriptor
|
val descriptor = declaration.descriptor
|
||||||
if (descriptor.containingDeclaration is PackageFragmentDescriptor) {
|
if (context.needGlobalInit(declaration)) {
|
||||||
val type = codegen.getLLVMType(descriptor.type)
|
val type = codegen.getLLVMType(descriptor.type)
|
||||||
val globalProperty = context.llvmDeclarations.forStaticField(descriptor).storage
|
val globalProperty = context.llvmDeclarations.forStaticField(descriptor).storage
|
||||||
if (declaration.initializer!!.expression is IrConst<*>) {
|
if (declaration.initializer!!.expression is IrConst<*>) {
|
||||||
@@ -640,10 +638,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
context.llvm.fileInitializers.add(declaration)
|
context.llvm.fileInitializers.add(declaration)
|
||||||
|
|
||||||
LLVMSetLinkage(globalProperty, LLVMLinkage.LLVMInternalLinkage)
|
|
||||||
// (Cannot do this before the global is initialized).
|
// (Cannot do this before the global is initialized).
|
||||||
|
LLVMSetLinkage(globalProperty, LLVMLinkage.LLVMInternalLinkage)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1292,12 +1288,12 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
if (value.descriptor.dispatchReceiverParameter != null) {
|
if (value.descriptor.dispatchReceiverParameter != null) {
|
||||||
val thisPtr = evaluateExpression(value.receiver!!)
|
val thisPtr = evaluateExpression(value.receiver!!)
|
||||||
functionGenerationContext.storeAnyGlobal(valueToAssign, fieldPtrOfClass(thisPtr, value.descriptor))
|
functionGenerationContext.storeAny(valueToAssign, fieldPtrOfClass(thisPtr, value.descriptor))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert (value.receiver == null)
|
assert (value.receiver == null)
|
||||||
val globalValue = context.llvmDeclarations.forStaticField(value.descriptor).storage
|
val globalValue = context.llvmDeclarations.forStaticField(value.descriptor).storage
|
||||||
functionGenerationContext.storeAnyGlobal(valueToAssign, globalValue)
|
functionGenerationContext.storeAny(valueToAssign, globalValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (value.type.isUnit())
|
assert (value.type.isUnit())
|
||||||
@@ -1411,12 +1407,11 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
fun getFileEntry(sourceFileName: String): SourceManager.FileEntry {
|
fun getFileEntry(sourceFileName: String): SourceManager.FileEntry =
|
||||||
// We must cache file entries, otherwise we reparse same file many times.
|
// We must cache file entries, otherwise we reparse same file many times.
|
||||||
return context.fileEntryCache.getOrPut(sourceFileName) {
|
context.fileEntryCache.getOrPut(sourceFileName) {
|
||||||
NaiveSourceBasedFileEntryImpl(sourceFileName)
|
NaiveSourceBasedFileEntryImpl(sourceFileName)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlockImpl) :
|
private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlockImpl) :
|
||||||
FileScope(IrFileImpl(getFileEntry(returnableBlock.sourceFileName))) {
|
FileScope(IrFileImpl(getFileEntry(returnableBlock.sourceFileName))) {
|
||||||
@@ -2336,7 +2331,8 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun delegatingConstructorCall(descriptor: ClassConstructorDescriptor, args: List<LLVMValueRef>): LLVMValueRef {
|
private fun delegatingConstructorCall(
|
||||||
|
descriptor: ClassConstructorDescriptor, args: List<LLVMValueRef>): LLVMValueRef {
|
||||||
|
|
||||||
val constructedClass = functionGenerationContext.constructedClass!!
|
val constructedClass = functionGenerationContext.constructedClass!!
|
||||||
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisAsReceiverParameter)
|
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisAsReceiverParameter)
|
||||||
@@ -2359,7 +2355,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun appendLlvmUsed(args: List<LLVMValueRef>) {
|
private fun appendLlvmUsed(args: List<LLVMValueRef>) {
|
||||||
if (args.isEmpty()) return
|
if (args.isEmpty()) return
|
||||||
|
|
||||||
memScoped {
|
memScoped {
|
||||||
@@ -2374,7 +2370,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun entryPointSelector(entryPoint: LLVMValueRef,
|
private fun entryPointSelector(entryPoint: LLVMValueRef,
|
||||||
entryPointType: LLVMTypeRef, selectorName: String): LLVMValueRef {
|
entryPointType: LLVMTypeRef, selectorName: String): LLVMValueRef {
|
||||||
|
|
||||||
assert(LLVMCountParams(entryPoint) == 1)
|
assert(LLVMCountParams(entryPoint) == 1)
|
||||||
@@ -2395,7 +2391,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun appendEntryPointSelector(descriptor: FunctionDescriptor?) {
|
private fun appendEntryPointSelector(descriptor: FunctionDescriptor?) {
|
||||||
if (descriptor == null) return
|
if (descriptor == null) return
|
||||||
|
|
||||||
val entryPoint = codegen.llvmFunction(descriptor)
|
val entryPoint = codegen.llvmFunction(descriptor)
|
||||||
|
|||||||
+4
-4
@@ -34,7 +34,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
|
|
||||||
inner class SlotRecord(val address: LLVMValueRef, val refSlot: Boolean, val isVar: Boolean) : Record {
|
inner class SlotRecord(val address: LLVMValueRef, val refSlot: Boolean, val isVar: Boolean) : Record {
|
||||||
override fun load() : LLVMValueRef = functionGenerationContext.loadSlot(address, isVar)
|
override fun load() : LLVMValueRef = functionGenerationContext.loadSlot(address, isVar)
|
||||||
override fun store(value: LLVMValueRef) = functionGenerationContext.storeAnyLocal(value, address)
|
override fun store(value: LLVMValueRef) = functionGenerationContext.storeAny(value, address)
|
||||||
override fun address() : LLVMValueRef = this.address
|
override fun address() : LLVMValueRef = this.address
|
||||||
override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}"
|
override fun toString() = (if (refSlot) "refslot" else "slot") + " for ${address}"
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
val type = functionGenerationContext.getLLVMType(descriptor.type)
|
val type = functionGenerationContext.getLLVMType(descriptor.type)
|
||||||
val slot = functionGenerationContext.alloca(type, descriptor.name.asString(), variableLocation)
|
val slot = functionGenerationContext.alloca(type, descriptor.name.asString(), variableLocation)
|
||||||
if (value != null)
|
if (value != null)
|
||||||
functionGenerationContext.storeAnyLocal(value, slot)
|
functionGenerationContext.storeAny(value, slot)
|
||||||
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), isVar))
|
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), isVar))
|
||||||
contextVariablesToIndex[descriptor] = index
|
contextVariablesToIndex[descriptor] = index
|
||||||
return index
|
return index
|
||||||
@@ -113,7 +113,7 @@ internal class VariableManager(val functionGenerationContext: FunctionGeneration
|
|||||||
val index = variables.size
|
val index = variables.size
|
||||||
val slot = functionGenerationContext.alloca(type, variableLocation = null)
|
val slot = functionGenerationContext.alloca(type, variableLocation = null)
|
||||||
if (value != null)
|
if (value != null)
|
||||||
functionGenerationContext.storeAnyLocal(value, slot)
|
functionGenerationContext.storeAny(value, slot)
|
||||||
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), true))
|
variables.add(SlotRecord(slot, functionGenerationContext.isObjectType(type), true))
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
@@ -174,4 +174,4 @@ internal fun debugInfoParameterLocation(builder: DIBuilderRef?,
|
|||||||
type = diType)
|
type = diType)
|
||||||
|
|
||||||
return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line)
|
return VariableDebugLocation(localVariable = variableDeclaration!!, location = location, file = file, line = line)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ public final class String : Comparable<String>, CharSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: in big Kotlin this operations are in kotlin.kotlin_builtins.
|
// TODO: in big Kotlin this operations are in kotlin.kotlin_builtins.
|
||||||
private val kNullString = "null"
|
private fun nullString() = "null"
|
||||||
|
|
||||||
public operator fun kotlin.String?.plus(other: kotlin.Any?): kotlin.String =
|
public operator fun kotlin.String?.plus(other: kotlin.Any?): kotlin.String =
|
||||||
(this?.toString() ?: kNullString).plus(other?.toString() ?: kNullString)
|
(this?.toString() ?: nullString()).plus(other?.toString() ?: nullString())
|
||||||
|
|
||||||
|
|
||||||
public fun Any?.toString() = this?.toString() ?: kNullString
|
public fun Any?.toString() = this?.toString() ?: nullString()
|
||||||
Reference in New Issue
Block a user