translator: add stack variable allocation, refactoring, llvmVariable starts storing Kotlin Name

This commit is contained in:
Alexey Stepanov
2016-07-12 12:07:03 +03:00
parent fbfe5dedda
commit 31c2937acc
9 changed files with 36 additions and 16 deletions
+1
View File
@@ -21,3 +21,4 @@ fun main(args: Array<String>) {
println(FileTranslator(state, files[0]).generateCode()) println(FileTranslator(state, files[0]).generateCode())
} }
@@ -3,9 +3,7 @@ package org.kotlinnative.translator
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
import org.kotlinnative.translator.llvm.LLVMBuilder import org.kotlinnative.translator.llvm.LLVMBuilder
import org.kotlinnative.translator.llvm.LLVMVariable
import org.kotlinnative.translator.utils.FunctionDescriptor import org.kotlinnative.translator.utils.FunctionDescriptor
import java.util.*
class FileTranslator(val state: TranslationState, val file: KtFile) { class FileTranslator(val state: TranslationState, val file: KtFile) {
@@ -66,7 +66,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
private fun generateLoadArguments(function: KtNamedFunction) { private fun generateLoadArguments(function: KtNamedFunction) {
args?.forEach { args?.forEach {
val loadVariable = LLVMVariable("%${it.name}", it.type) val loadVariable = LLVMVariable("%${it.name}", it.type, it.name)
codeBuilder.loadVariable(loadVariable) codeBuilder.loadVariable(loadVariable)
variableManager.addVariable(it.name, loadVariable, 2) variableManager.addVariable(it.name, loadVariable, 2)
} }
@@ -76,6 +76,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
when (expr) { when (expr) {
is KtBlockExpression -> expressionWalker(expr.firstChild, scopeDepth + 1) is KtBlockExpression -> expressionWalker(expr.firstChild, scopeDepth + 1)
is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement, scopeDepth) is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement, scopeDepth)
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
is PsiElement -> evaluateExpression(expr.firstChild, scopeDepth + 1) is PsiElement -> evaluateExpression(expr.firstChild, scopeDepth + 1)
null -> { null -> {
variableManager.pullUpwardsLevel(scopeDepth) variableManager.pullUpwardsLevel(scopeDepth)
@@ -141,7 +142,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMVariable { private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMVariable {
val node = expr.node val node = expr.node
return LLVMVariable(node.firstChildNode.text, ::LLVMIntType.invoke()) return codeBuilder.addConstant(LLVMVariable(node.firstChildNode.text, LLVMIntType()))
} }
private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMVariable? { private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMVariable? {
@@ -168,9 +169,12 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
val assignExpression = evaluateExpression(eq.getNextSiblingIgnoringWhitespaceAndComments(), scopeDepth) ?: return null val assignExpression = evaluateExpression(eq.getNextSiblingIgnoringWhitespaceAndComments(), scopeDepth) ?: return null
when (assignExpression) { when (assignExpression) {
is LLVMVariable -> variableManager.addVariable(identifier!!.text, assignExpression, scopeDepth); is LLVMVariable -> {
variableManager.addVariable(identifier!!.text, assignExpression, scopeDepth)
return null
}
} }
codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}"), assignExpression) codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}", null, identifier.text), assignExpression)
return null return null
} }
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import org.kotlinnative.translator.exceptions.TranslationException import org.kotlinnative.translator.exceptions.TranslationException
import org.kotlinnative.translator.llvm.LLVMVariable
import org.kotlinnative.translator.utils.FunctionDescriptor import org.kotlinnative.translator.utils.FunctionDescriptor
import java.util.* import java.util.*
@@ -36,7 +35,7 @@ class TranslationState(sources: List<String>, disposer: Disposable) {
private var hasError = false private var hasError = false
override fun hasErrors(): Boolean { override fun hasErrors(): Boolean {
return hasError; return hasError
} }
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) { override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
@@ -16,9 +16,9 @@ class VariableManager {
fileVariableCollectionTree.forEach { s, stack -> if (!stack.empty() && stack.peek().second >= level) stack.pop() else Unit } fileVariableCollectionTree.forEach { s, stack -> if (!stack.empty() && stack.peek().second >= level) stack.pop() else Unit }
} }
fun addVariable(name: String, variable: LLVMVariable, level: Int){ fun addVariable(name: String, variable: LLVMVariable, level: Int) {
val stack = fileVariableCollectionTree.getOrDefault(String, Stack<Pair<LLVMVariable, Int>>()); val stack = fileVariableCollectionTree.getOrDefault(String, Stack<Pair<LLVMVariable, Int>>())
stack.push(Pair(variable, level)); stack.push(Pair(variable, level))
fileVariableCollectionTree.put(name, stack) fileVariableCollectionTree.put(name, stack)
} }
@@ -32,6 +32,7 @@ class LLVMBuilder {
KtTokens.PLUS -> firstOp.type!!.operatorPlus(newVar, firstOp, secondOp) KtTokens.PLUS -> firstOp.type!!.operatorPlus(newVar, firstOp, secondOp)
KtTokens.MINUS -> firstOp.type!!.operatorMinus(newVar, firstOp, secondOp) KtTokens.MINUS -> firstOp.type!!.operatorMinus(newVar, firstOp, secondOp)
KtTokens.MUL -> firstOp.type!!.operatorTimes(newVar, firstOp, secondOp) KtTokens.MUL -> firstOp.type!!.operatorTimes(newVar, firstOp, secondOp)
KtTokens.EQ -> throw UnsupportedOperationException()
else -> throw UnsupportedOperationException("Unknown binary operator") else -> throw UnsupportedOperationException("Unknown binary operator")
} }
@@ -61,8 +62,25 @@ class LLVMBuilder {
} }
fun loadVariable(llvmVariable: LLVMVariable) { fun loadVariable(llvmVariable: LLVMVariable) {
llvmCode.appendln("$llvmVariable.addr = alloca ${llvmVariable.type}, align ${llvmVariable.type?.getAlign()}") addVariableByRef(llvmVariable, LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName))
llvmCode.appendln("store ${llvmVariable.type} $llvmVariable, ${llvmVariable.type}* ${llvmVariable.type}.addr, align ${llvmVariable.type?.getAlign()}") }
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) {
llvmCode.appendln("$sourceVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.getAlign()}")
llvmCode.appendln("store ${targetVariable.type} $targetVariable, ${targetVariable.type}* ${sourceVariable}, align ${targetVariable.type?.getAlign()}")
}
fun addVariableByValue(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) {
val tmp = getNewVariable(targetVariable.type)
llvmCode.appendln("$tmp = alloca ${tmp.type}, align ${tmp.type?.getAlign()}")
llvmCode.appendln("store ${tmp.type} $sourceVariable, ${tmp.type}* ${tmp}, align ${tmp.type?.getAlign()}")
llvmCode.appendln("$targetVariable = load ${targetVariable.type}, ${targetVariable.type}* $tmp, align ${targetVariable.type?.getAlign()}")
}
fun addConstant(sourceVariable: LLVMVariable): LLVMVariable {
val target = getNewVariable(sourceVariable.type)
addVariableByValue(target, sourceVariable)
return target
} }
override fun toString(): String { override fun toString(): String {
@@ -2,7 +2,7 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType 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, val kotlinName: String? = null) : LLVMNode() {
override fun toString(): String = label override fun toString(): String = label
@@ -7,7 +7,7 @@ import org.kotlinnative.translator.utils.FunctionArgument
fun LLVMFunctionDescriptor(name: String, argTypes: List<FunctionArgument>?, returnType: LLVMType, declare: Boolean = false) = fun LLVMFunctionDescriptor(name: String, argTypes: List<FunctionArgument>?, returnType: LLVMType, declare: Boolean = false) =
"${if (declare) "declare" else "define"} $returnType @$name(${ "${if (declare) "declare" else "define"} $returnType @$name(${
argTypes?.mapIndexed { i: Int, s: FunctionArgument -> argTypes?.mapIndexed { i: Int, s: FunctionArgument ->
"${s.type} %tmp.${s.name}" "${s.type} %${s.name}"
}?.joinToString() ?: ""})" }?.joinToString() ?: ""})"
fun LLVMMapStandardType(type: String): LLVMType = when (type) { fun LLVMMapStandardType(type: String): LLVMType = when (type) {
@@ -6,4 +6,4 @@ enum class LLVMTypes {
int, double, float, char int, double, float, char
} }
val typesMap = mapOf(Pair(LLVMTypes.int, ::LLVMIntType)); val typesMap = mapOf(Pair(LLVMTypes.int, ::LLVMIntType))