translator: add plain function calls, C function support
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
+3
@@ -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*"
|
||||||
}
|
}
|
||||||
+9
-12
@@ -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"
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user