Merge pull request #1 from JetBrains/rr/translation-prototype
naive sum translation
This commit is contained in:
+67
@@ -0,0 +1,67 @@
|
|||||||
|
package org.jetbrains.kotlin.backend.native.llvm
|
||||||
|
|
||||||
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Created by minamoto on 07/10/2016.
|
||||||
|
*/
|
||||||
|
|
||||||
|
internal class CodeGenerator(override val context:Context) : ContextUtils {
|
||||||
|
var currentFunction:FunctionDescriptor? = null
|
||||||
|
|
||||||
|
fun function(declaration: IrFunction) {
|
||||||
|
index = 0
|
||||||
|
currentFunction = declaration.descriptor
|
||||||
|
val fn = LLVMAddFunction(context.llvmModule, declaration.descriptor.symbolName, getLlvmFunctionType(declaration.descriptor))
|
||||||
|
val block = LLVMAppendBasicBlock(fn, "entry")
|
||||||
|
LLVMPositionBuilderAtEnd(context.llvmBuilder, block)
|
||||||
|
function2variables.put(declaration.descriptor, mutableMapOf())
|
||||||
|
declaration.descriptor.valueParameters.forEachIndexed { i, descriptor ->
|
||||||
|
val name = descriptor.name.asString()
|
||||||
|
val type = descriptor.type
|
||||||
|
val v = alloca(type, name)
|
||||||
|
store(LLVMGetParam(fn, i)!!, v)
|
||||||
|
currentFunction!!.registerVariable(name, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tmpVariable():String = currentFunction!!.tmpVariable()
|
||||||
|
|
||||||
|
val variablesGlobal = mapOf<String, LLVMOpaqueValue?>()
|
||||||
|
fun variable(varName:String):LLVMOpaqueValue? = currentFunction!!.variable(varName)
|
||||||
|
|
||||||
|
fun FunctionDescriptor.param(num:Int):LLVMOpaqueValue? = LLVMGetParam(llvmFunction.getLlvmValue(), num)
|
||||||
|
|
||||||
|
var index:Int = 0
|
||||||
|
private var FunctionDescriptor.tmpVariableIndex: Int
|
||||||
|
get() = index
|
||||||
|
set(i:Int){ index = i}
|
||||||
|
|
||||||
|
fun FunctionDescriptor.tmpVariable():String = "tmp${tmpVariableIndex++}"
|
||||||
|
|
||||||
|
fun registerVariable(varName: String, value:LLVMOpaqueValue) = currentFunction!!.registerVariable(varName, value)
|
||||||
|
|
||||||
|
val function2variables = mutableMapOf<FunctionDescriptor, MutableMap<String, LLVMOpaqueValue?>>()
|
||||||
|
|
||||||
|
|
||||||
|
val FunctionDescriptor.variables: MutableMap<String, LLVMOpaqueValue?>
|
||||||
|
get() = this@CodeGenerator.function2variables[this]!!
|
||||||
|
|
||||||
|
|
||||||
|
fun FunctionDescriptor.registerVariable(varName: String, value:LLVMOpaqueValue?) = variables.put(varName, value)
|
||||||
|
private fun FunctionDescriptor.variable(varName: String): LLVMOpaqueValue? = variables[varName]
|
||||||
|
|
||||||
|
fun plus(arg0:LLVMOpaqueValue, arg1:LLVMOpaqueValue, result:String):LLVMOpaqueValue = LLVMBuildAdd(context.llvmBuilder, arg0, arg1, result)!!
|
||||||
|
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)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+72
-1
@@ -3,7 +3,10 @@ package org.jetbrains.kotlin.backend.native.llvm
|
|||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
|
|
||||||
@@ -16,6 +19,7 @@ fun emitLLVM(module: IrModuleFragment, runtimeFile: String, outFile: String) {
|
|||||||
val context = Context(module, runtime, llvmModule) // TODO: dispose
|
val context = Context(module, runtime, llvmModule) // TODO: dispose
|
||||||
|
|
||||||
module.accept(RTTIGeneratorVisitor(context), null)
|
module.accept(RTTIGeneratorVisitor(context), null)
|
||||||
|
module.accept(CodeGeneratorVisitor(context), null)
|
||||||
LLVMWriteBitcodeToFile(llvmModule, outFile)
|
LLVMWriteBitcodeToFile(llvmModule, outFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,4 +35,71 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
|
|||||||
generator.generate(declaration.descriptor)
|
generator.generate(declaration.descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: split CodeGeneratorVisitor on Visitor and Generator :)
|
||||||
|
*/
|
||||||
|
internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid {
|
||||||
|
val generator = CodeGenerator(context)
|
||||||
|
override fun visitFunction(declaration: IrFunction) {
|
||||||
|
generator.function(declaration)
|
||||||
|
declaration.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSetVariable(expression: IrSetVariable) {
|
||||||
|
val value = evaluateExpression(generator.tmpVariable(), expression.value)
|
||||||
|
generator.store(value!!, generator.variable(expression.descriptor.name.asString())!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun evaluateExpression(tmpVariableName: String, value: IrExpression?): LLVMOpaqueValue? {
|
||||||
|
when (value) {
|
||||||
|
is IrCall -> return evaluateCall(tmpVariableName, value)
|
||||||
|
is IrGetValue -> return generator.load(generator.variable(value.descriptor.name.asString())!!, tmpVariableName)
|
||||||
|
null -> return null
|
||||||
|
else -> {
|
||||||
|
TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun evaluateCall(tmpVariableName: String, value: IrCall?): LLVMOpaqueValue? {
|
||||||
|
/* TODO: should we count on receiver?
|
||||||
|
* val tmp = tmpVar()
|
||||||
|
* val lhs = evaluateExpression(tmp, value.dispatchReceiver!!)
|
||||||
|
*/
|
||||||
|
val args = mutableListOf<LLVMOpaqueValue?>()
|
||||||
|
value!!.acceptChildrenVoid(object:IrElementVisitorVoid{
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
val tmp = generator.tmpVariable()
|
||||||
|
args.add(evaluateExpression(tmp, element as IrExpression))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
when (value!!.origin) {
|
||||||
|
IrStatementOrigin.PLUS -> return generator.plus(args[0]!!, args[1]!!, tmpVariableName)
|
||||||
|
else -> {
|
||||||
|
TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TODO()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVariable(declaration: IrVariable) {
|
||||||
|
val variableName = declaration.descriptor.name.asString()
|
||||||
|
val variableType = declaration.descriptor.type
|
||||||
|
generator.registerVariable(variableName, generator.alloca(variableType, variableName))
|
||||||
|
|
||||||
|
evaluateExpression(variableName, declaration.initializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturn(expression: IrReturn) {
|
||||||
|
val tmpVarName = generator.tmpVariable()
|
||||||
|
val value:LLVMOpaqueValue?
|
||||||
|
value = evaluateExpression(tmpVarName, expression.value)
|
||||||
|
LLVMBuildRet(context.llvmBuilder, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
TESTS := sum
|
||||||
|
|
||||||
|
BIN_TESTS=$(foreach t, ${TESTS},${t}_test)
|
||||||
|
|
||||||
|
VPATH=codegen/function
|
||||||
|
|
||||||
|
LLC=llc-mp-3.8
|
||||||
|
CC=clang-mp-3.8
|
||||||
|
JAVA=java
|
||||||
|
|
||||||
|
TOP=../..
|
||||||
|
RUNTIME=${TOP}/runtime
|
||||||
|
BACKEND=${TOP}/backend.native
|
||||||
|
BACKEND_CLASSES=${TOP}/backend.native/build/classes
|
||||||
|
KOTLIN_DIST=${BACKEND}/kotlin-ir/dist
|
||||||
|
KOTLIN_NATIVE_CLASSPATH=${BACKEND_CLASSES}/bc_frontend:${BACKEND_CLASSES}/cli_bc:${BACKEND_CLASSES}/compiler:${KOTLIN_DIST}/kotlinc/lib/kotlin-reflect.jar:${KOTLIN_DIST}kotlinc/lib/kotlin-stdlib.jar:${KOTLIN_DIST}/kotlinc/lib/kotlin-compiler.jar:${KOTLIN_DIST}/kotlinc/lib/kotlin-runtime.jar:${TOP}/Interop/Runtime/build/classes/main
|
||||||
|
|
||||||
|
|
||||||
|
define PROTO
|
||||||
|
$(1)_test: main.c $1-test.c $1.S
|
||||||
|
$(CC) -o $$@ $$^
|
||||||
|
|
||||||
|
${1}_run:${1}_test
|
||||||
|
./${1}_test
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(foreach test,${TESTS},$(eval $(call PROTO,$(test))))
|
||||||
|
|
||||||
|
all:${BIN_TESTS}
|
||||||
|
|
||||||
|
run:$(foreach test,${TESTS},${test}_run)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
${RM} *.o *.S *.BCkt ${BIN_TESTS}
|
||||||
|
|
||||||
|
|
||||||
|
%.S:%.BCkt
|
||||||
|
${LLC} -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
|
%.BCkt:%.kt
|
||||||
|
${JAVA} -cp ${KOTLIN_NATIVE_CLASSPATH} -Djava.library.path=${BACKEND}/build/nativelibs org.jetbrains.kotlin.cli.bc.K2NativeKt -output $@ -runtime ${RUNTIME}/build/runtime.bc $<
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
extern void *resolve_symbol(const char*);
|
||||||
|
|
||||||
|
int
|
||||||
|
run_test() {
|
||||||
|
int (*sum)(int, int) = resolve_symbol("kfun:sum");
|
||||||
|
|
||||||
|
if (sum(2, 3) != 5) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
fun sum(a:Int, b:Int) = a + b
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun foo():Int = 1
|
||||||
|
//fun bar():Int = 2
|
||||||
|
//fun sum():Int = foo() + bar()
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fun sum(a:Int, b:Int):Int {
|
||||||
|
var c:Int
|
||||||
|
c = a + b
|
||||||
|
return c
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
/**
|
||||||
|
* > llc-mp-3.8 b.out -o b.S
|
||||||
|
* > /opt/local/libexec/llvm-3.8/bin/clang main.c b.S -o sum-test
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern int run_test();
|
||||||
|
|
||||||
|
void * resolve_symbol(char *name) {
|
||||||
|
/* here we can add here some magic to resolve symbols in kotlin native*/
|
||||||
|
return dlsym(RTLD_SELF, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main() {
|
||||||
|
return run_test();
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
int foo() { return 1; }
|
||||||
|
int bar() {return 2;}
|
||||||
|
int sum() {return foo() + bar();}
|
||||||
Reference in New Issue
Block a user