add simpy variable manager, fix some bugs

This commit is contained in:
Alexey Stepanov
2016-07-11 20:11:20 +03:00
parent 33ff4f720a
commit fbfe5dedda
13 changed files with 132 additions and 42 deletions
@@ -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
}
@@ -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>)