translator: add while loops, fix for constant assignment, speaking markup for labels

This commit is contained in:
Alexey Stepanov
2016-07-13 16:15:07 +03:00
parent d54ef1d3c5
commit 4da6ddde80
5 changed files with 56 additions and 26 deletions
@@ -67,8 +67,8 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
private fun generateLoadArguments() {
args?.forEach {
val loadVariable = LLVMVariable("%${it.label}", it.type, it.label, false)
codeBuilder.loadArgument(loadVariable)
variableManager.addVariable(it.label, loadVariable, 2)
val allocVar = codeBuilder.loadArgument(loadVariable)
variableManager.addVariable(it.label, allocVar, 2)
}
}
@@ -207,11 +207,37 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth)
KtTokens.VAL_KEYWORD -> evaluateValExpression(element, scopeDepth)
KtTokens.VAR_KEYWORD -> evaluateValExpression(element, scopeDepth)
KtTokens.IF_KEYWORD -> evaluateIfOperator(element, scopeDepth, false)
KtTokens.IF_KEYWORD -> evaluateIfOperator(element, scopeDepth, containReturn = false)
KtTokens.WHILE_KEYWORD -> evaluateWhileOperator(element, scopeDepth)
else -> null
}
}
private fun evaluateWhileOperator(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
var getBrackets = element.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
val condition = getBrackets.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
getBrackets = condition.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
val bodyExpression = getBrackets.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
return executeWhileBlock(condition.firstChild as KtBinaryExpression, bodyExpression.firstChild, scopeDepth)
}
private fun executeWhileBlock(condition: KtBinaryExpression, bodyExpression: PsiElement, scopeDepth: Int): LLVMVariable? {
val conditionLable = codeBuilder.getNewLabel(prefix = "while")
val bodyLable = codeBuilder.getNewLabel(prefix = "while")
val exitLable = codeBuilder.getNewLabel(prefix = "while")
codeBuilder.addUnconditionJump(conditionLable)
codeBuilder.markWithLabel(conditionLable)
val conditionResult = evaluateBinaryExpression(condition, scopeDepth + 1)
codeBuilder.addCondition(conditionResult, bodyLable, exitLable)
evaluateCodeBlock(bodyExpression, bodyLable, conditionLable, scopeDepth + 1)
codeBuilder.markWithLabel(exitLable)
return null
}
private fun evaluateIfOperator(element: LeafPsiElement, scopeDepth: Int, containReturn: Boolean): LLVMVariable? {
var getBrackets = element.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
val condition = getBrackets.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
@@ -231,9 +257,9 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
val conditionResult: LLVMVariable = evaluateBinaryExpression(condition, scopeDepth + 1)
val variable = codeBuilder.getNewVariable(LLVMIntType(), true)
codeBuilder.allocVar(variable)
val thenLabel = codeBuilder.getNewLabel()
val elseLabel = codeBuilder.getNewLabel()
val endLabel = codeBuilder.getNewLabel()
val thenLabel = codeBuilder.getNewLabel(prefix = "if")
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
val endLabel = codeBuilder.getNewLabel(prefix = "if")
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
codeBuilder.markWithLabel(thenLabel)
@@ -249,10 +275,10 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
}
private fun executeIfBlock(condition: KtBinaryExpression, thenExpression: PsiElement, elseExpression: PsiElement?, scopeDepth: Int): LLVMVariable? {
val conditionResult: LLVMVariable = evaluateBinaryExpression(condition, scopeDepth + 1)
val thenLabel = codeBuilder.getNewLabel()
val elseLabel = codeBuilder.getNewLabel()
val endLabel = codeBuilder.getNewLabel()
val conditionResult = evaluateBinaryExpression(condition, scopeDepth + 1)
val thenLabel = codeBuilder.getNewLabel(prefix = "if")
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
val endLabel = codeBuilder.getNewLabel(prefix = "if")
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
@@ -271,6 +297,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
val assignExpression = evaluateExpression(eq.getNextSiblingIgnoringWhitespaceAndComments(), scopeDepth) ?: return null
when (assignExpression) {
//TODO resolving
is LLVMVariable -> {
assignExpression.kotlinName = identifier!!.text
assignExpression.pointer = false
@@ -278,6 +305,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
}
is LLVMConstant -> {
val newVar = variableManager.getVariable(identifier!!.text, LLVMIntType(), pointer = true)
codeBuilder.addConstant(newVar, assignExpression)
variableManager.addVariable(identifier.text, newVar, scopeDepth)
}
@@ -288,7 +316,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
codeBuilder.addLLVMCode(assignExpression.call(result).toString())
}
else -> {
codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}", null, identifier.text), assignExpression)
codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}", LLVMIntType(), identifier.text), assignExpression)
}
}
return null
@@ -28,7 +28,7 @@ class VariableManager {
val ourVersion = variableVersion.getOrDefault(name, 0) + 1
variableVersion.put(name, ourVersion)
return LLVMVariable("%managed.${name}.${ourVersion}", kotlinName = name, type = type, pointer = pointer)
return LLVMVariable("%managed.$name.$ourVersion", kotlinName = name, type = type, pointer = pointer)
}
}
@@ -24,14 +24,14 @@ class LLVMBuilder(val arm: Boolean) {
}
}
fun getNewVariable(type: LLVMType?, pointer: Boolean = false, kotlinName: String? = null): LLVMVariable {
fun getNewVariable(type: LLVMType, pointer: Boolean = false, kotlinName: String? = null): LLVMVariable {
variableCount++
return LLVMVariable("%var$variableCount", type, kotlinName, pointer)
}
fun getNewLabel(scope: LLVMScope = LLVMLocalScope()): LLVMLabel {
fun getNewLabel(scope: LLVMScope = LLVMLocalScope(), prefix: String): LLVMLabel {
labelCount++
return LLVMLabel("label$labelCount", scope)
return LLVMLabel("label.$prefix.$labelCount", scope)
}
fun addLLVMCode(code: String) {
@@ -117,36 +117,38 @@ class LLVMBuilder(val arm: Boolean) {
llvmCode.appendln(code)
}
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true) {
addVariableByRef(LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, true), llvmVariable, store)
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable {
val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, true)
addVariableByRef(allocVar, llvmVariable, store)
return allocVar
}
fun loadVariable(target: LLVMVariable, source: LLVMVariable) {
val code = "$target = load ${target.type}, ${source.getType()} $source, align ${target.type?.align!!}"
val code = "$target = load ${target.type}, ${source.getType()} $source, align ${target.type.align}"
llvmCode.appendln(code)
}
fun allocVar(target: LLVMVariable) {
llvmCode.appendln("$target = alloca ${target.type}, align ${target.type?.align!!}")
llvmCode.appendln("$target = alloca ${target.type}, align ${target.type.align}")
}
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) {
llvmCode.appendln("$targetVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.align}")
llvmCode.appendln("$targetVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type.align}")
if (store) {
llvmCode.appendln("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type?.align}")
llvmCode.appendln("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type.align}")
}
}
fun addConstant(allocVariable: LLVMVariable, constantValue: LLVMConstant) {
llvmCode.appendln("$allocVariable = alloca ${allocVariable.type}, align ${allocVariable.type?.align}")
llvmCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type?.align}")
llvmCode.appendln("$allocVariable = alloca ${allocVariable.type}, align ${allocVariable.type.align}")
llvmCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type.align}")
}
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
assert(!source.pointer)
val target = getNewVariable(source.type, source.pointer, source.kotlinName)
val code = "$target = load ${target.type}, ${source.getType()} $source, align ${target.type?.align!!}"
val code = "$target = load ${target.type}, ${source.getType()} $source, align ${target.type.align}"
llvmCode.appendln(code)
return target
}
@@ -3,4 +3,4 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMClassVariable(label: String, type: LLVMType? = null, val offset: Int = 0) : LLVMVariable(label, type)
class LLVMClassVariable(label: String, type: LLVMType, val offset: Int = 0) : LLVMVariable(label, type)
@@ -2,7 +2,7 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMVariable(val label: String, override val type: LLVMType? = null, var kotlinName: String? = null, override var pointer: Boolean = false) : LLVMSingleValue() {
open class LLVMVariable(val label: String, override val type: LLVMType, var kotlinName: String? = null, override var pointer: Boolean = false) : LLVMSingleValue() {
override fun getType(): String = type.toString() + if (pointer) "*" else ""