translator: add pointer modificator, fixes for stack allocation, refactoring

This commit is contained in:
Alexey Stepanov
2016-07-12 13:54:10 +03:00
parent d17c8922b8
commit 1a76a916a6
12 changed files with 52 additions and 30 deletions
-1
View File
@@ -21,4 +21,3 @@ fun main(args: Array<String>) {
println(FileTranslator(state, files[0]).generateCode())
}
@@ -66,7 +66,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
private fun generateLoadArguments(function: KtNamedFunction) {
args?.forEach {
val loadVariable = LLVMVariable("%${it.name}", it.type, it.name)
val loadVariable = LLVMVariable("%${it.name}", it.type, it.name, true)
codeBuilder.loadVariable(loadVariable)
variableManager.addVariable(it.name, loadVariable, 2)
}
@@ -142,7 +142,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMVariable {
val node = expr.node
return codeBuilder.addConstant(LLVMVariable(node.firstChildNode.text, LLVMIntType()))
return codeBuilder.addConstant(LLVMVariable(node.firstChildNode.text, LLVMIntType(), pointer = false))
}
private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMVariable? {
@@ -168,9 +168,12 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
val eq = identifier?.getNextSiblingIgnoringWhitespaceAndComments() ?: return null
val assignExpression = evaluateExpression(eq.getNextSiblingIgnoringWhitespaceAndComments(), scopeDepth) ?: return null
when (assignExpression) {
is LLVMVariable -> {
variableManager.addVariable(identifier!!.text, assignExpression, scopeDepth)
assignExpression.kotlinName = identifier!!.text
assignExpression.pointer = false
variableManager.addVariable(identifier.text, assignExpression, scopeDepth)
return null
}
}
@@ -34,9 +34,7 @@ class TranslationState(sources: List<String>, disposer: Disposable) {
val messageCollector = GroupingMessageCollector(object : MessageCollector {
private var hasError = false
override fun hasErrors(): Boolean {
return hasError
}
override fun hasErrors(): Boolean = hasError
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
println("[report] $message")
@@ -9,9 +9,9 @@ class LLVMBuilder {
private var llvmCode: StringBuilder = StringBuilder()
private var variableCount = 0
fun getNewVariable(type: LLVMType?): LLVMVariable {
fun getNewVariable(type: LLVMType?, pointer: Boolean = false): LLVMVariable {
variableCount++
return LLVMVariable("%var$variableCount", type)
return LLVMVariable("%var$variableCount", type, pointer = pointer)
}
fun addLLVMCode(code: String) {
@@ -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)
KtTokens.EQ -> throw UnsupportedOperationException()
KtTokens.EQ -> return moveVariableValue(secondOp, firstOp)
else -> throw UnsupportedOperationException("Unknown binary operator")
}
@@ -41,6 +41,21 @@ class LLVMBuilder {
return newVar
}
private fun moveVariableValue(from: LLVMVariable, to: LLVMVariable): LLVMVariable {
//%0 = load i32, i32* %y, align 4
//store i32 %0, i32* %z, align 4
//%1 = load i32, i32* %z, align 4
llvmCode.appendln("VARIABLE from $from TO $to")
/*
val tmp1 = getNewVariable(from.type)
val tmp2 = getNewVariable(to.type)
llvmCode.appendln("$tmp1 = load ${tmp1.type}, ${tmp1.type}* $from, align ${tmp1.type?.align}")
llvmCode.appendln("store ${tmp1.type} $tmp1, ${to.type}* $to, align ${to.type?.align}")
llvmCode.appendln("$tmp2 = load ${tmp2.type}, ${tmp2.type}* $to, align ${to.type?.align}")*/
return from
}
fun clean() {
llvmCode = StringBuilder()
}
@@ -50,7 +65,7 @@ class LLVMBuilder {
}
fun addReturnOperator(llvmVariable: LLVMVariable) {
llvmCode.appendln("ret i32 $llvmVariable")
llvmCode.appendln("ret ${llvmVariable.type} $llvmVariable")
}
fun addVoidReturn() {
@@ -58,30 +73,32 @@ class LLVMBuilder {
}
fun loadVariable(llvmVariable: LLVMVariable) {
addVariableByRef(llvmVariable, LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName))
addVariableByRef(llvmVariable, LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, true))
}
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()}")
llvmCode.appendln("$sourceVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.align}")
llvmCode.appendln("store ${sourceVariable.type} $targetVariable, ${targetVariable.getType()} $sourceVariable, align ${targetVariable.type?.align}")
}
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()}")
val tmp = getNewVariable(targetVariable.type, pointer = true)
llvmCode.appendln("$tmp = alloca ${tmp.type}, align ${tmp.type?.align}")
llvmCode.appendln("store ${tmp.type} $sourceVariable, ${tmp.getType()} $tmp, align ${tmp.type?.align}")
llvmCode.appendln("$targetVariable = load ${targetVariable.type}, ${tmp.getType()} $tmp, align ${targetVariable.type?.align}")
}
fun addConstant(sourceVariable: LLVMVariable): LLVMVariable {
val target = getNewVariable(sourceVariable.type)
val target = getNewVariable(sourceVariable.type, pointer = sourceVariable.pointer)
addVariableByValue(target, sourceVariable)
return target
}
fun createClass(name: String, fields: List<LLVMVariable>) {
val code = "@class.$name = type { ${ fields.map { it.type }.joinToString() } }"
fun createClass(name: String, fields: List<LLVMVariable>) {
val code = "@class.$name = type { ${fields.map { it.type }.joinToString()} }"
llvmCode.appendln(code)
}
@@ -2,8 +2,10 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMVariable(val label: String, val type: LLVMType? = null, val kotlinName: String? = null) : LLVMNode() {
open class LLVMVariable(val label: String, val type: LLVMType? = null, var kotlinName: String? = null, var pointer: Boolean = false) : LLVMNode() {
override fun toString(): String = label
fun getType(): String = type.toString() + if (pointer) "*" else ""
}
@@ -4,4 +4,6 @@ class LLVMCharType() : LLVMType() {
override fun toString(): String = "i8"
override val align = 1
}
@@ -20,5 +20,5 @@ class LLVMDoubleType() : LLVMType() {
override fun toString() = "double"
override fun getAlign() = 8
override val align = 8
}
@@ -20,5 +20,6 @@ class LLVMIntType() : LLVMType() {
override fun toString() = "i32"
override fun getAlign() = 4
override val align = 4
}
@@ -12,13 +12,11 @@ class LLVMReferenceType(val type: String) : LLVMType() {
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
override val align = -1
}
@@ -4,4 +4,5 @@ class LLVMShortType() : LLVMType() {
override fun toString(): String = "i16"
override val align = 1
}
@@ -11,7 +11,7 @@ abstract class LLVMType() {
open fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
open fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression = throw UnimplementedException()
open fun getAlign(): Int = throw UnimplementedException()
abstract val align: Int
}
fun parseLLVMType(type: String): LLVMType = when (type) {
@@ -2,7 +2,8 @@ package org.kotlinnative.translator.llvm.types
class LLVMVoidType() : LLVMType() {
override fun getAlign(): Int = 0
override val align = 0
override fun toString(): String = "void"
}