From 8de943bb8a3effb1cea3406e29e06d5c545a7de2 Mon Sep 17 00:00:00 2001 From: Vasily Levchenko Date: Wed, 2 Nov 2016 11:34:06 +0300 Subject: [PATCH 1/2] ir-enchancement:support operations with variables and block processing --- .../kotlin/backend/native/llvm/IrToBitcode.kt | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/IrToBitcode.kt index 80aeca49af9..2c48f301ba8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/IrToBitcode.kt @@ -9,7 +9,10 @@ import org.jetbrains.kotlin.descriptors.impl.LazyClassReceiverParameterDescripto import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.* import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrBinaryPrimitiveImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -126,7 +129,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid generator.store(value!!, generator.variable(expression.descriptor.name.asString())!!) } - private fun evaluateExpression(tmpVariableName: String, value: IrExpression?): LLVMOpaqueValue? { + private fun evaluateExpression(tmpVariableName: String, value: IrElement?): LLVMOpaqueValue? { when (value) { is IrCall -> return evaluateCall(tmpVariableName, value) is IrGetValue -> { @@ -147,6 +150,17 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid } } + is IrSetVariable -> { + val ret = evaluateExpression(generator.tmpVariable(), value.value) + return generator.store(ret!!, generator.variable(value.descriptor.name.asString())!!) + } + is IrVariable -> { + val ret = evaluateExpression(generator.tmpVariable(), value.initializer) + val variableName = value.descriptor.name.asString() + val variable = generator.alloca(LLVMTypeOf(ret), variableName) + generator.registerVariable(variableName, ret!!) + return generator.store(ret, variable) + } is IrGetField -> { if (value.descriptor.dispatchReceiverParameter != null) { val thisPtr = generator.load(generator.thisVariable(), generator.tmpVariable()) @@ -170,6 +184,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid IrConstKind.Double -> TODO() } + is IrBlock -> { + + value.statements.dropLast(1).forEach { + evaluateExpression(generator.tmpVariable(), it) + } + return evaluateExpression(generator.tmpVariable(), value.statements.lastOrNull()) + } + null -> return null else -> { TODO() @@ -193,7 +215,56 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid TODO() } } + } + //-------------------------------------------------------------------------// + + private fun evaluateGetValue(tmpVariableName: String, value: IrGetValue): LLVMOpaqueValue { + when (value.descriptor) { + is LocalVariableDescriptor, + is ValueParameterDescriptor, + is IrTemporaryVariableDescriptor -> { + val variable = generator.variable(value.descriptor.name.asString()) + return generator.load(variable!!, tmpVariableName) + } + is LazyClassReceiverParameterDescriptor -> { + if (value.descriptor.name.asString() == "") { + return generator.load(generator.thisVariable(), tmpVariableName) + } + TODO() + } + else -> { + TODO() + } + } + } + + //-------------------------------------------------------------------------// + + private fun evaluateSetVariable(value: IrSetVariable): LLVMOpaqueValue { + val ret = evaluateExpression(generator.tmpVariable(), value.value) + return generator.store(ret!!, generator.variable(value.descriptor.name.asString())!!) + } + + //-------------------------------------------------------------------------// + + private fun evaluateVariable(value: IrVariable): LLVMOpaqueValue { + val ret = evaluateExpression(generator.tmpVariable(), value.initializer) + val variableName = value.descriptor.name.asString() + val variable = generator.alloca(LLVMTypeOf(ret), variableName) + generator.registerVariable(variableName, variable) + return generator.store(ret!!, variable) + } + + //-------------------------------------------------------------------------// + + private fun evaluateGetField(value: IrGetField): LLVMOpaqueValue { + if (value.descriptor.dispatchReceiverParameter != null) { + val thisPtr = generator.load(generator.thisVariable(), generator.tmpVariable()) + val typedPtr = generator.bitcast(pointerType(generator.classType(generator.currentClass!!)), thisPtr, generator.tmpVariable()) + val fieldPtr = LLVMBuildStructGEP(generator.context.llvmBuilder, typedPtr, generator.indexInClass(value.descriptor), generator.tmpVariable()) + return generator.load(fieldPtr!!, generator.tmpVariable()) + } TODO() } From 4078e4004c0b13190da3c234860d3e4304dda378 Mon Sep 17 00:00:00 2001 From: Konstantin Anisimov Date: Thu, 3 Nov 2016 16:13:46 +0300 Subject: [PATCH 2/2] tests for local variables --- backend.native/tests/build.gradle | 4 ++++ .../tests/codegen/basics/local_variable-test.c | 10 ++++++++++ backend.native/tests/codegen/basics/local_variable.kt | 5 +++++ 3 files changed, 19 insertions(+) create mode 100644 backend.native/tests/codegen/basics/local_variable-test.c create mode 100644 backend.native/tests/codegen/basics/local_variable.kt diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index c9fbfe1e4c8..61ff9fa4583 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -153,6 +153,10 @@ task sum_3const(type: UnitKonanTest) { source = "codegen/function/sum_3const.kt" } +task local_variable(type: UnitKonanTest) { + source = "codegen/basics/local_variable.kt" +} + //task hello0(type: RunKonanTest) { // source = "runtime/basic/hello0.kt" //} diff --git a/backend.native/tests/codegen/basics/local_variable-test.c b/backend.native/tests/codegen/basics/local_variable-test.c new file mode 100644 index 00000000000..9d0df19af46 --- /dev/null +++ b/backend.native/tests/codegen/basics/local_variable-test.c @@ -0,0 +1,10 @@ +extern void *resolve_symbol(const char*); + +int +run_test() { + int (*local_variable)(int) = resolve_symbol("kfun:local_variable"); + + if (local_variable(3) != 14) return 1; + + return 0; +} diff --git a/backend.native/tests/codegen/basics/local_variable.kt b/backend.native/tests/codegen/basics/local_variable.kt new file mode 100644 index 00000000000..dcdb109be7a --- /dev/null +++ b/backend.native/tests/codegen/basics/local_variable.kt @@ -0,0 +1,5 @@ +fun local_variable(a: Int) : Int { + var b = 0 + b = a + 11 + return b +} \ No newline at end of file