From f986a0cb101d724c28b820947e9157061b61f6bf Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Tue, 9 Jan 2018 14:21:38 +0300 Subject: [PATCH] Move singleton support from IR visitor to code generator --- .../backend/konan/llvm/CodeGenerator.kt | 64 +++++++++++++++ .../kotlin/backend/konan/llvm/ContextUtils.kt | 1 + .../kotlin/backend/konan/llvm/IrToBitcode.kt | 77 +++---------------- 3 files changed, 77 insertions(+), 65 deletions(-) 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 b88f56123b5..ee858d32460 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 @@ -21,6 +21,7 @@ import kotlinx.cinterop.* import llvm.* import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.descriptors.isInterface +import org.jetbrains.kotlin.backend.konan.descriptors.isUnit import org.jetbrains.kotlin.backend.konan.descriptors.stdlibModule import org.jetbrains.kotlin.backend.konan.isObjCClass import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor @@ -49,6 +50,32 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { fun functionLlvmValue(descriptor: FunctionDescriptor) = descriptor.llvmFunction fun functionEntryPointAddress(descriptor: FunctionDescriptor) = descriptor.entryPointAddress.llvm fun functionHash(descriptor: FunctionDescriptor): LLVMValueRef = descriptor.functionName.localHash.llvm + + fun getObjectInstanceStorage(descriptor: ClassDescriptor): LLVMValueRef { + assert (!descriptor.isUnit()) + val llvmGlobal = if (!isExternal(descriptor)) { + context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef + } else { + val llvmType = getLLVMType(descriptor.defaultType) + importGlobal( + descriptor.objectInstanceFieldSymbolName, + llvmType, + origin = descriptor.llvmSymbolOrigin, + threadLocal = true + ) + } + context.llvm.objects += llvmGlobal + return llvmGlobal + } + + fun typeInfoForAllocation(constructedClass: ClassDescriptor): LLVMValueRef { + val descriptorForTypeInfo = if (constructedClass.isObjCClass()) { + context.interopBuiltIns.objCPointerHolder + } else { + constructedClass + } + return typeInfoValue(descriptorForTypeInfo) + } } internal sealed class ExceptionHandler { @@ -352,6 +379,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, return call(context.llvm.allocInstanceFunction, listOf(typeInfo), lifetime) } + fun allocInstance(descriptor: ClassDescriptor, lifetime: Lifetime): LLVMValueRef = + allocInstance(codegen.typeInfoForAllocation(descriptor), lifetime) + fun allocArray( typeInfo: LLVMValueRef, count: LLVMValueRef, lifetime: Lifetime): LLVMValueRef { return call(context.llvm.allocArrayFunction, listOf(typeInfo, count), lifetime) @@ -532,6 +562,40 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, return bitcast(functionPtrType, llvmMethod) // Cast method address to the type } + fun getObjectValue( + descriptor: ClassDescriptor, + exceptionHandler: ExceptionHandler, + locationInfo: LocationInfo? + ): LLVMValueRef { + if (descriptor.isUnit()) { + return codegen.theUnitInstanceRef.llvm + } + + val objectPtr = codegen.getObjectInstanceStorage(descriptor) + val bbCurrent = currentBlock + val bbInit = basicBlock("label_init", locationInfo) + val bbExit = basicBlock("label_continue", locationInfo) + val objectVal = loadSlot(objectPtr, false) + val condition = icmpNe(objectVal, codegen.kNullObjHeaderPtr) + condBr(condition, bbExit, bbInit) + + positionAtEnd(bbInit) + val typeInfo = codegen.typeInfoForAllocation(descriptor) + val initFunction = descriptor.constructors.first { it.valueParameters.size == 0 } + val ctor = codegen.llvmFunction(initFunction) + val args = listOf(objectPtr, typeInfo, ctor) + val newValue = call(context.llvm.initInstanceFunction, args, Lifetime.GLOBAL, exceptionHandler) + val bbInitResult = currentBlock + br(bbExit) + + positionAtEnd(bbExit) + val valuePhi = phi(codegen.getLLVMType(descriptor.defaultType)) + addPhiIncoming(valuePhi, + bbCurrent to objectVal, bbInitResult to newValue) + + return valuePhi + } + fun resetDebugLocation() { if (!context.shouldContainDebugInfo()) return if (!currentPositionHolder.isAfterTerminator) 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 759da100dde..6e8405a8092 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 @@ -439,6 +439,7 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) { val compilerUsedGlobals = mutableListOf() val staticInitializers = mutableListOf() val fileInitializers = mutableListOf() + val objects = mutableSetOf() private object lazyRtFunction { operator fun provideDelegate( 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 2bde873ecac..afea1bdb7c9 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 @@ -332,7 +332,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map() - - private fun getObjectInstanceStorage(descriptor: ClassDescriptor): LLVMValueRef { - assert (!descriptor.isUnit()) - val llvmGlobal = if (!codegen.isExternal(descriptor)) { - context.llvmDeclarations.forSingleton(descriptor).instanceFieldRef - } else { - val llvmType = codegen.getLLVMType(descriptor.defaultType) - codegen.importGlobal( - descriptor.objectInstanceFieldSymbolName, - llvmType, - origin = descriptor.llvmSymbolOrigin, - threadLocal = true - ) - } - objects += llvmGlobal - return llvmGlobal - } - - //-------------------------------------------------------------------------// - private fun evaluateSetField(value: IrSetField): LLVMValueRef { context.log{"evaluateSetField : ${ir2string(value)}"} val valueToAssign = evaluateExpression(value.value) @@ -1947,7 +1903,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map): LLVMValueRef { @@ -2064,7 +2011,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map TODO(callee.descriptor.original.toString())