From bab2b8bc3f223d3090107be42c85adc54bb1bf58 Mon Sep 17 00:00:00 2001 From: Konstantin Anisimov Date: Mon, 5 Dec 2016 14:13:14 +0300 Subject: [PATCH] CODEGEN: get_object implementation --- .../backend/konan/llvm/CodeGenerator.kt | 6 ++++ .../kotlin/backend/konan/llvm/Context.kt | 1 + .../kotlin/backend/konan/llvm/IrToBitcode.kt | 34 ++++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) 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 eff41a59725..9e3acbc0033 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 @@ -60,11 +60,15 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { fun icmpLe(arg0: LLVMValueRef, arg1: LLVMValueRef, result: String): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLE, arg0, arg1, result)!! fun icmpNe(arg0: LLVMValueRef, arg1: LLVMValueRef, result: String): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntNE, arg0, arg1, result)!! + fun ucmpGt(arg0: LLVMValueRef, arg1: LLVMValueRef, result: String): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntUGT, arg0, arg1, result)!! + /* floating-point comparisons */ fun fcmpEq(arg0: LLVMValueRef, arg1: LLVMValueRef, result: String): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOEQ, arg0, arg1, result)!! fun bitcast(type: LLVMTypeRef?, value: LLVMValueRef, result: String) = LLVMBuildBitCast(builder, value, type, result)!! + fun intToPtr(imm: LLVMValueRef?, DestTy: LLVMTypeRef, Name: String) = LLVMBuildIntToPtr(builder, imm, DestTy, Name) + fun alloca(type: KotlinType, varName: String): LLVMValueRef = alloca( getLLVMType(type), varName) fun alloca(type: LLVMTypeRef?, varName: String): LLVMValueRef { appendingTo(prologueBb!!) { @@ -256,6 +260,8 @@ internal class CodeGenerator(override val context: Context) : ContextUtils { code() } + fun llvmFunction(function: FunctionDescriptor): LLVMValueRef = function.llvmFunction + } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt index 851aefd423b..c87338d09ad 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/Context.kt @@ -23,6 +23,7 @@ internal class Context(val irModule: IrModuleFragment, val runtime: Runtime, val private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule) val allocInstanceFunction = importRtFunction("AllocInstance") + val initInstanceFunction = importRtFunction("InitInstance") val allocArrayFunction = importRtFunction("AllocArrayInstance") val setArrayFunction = importRtFunction("Kotlin_Array_set") val lookupFieldOffset = importRtFunction("LookupFieldOffset") 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 054aa928131..aca2e09f801 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 @@ -279,7 +279,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid if (!skipConstructorBodyGeneration(constructorDeclaration)) constructorDeclaration.acceptChildrenVoid(this) - if (constructorDescriptor.isPrimary && !DescriptorUtils.isCompanionObject(constructorDescriptor.constructedClass)) { + if (constructorDescriptor.isPrimary) { val irOfCurrentClass = context.moduleIndex.classes[classDescriptor.classId] irOfCurrentClass!!.acceptChildrenVoid(object : IrElementVisitorVoid { override fun visitElement(element: IrElement) { @@ -602,6 +602,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid is IrVararg -> return evaluateVararg (tmpVariableName, value) is IrBreak -> return evaluateBreak ( value) is IrContinue -> return evaluateContinue ( value) + is IrGetObjectValue -> return evaluateGetObjectValue (tmpVariableName, value) null -> return null else -> { TODO("${ir2string(value)}") @@ -609,6 +610,37 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid } } + //-------------------------------------------------------------------------// + + private fun evaluateGetObjectValue(tmpVariableName: String, value: IrGetObjectValue): LLVMValueRef? { + val objName = value.descriptor.fqNameSafe.asString() + var objectPtr = LLVMGetNamedGlobal(context.llvmModule, objName) + if (objectPtr == null) { + objectPtr = LLVMAddGlobal(context.llvmModule, codegen.getLLVMType(value.type), objName) + LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr) + } + + val bbInit = codegen.basicBlock("label_init") + val bbExit = codegen.basicBlock("label_continue") + val onePtr = codegen.intToPtr(kImmInt64One, codegen.kObjHeaderPtr, codegen.newVar()) + val objectVal = codegen.load(objectPtr!!, codegen.newVar()) + val condition = codegen.ucmpGt(objectVal, onePtr!!, codegen.newVar()) + codegen.condBr(condition, bbExit, bbInit) + + codegen.positionAtEnd(bbInit) + val typeInfo = codegen.typeInfoValue(value.descriptor) + val allocHint = Int32(1).llvm + val initFunction = value.descriptor.constructors.first { it.valueParameters.size == 0 } + val ctor = codegen.llvmFunction(initFunction) + val args = listOf(objectPtr, typeInfo, allocHint, ctor) + currentCodeContext.genCall(context.initInstanceFunction, args, codegen.newVar()) + codegen.br(bbExit) + + codegen.positionAtEnd(bbExit) + return objectVal + } + //-------------------------------------------------------------------------// + private fun evaluateExpressionAndJump(expression: IrExpression, destination: ContinuationBlock) { val result = evaluateExpression("res", expression)