translator: add plain function calls, C function support

This commit is contained in:
e5l
2016-07-11 18:01:10 +03:00
parent 83a41238e2
commit 33ff4f720a
9 changed files with 71 additions and 39 deletions
@@ -30,20 +30,42 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
} }
fun generate() { fun generate() {
generateDeclaration(function) if (generateDeclaration(function)) {
return
}
codeBuilder.addStartExpression() codeBuilder.addStartExpression()
expressionWalker(function.bodyExpression) expressionWalker(function.bodyExpression)
if (returnType == "void") {
codeBuilder.addVoidReturn()
}
codeBuilder.addEndExpression() codeBuilder.addEndExpression()
} }
private fun generateDeclaration(function: KtNamedFunction) { private fun generateDeclaration(function: KtNamedFunction): Boolean {
codeBuilder.addLLVMCode(LLVMDescriptorGenerate(function.fqName.toString(), args, returnType)) var external = false
var keyword = function.firstChild
while (keyword != null) {
if (keyword.text == "external") {
external = true
break
}
keyword = keyword.getNextSiblingIgnoringWhitespaceAndComments()
}
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(function.fqName.toString(), args, returnType, external))
return external
} }
private fun expressionWalker(expr: PsiElement?) { private fun expressionWalker(expr: PsiElement?) {
when (expr) { when (expr) {
is KtBlockExpression -> expressionWalker(expr.firstChild) is KtBlockExpression -> expressionWalker(expr.firstChild)
is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement) is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement)
is KtCallExpression -> codeBuilder.addLLVMCode(evaluateCallExpression(expr).toString())
is PsiElement -> evaluateExpression(expr.firstChild) is PsiElement -> evaluateExpression(expr.firstChild)
null -> return null -> return
else -> UnsupportedOperationException() else -> UnsupportedOperationException()
@@ -0,0 +1,3 @@
package org.kotlinnative.translator.exceptions
class UnimplementedException() : Exception()
@@ -56,6 +56,10 @@ class LLVMBuilder {
llvmCode.appendln("ret i32 $llvmVariable") llvmCode.appendln("ret i32 $llvmVariable")
} }
fun addVoidReturn() {
llvmCode.appendln("ret void")
}
override fun toString(): String { override fun toString(): String {
return llvmCode.toString() return llvmCode.toString()
} }
@@ -4,8 +4,6 @@ import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMVariable(val label: String, val type: LLVMType? = null) : LLVMNode() { class LLVMVariable(val label: String, val type: LLVMType? = null) : LLVMNode() {
override fun toString(): String { override fun toString(): String = label
return label
}
} }
@@ -2,10 +2,14 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.utils.FunctionArgument import org.kotlinnative.translator.utils.FunctionArgument
fun LLVMDescriptorGenerate(name: String, argTypes: List<FunctionArgument>?, returnType: String) = fun LLVMFunctionDescriptor(name: String, argTypes: List<FunctionArgument>?, returnType: String, declare: Boolean = false) =
"define $returnType @$name(${argTypes?.mapIndexed { i: Int, s: FunctionArgument -> "${s.type} %tmp.${s.name}" }?.joinToString() ?: "" })" "${ if (declare) "declare" else "define"} $returnType @$name(${
argTypes?.mapIndexed { i: Int, s: FunctionArgument -> "${s.type} %tmp.${s.name}"
}?.joinToString() ?: "" })"
fun LLVMMapStandardType(type: String) = when(type) { fun LLVMMapStandardType(type: String) = when(type) {
"Int" -> "i32" "Int" -> "i32"
"Unit" -> "void"
else -> "%$type*" else -> "%$type*"
} }
@@ -6,20 +6,17 @@ import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMDoubleType() : LLVMType() { class LLVMDoubleType() : LLVMType() {
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression { //TODO switch by types: int + double = int
//TODO switch by types: int + double = int override fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
return LLVMExpression(LLVMDoubleType(), "fsub double i32 $firstOp, $secondOp") LLVMExpression(LLVMDoubleType(), "fsub double i32 $firstOp, $secondOp")
}
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression { //TODO switch by types: int + double = int
//TODO switch by types: int + double = int override fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
return LLVMExpression(LLVMDoubleType(), "fmul double i32 $firstOp, $secondOp") LLVMExpression(LLVMDoubleType(), "fmul double i32 $firstOp, $secondOp")
}
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression { //TODO switch by types: int + double = int
//TODO switch by types: int + double = int override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
return LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp") LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp")
}
override fun toString(): String { override fun toString(): String {
return "double" return "double"
@@ -6,23 +6,18 @@ import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMIntType() : LLVMType() { class LLVMIntType() : LLVMType() {
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression { //TODO switch by types: int + double = int
//TODO switch by types: int + double = int override fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
return LLVMExpression(LLVMIntType(), "sub nsw i32 $firstOp, $secondOp") LLVMExpression(LLVMIntType(), "sub nsw i32 $firstOp, $secondOp")
}
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression { //TODO switch by types: int + double = int
//TODO switch by types: int + double = int override fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
return LLVMExpression(LLVMIntType(), "mul nsw i32 $firstOp, $secondOp") LLVMExpression(LLVMIntType(), "mul nsw i32 $firstOp, $secondOp")
}
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression { //TODO switch by types: int + double = int
//TODO switch by types: int + double = int override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
return LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp") LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp")
}
override fun toString(): String { override fun toString() = "i32"
return "i32"
}
} }
@@ -1,17 +1,19 @@
package org.kotlinnative.translator.llvm.types; package org.kotlinnative.translator.llvm.types;
import org.kotlinnative.translator.exceptions.TranslationException import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.exceptions.UnimplementedException
import org.kotlinnative.translator.llvm.LLVMExpression import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMVariable import org.kotlinnative.translator.llvm.LLVMVariable
abstract class LLVMType() { abstract class LLVMType() {
abstract fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression; open fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
abstract fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression; open fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
abstract fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression; open fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
} }
fun parseLLVMType(type: String): LLVMType = when(type) { fun parseLLVMType(type: String): LLVMType = when (type) {
"i32" -> LLVMIntType() "i32" -> LLVMIntType()
"Unit" -> LLVMVoidType()
else -> throw TranslationException() else -> throw TranslationException()
} }
@@ -0,0 +1,7 @@
package org.kotlinnative.translator.llvm.types
class LLVMVoidType() : LLVMType() {
override fun toString(): String = "void"
}