add simpy variable manager, fix some bugs
This commit is contained in:
@@ -3,7 +3,9 @@ package org.kotlinnative.translator
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import org.kotlinnative.translator.utils.FunctionDescriptor
|
||||
import java.util.*
|
||||
|
||||
class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComme
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.llvm.*
|
||||
import org.kotlinnative.translator.llvm.types.LLVMIntType
|
||||
import org.kotlinnative.translator.llvm.types.parseLLVMType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
||||
import org.kotlinnative.translator.utils.FunctionArgument
|
||||
import java.util.*
|
||||
|
||||
@@ -17,8 +18,9 @@ import java.util.*
|
||||
class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) {
|
||||
|
||||
var name = function.fqName.toString()
|
||||
var returnType: String
|
||||
var returnType: LLVMType
|
||||
var args: List<FunctionArgument>?
|
||||
val variableManager = state.variableManager
|
||||
|
||||
init {
|
||||
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)
|
||||
@@ -35,9 +37,10 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
||||
}
|
||||
|
||||
codeBuilder.addStartExpression()
|
||||
generateLoadArguments(function)
|
||||
expressionWalker(function.bodyExpression)
|
||||
|
||||
if (returnType == "void") {
|
||||
if (returnType is LLVMVoidType) {
|
||||
codeBuilder.addVoidReturn()
|
||||
}
|
||||
|
||||
@@ -61,31 +64,47 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
||||
return external
|
||||
}
|
||||
|
||||
private fun expressionWalker(expr: PsiElement?) {
|
||||
private fun generateLoadArguments(function: KtNamedFunction) {
|
||||
args?.forEach {
|
||||
val loadVariable = LLVMVariable("%${it.name}", it.type)
|
||||
codeBuilder.loadVariable(loadVariable)
|
||||
variableManager.addVariable(it.name, loadVariable, 2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun expressionWalker(expr: PsiElement?, scopeDepth: Int = 0) {
|
||||
when (expr) {
|
||||
is KtBlockExpression -> expressionWalker(expr.firstChild)
|
||||
is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement)
|
||||
is KtCallExpression -> codeBuilder.addLLVMCode(evaluateCallExpression(expr).toString())
|
||||
is PsiElement -> evaluateExpression(expr.firstChild)
|
||||
null -> return
|
||||
is KtBlockExpression -> expressionWalker(expr.firstChild, scopeDepth + 1)
|
||||
is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement, scopeDepth)
|
||||
is PsiElement -> evaluateExpression(expr.firstChild, scopeDepth + 1)
|
||||
null -> {
|
||||
variableManager.pullUpwardsLevel(scopeDepth)
|
||||
return
|
||||
}
|
||||
else -> UnsupportedOperationException()
|
||||
}
|
||||
|
||||
expressionWalker(expr.getNextSiblingIgnoringWhitespaceAndComments())
|
||||
expressionWalker(expr.getNextSiblingIgnoringWhitespaceAndComments(), scopeDepth)
|
||||
}
|
||||
|
||||
private fun evaluateExpression(expr: PsiElement?): LLVMNode? {
|
||||
private fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMNode? {
|
||||
return when (expr) {
|
||||
is KtBinaryExpression -> evaluateBinaryExpression(expr)
|
||||
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
||||
is KtConstantExpression -> evaluateConstantExpression(expr)
|
||||
is KtCallExpression -> evaluateCallExpression(expr)
|
||||
is KtReferenceExpression -> evaluateReferenceExpression(expr)
|
||||
is PsiWhiteSpace -> null
|
||||
is PsiElement -> evaluatePsiElement(expr)
|
||||
is PsiElement -> evaluatePsiElement(expr, scopeDepth)
|
||||
null -> null
|
||||
else -> throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateReferenceExpression(expr: KtReferenceExpression): LLVMNode? {
|
||||
val variableName = expr.firstChild.text
|
||||
return variableManager.getLLVMvalue(variableName)
|
||||
}
|
||||
|
||||
private fun evaluateCallExpression(expr: KtCallExpression): LLVMNode? {
|
||||
val function = expr.firstChild.firstChild
|
||||
val descriptor = state.functions[function.text] ?: return null
|
||||
@@ -94,7 +113,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
||||
.getNextSiblingIgnoringWhitespaceAndComments()
|
||||
?.firstChild)
|
||||
|
||||
return LLVMCall(descriptor.returnType, "@${function.text}", descriptor.argTypes.mapIndexed { i: Int, type: String -> LLVMVariable(names[i], parseLLVMType(type)) })
|
||||
return LLVMCall(descriptor.returnType, "@${function.text}", descriptor.argTypes.mapIndexed { i: Int, type: LLVMType -> LLVMVariable(names[i], type) })
|
||||
}
|
||||
|
||||
private fun parseArgList(argumentList: PsiElement?): List<String> {
|
||||
@@ -112,9 +131,9 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
||||
return args
|
||||
}
|
||||
|
||||
private fun evaluateBinaryExpression(expr: KtBinaryExpression): LLVMNode {
|
||||
val left = evaluateExpression(expr.firstChild) as LLVMVariable? ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||
val right = evaluateExpression(expr.lastChild) as LLVMVariable? ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||
private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMNode {
|
||||
val left = evaluateExpression(expr.firstChild, scopeDepth) as LLVMVariable? ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||
val right = evaluateExpression(expr.lastChild, scopeDepth) as LLVMVariable? ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||
val operator = expr.operationToken
|
||||
|
||||
return codeBuilder.addPrimitiveBinaryOperation(operator, left, right)
|
||||
@@ -125,36 +144,39 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
||||
return LLVMVariable(node.firstChildNode.text, ::LLVMIntType.invoke())
|
||||
}
|
||||
|
||||
private fun evaluatePsiElement(element: PsiElement): LLVMVariable? {
|
||||
private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMVariable? {
|
||||
return when (element) {
|
||||
is LeafPsiElement -> evaluateLeafPsiElement(element)
|
||||
is LeafPsiElement -> evaluateLeafPsiElement(element, scopeDepth)
|
||||
is KtConstantExpression -> evaluateConstantExpression(element)
|
||||
KtTokens.INTEGER_LITERAL -> null
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateLeafPsiElement(element: LeafPsiElement): LLVMVariable? {
|
||||
private fun evaluateLeafPsiElement(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
|
||||
return when (element.elementType) {
|
||||
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element)
|
||||
KtTokens.VAL_KEYWORD -> evaluateValExpression(element)
|
||||
KtTokens.VAR_KEYWORD -> evaluateValExpression(element)
|
||||
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth)
|
||||
KtTokens.VAL_KEYWORD -> evaluateValExpression(element, scopeDepth)
|
||||
KtTokens.VAR_KEYWORD -> evaluateValExpression(element, scopeDepth)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateValExpression(element: LeafPsiElement): LLVMVariable? {
|
||||
private fun evaluateValExpression(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
|
||||
val identifier = element.getNextSiblingIgnoringWhitespaceAndComments()
|
||||
val eq = identifier?.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
|
||||
|
||||
val assignExpression = evaluateExpression(eq.getNextSiblingIgnoringWhitespaceAndComments()) ?: return null
|
||||
val assignExpression = evaluateExpression(eq.getNextSiblingIgnoringWhitespaceAndComments(), scopeDepth) ?: return null
|
||||
when (assignExpression) {
|
||||
is LLVMVariable -> variableManager.addVariable(identifier!!.text, assignExpression, scopeDepth);
|
||||
}
|
||||
codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}"), assignExpression)
|
||||
return null
|
||||
}
|
||||
|
||||
private fun evaluateReturnInstruction(element: LeafPsiElement): LLVMVariable? {
|
||||
private fun evaluateReturnInstruction(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
|
||||
var next = element.getNextSiblingIgnoringWhitespaceAndComments()
|
||||
val retVar = evaluateExpression(next) as LLVMVariable
|
||||
val retVar = evaluateExpression(next, scopeDepth) as LLVMVariable
|
||||
|
||||
codeBuilder.addReturnOperator(retVar)
|
||||
return null
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import org.kotlinnative.translator.exceptions.TranslationException
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import org.kotlinnative.translator.utils.FunctionDescriptor
|
||||
import java.util.*
|
||||
|
||||
@@ -27,6 +28,7 @@ class TranslationState(sources: List<String>, disposer: Disposable) {
|
||||
val environment: KotlinCoreEnvironment
|
||||
val bindingContext: BindingContext
|
||||
var functions = HashMap<String, FunctionDescriptor>()
|
||||
val variableManager = VariableManager()
|
||||
|
||||
init {
|
||||
val configuration = CompilerConfiguration()
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import java.util.*
|
||||
|
||||
class VariableManager {
|
||||
|
||||
private var fileVariableCollectionTree = HashMap<String, Stack<Pair<LLVMVariable, Int>>>()
|
||||
private var globalVariableCollection = HashMap<String, LLVMVariable>()
|
||||
|
||||
fun getLLVMvalue(variableName: String): LLVMVariable? {
|
||||
return fileVariableCollectionTree.get(variableName)?.peek()?.first ?: globalVariableCollection.get(variableName)
|
||||
}
|
||||
|
||||
fun pullUpwardsLevel(level: Int) {
|
||||
fileVariableCollectionTree.forEach { s, stack -> if (!stack.empty() && stack.peek().second >= level) stack.pop() else Unit }
|
||||
}
|
||||
|
||||
fun addVariable(name: String, variable: LLVMVariable, level: Int){
|
||||
val stack = fileVariableCollectionTree.getOrDefault(String, Stack<Pair<LLVMVariable, Int>>());
|
||||
stack.push(Pair(variable, level));
|
||||
fileVariableCollectionTree.put(name, stack)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ class LLVMBuilder {
|
||||
KtTokens.PLUS -> firstOp.type!!.operatorPlus(newVar, firstOp, secondOp)
|
||||
KtTokens.MINUS -> firstOp.type!!.operatorMinus(newVar, firstOp, secondOp)
|
||||
KtTokens.MUL -> firstOp.type!!.operatorTimes(newVar, firstOp, secondOp)
|
||||
else -> throw UnsupportedOperationException("Unkbown binary operator")
|
||||
else -> throw UnsupportedOperationException("Unknown binary operator")
|
||||
}
|
||||
|
||||
addAssignment(newVar, llvmExpression)
|
||||
@@ -60,6 +60,11 @@ class LLVMBuilder {
|
||||
llvmCode.appendln("ret void")
|
||||
}
|
||||
|
||||
fun loadVariable(llvmVariable: LLVMVariable) {
|
||||
llvmCode.appendln("$llvmVariable.addr = alloca ${llvmVariable.type}, align ${llvmVariable.type?.getAlign()}")
|
||||
llvmCode.appendln("store ${llvmVariable.type} $llvmVariable, ${llvmVariable.type}* ${llvmVariable.type}.addr, align ${llvmVariable.type?.getAlign()}")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return llvmCode.toString()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
class LLVMCall(val returnType: String, val name: String, val arguments: List<LLVMVariable>) : LLVMNode() {
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
class LLVMCall(val returnType: LLVMType, val name: String, val arguments: List<LLVMVariable>) : LLVMNode() {
|
||||
|
||||
override fun toString(): String {
|
||||
return "call $returnType $name(${arguments.joinToString { "${it.type} ${it.label}" }})"
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
import org.kotlinnative.translator.utils.FunctionArgument
|
||||
|
||||
fun LLVMFunctionDescriptor(name: String, argTypes: List<FunctionArgument>?, returnType: String, declare: Boolean = false) =
|
||||
"${ if (declare) "declare" else "define"} $returnType @$name(${
|
||||
argTypes?.mapIndexed { i: Int, s: FunctionArgument -> "${s.type} %tmp.${s.name}"
|
||||
}?.joinToString() ?: "" })"
|
||||
|
||||
fun LLVMFunctionDescriptor(name: String, argTypes: List<FunctionArgument>?, returnType: LLVMType, declare: Boolean = false) =
|
||||
"${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) {
|
||||
"Int" -> "i32"
|
||||
"Unit" -> "void"
|
||||
else -> "%$type*"
|
||||
fun LLVMMapStandardType(type: String): LLVMType = when (type) {
|
||||
"Int" -> LLVMIntType()
|
||||
"Double" -> LLVMDoubleType()
|
||||
"Unit" -> LLVMVoidType()
|
||||
else -> LLVMReferenceType("%$type*")
|
||||
}
|
||||
@@ -18,8 +18,7 @@ class LLVMDoubleType() : LLVMType() {
|
||||
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
|
||||
LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp")
|
||||
|
||||
override fun toString(): String {
|
||||
return "double"
|
||||
}
|
||||
override fun toString() = "double"
|
||||
|
||||
override fun getAlign() = 8
|
||||
}
|
||||
@@ -20,4 +20,5 @@ class LLVMIntType() : LLVMType() {
|
||||
|
||||
override fun toString() = "i32"
|
||||
|
||||
override fun getAlign() = 4
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
|
||||
class LLVMReferenceType(val type: String) : LLVMType() {
|
||||
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
|
||||
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
|
||||
override fun getAlign(): Int {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
|
||||
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression {
|
||||
throw UnsupportedOperationException("not implemented")
|
||||
}
|
||||
override fun toString() = type
|
||||
|
||||
}
|
||||
@@ -10,6 +10,8 @@ abstract class LLVMType() {
|
||||
open fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
|
||||
|
||||
abstract fun getAlign(): Int
|
||||
}
|
||||
|
||||
fun parseLLVMType(type: String): LLVMType = when (type) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.kotlinnative.translator.llvm.types
|
||||
|
||||
class LLVMVoidType() : LLVMType() {
|
||||
|
||||
override fun getAlign(): Int = 0
|
||||
override fun toString(): String = "void"
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.kotlinnative.translator.utils
|
||||
|
||||
data class FunctionArgument(val type: String, val name: String)
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
data class FunctionDescriptor(val returnType: String, val argTypes: List<String>)
|
||||
data class FunctionArgument(val type: LLVMType, val name: String)
|
||||
|
||||
data class FunctionDescriptor(val returnType: LLVMType, val argTypes: List<LLVMType>)
|
||||
|
||||
Reference in New Issue
Block a user