From 390edc146da29f95df3d95a5e681d258c670966f Mon Sep 17 00:00:00 2001 From: Vasily Levchenko Date: Mon, 10 Oct 2016 23:12:25 +0300 Subject: [PATCH 1/2] interprocedural call implementation --- .../backend/native/llvm/CodeGenerator.kt | 7 +++++ .../kotlin/backend/native/llvm/IrToBitcode.kt | 31 +++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/CodeGenerator.kt index 3ee834aff69..b7d7fdf4834 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/native/llvm/CodeGenerator.kt @@ -1,5 +1,7 @@ package org.jetbrains.kotlin.backend.native.llvm + +import kotlin_native.interop.* import llvm.* import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.declarations.IrFunction @@ -55,6 +57,11 @@ internal class CodeGenerator(override val context:Context) : ContextUtils { fun alloca(type: KotlinType, varName: String):LLVMOpaqueValue = LLVMBuildAlloca(context.llvmBuilder, getLLVMType(type), varName)!! fun load(value:LLVMOpaqueValue, varName: String):LLVMOpaqueValue = LLVMBuildLoad(context.llvmBuilder, value, varName)!! fun store(value:LLVMOpaqueValue, ptr:LLVMOpaqueValue):LLVMOpaqueValue = LLVMBuildStore(context.llvmBuilder, value, ptr)!! + fun call(descriptor: FunctionDescriptor, args: MutableList, result: String): LLVMOpaqueValue? { + val rargs = malloc(array[args.size](Ref to LLVMOpaqueValue)) + args.forEachIndexed { i, llvmOpaqueValue -> rargs[i].value = args[i]} + return LLVMBuildCall(context.llvmBuilder, descriptor.llvmFunction.getLlvmValue(), rargs[0], args.size, result) + } } 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 a5989247ff0..f55dc8134bc 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 @@ -1,6 +1,7 @@ package org.jetbrains.kotlin.backend.native.llvm import llvm.* +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction @@ -10,6 +11,7 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid + fun emitLLVM(module: IrModuleFragment, runtimeFile: String, outFile: String) { val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose val runtime = Runtime(runtimeFile) // TODO: dispose @@ -76,13 +78,38 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid args.add(evaluateExpression(tmp, element as IrExpression)) } }) - when (value!!.origin) { + when (value.descriptor) { + is FunctionDescriptor -> return evaluateFunctionCall(tmpVariableName, value, args) + else -> { + TODO() + } + } + + TODO() + } + + private fun evaluateSimpleFunctionCall(tmpVariableName: String, value: IrCall, args: MutableList): LLVMOpaqueValue? { + return generator.call(value.descriptor as org.jetbrains.kotlin.descriptors.FunctionDescriptor, args, tmpVariableName) + } + + + private fun evaluateFunctionCall(tmpVariableName: String, callee: IrCall, args: MutableList): LLVMOpaqueValue? { + val descriptor:FunctionDescriptor = callee.descriptor as FunctionDescriptor + when { + descriptor.isOperator -> return evaluateOperatorCall(tmpVariableName, callee, args) + else -> { + return evaluateSimpleFunctionCall(tmpVariableName, callee, args) + } + } + } + + private fun evaluateOperatorCall(tmpVariableName: String, callee: IrCall, args: MutableList): LLVMOpaqueValue { + when (callee!!.origin) { IrStatementOrigin.PLUS -> return generator.plus(args[0]!!, args[1]!!, tmpVariableName) else -> { TODO() } } - TODO() } override fun visitVariable(declaration: IrVariable) { From 97e31820aeaaee57f7d7084ec27d87b500de5c88 Mon Sep 17 00:00:00 2001 From: Vasily Levchenko Date: Mon, 10 Oct 2016 23:13:28 +0300 Subject: [PATCH 2/2] inter-procedural call test --- backend.native/tests/Makefile | 3 ++- .../tests/codegen/function/sum_foo_bar-test.c | 10 ++++++++++ backend.native/tests/codegen/function/sum_foo_bar.kt | 4 ++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 backend.native/tests/codegen/function/sum_foo_bar-test.c create mode 100644 backend.native/tests/codegen/function/sum_foo_bar.kt diff --git a/backend.native/tests/Makefile b/backend.native/tests/Makefile index 33df8c2c53f..eeb38de1d92 100644 --- a/backend.native/tests/Makefile +++ b/backend.native/tests/Makefile @@ -1,4 +1,5 @@ -TESTS := sum +TESTS := sum \ + sum_foo_bar BIN_TESTS=$(foreach t, ${TESTS},${t}_test) diff --git a/backend.native/tests/codegen/function/sum_foo_bar-test.c b/backend.native/tests/codegen/function/sum_foo_bar-test.c new file mode 100644 index 00000000000..325c26b35fb --- /dev/null +++ b/backend.native/tests/codegen/function/sum_foo_bar-test.c @@ -0,0 +1,10 @@ +extern void *resolve_symbol(const char*); + +int +run_test() { + int (*sum)(int, int) = resolve_symbol("kfun:sumFooBar"); + + if (sum(2, 3) != 5) return 1; + + return 0; +} diff --git a/backend.native/tests/codegen/function/sum_foo_bar.kt b/backend.native/tests/codegen/function/sum_foo_bar.kt new file mode 100644 index 00000000000..ce1a0929736 --- /dev/null +++ b/backend.native/tests/codegen/function/sum_foo_bar.kt @@ -0,0 +1,4 @@ +fun foo(a:Int):Int = a +fun bar(a:Int):Int = a + +fun sumFooBar(a:Int, b:Int):Int = foo(a) + bar(b) \ No newline at end of file