translator: add resolving variable, LLVMConstant and LLVMSingleValue

This commit is contained in:
Alexey Stepanov
2016-07-12 18:32:12 +03:00
parent 6972a4d658
commit 9e2b593a57
8 changed files with 100 additions and 57 deletions
@@ -133,7 +133,8 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
?.firstChild)
return LLVMCall(descriptor.returnType, "@${function.text}", descriptor.args?.mapIndexed {
i: Int, variable: LLVMVariable -> LLVMVariable(names[i], variable.type)
i: Int, variable: LLVMVariable ->
LLVMVariable(names[i], variable.type)
} ?: listOf())
}
@@ -153,19 +154,19 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
}
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 left = evaluateExpression(expr.firstChild, scopeDepth) as LLVMSingleValue? ?: throw UnsupportedOperationException("Wrong binary exception")
val right = evaluateExpression(expr.lastChild, scopeDepth) as LLVMSingleValue? ?: throw UnsupportedOperationException("Wrong binary exception")
val operator = expr.operationToken
return codeBuilder.addPrimitiveBinaryOperation(operator, left, right)
val newVar = codeBuilder.getNewVariable(LLVMIntType())
return codeBuilder.addPrimitiveBinaryOperation(operator, newVar, left, right)
}
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMVariable {
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant {
val node = expr.node
return codeBuilder.addConstant(LLVMVariable(node.firstChildNode.text, LLVMIntType(), pointer = false))
return LLVMConstant(node.firstChildNode.text, LLVMIntType(), pointer = false)
}
private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMVariable? {
private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMSingleValue? {
return when (element) {
is LeafPsiElement -> evaluateLeafPsiElement(element, scopeDepth)
is KtConstantExpression -> evaluateConstantExpression(element)
@@ -194,16 +195,22 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
assignExpression.kotlinName = identifier!!.text
assignExpression.pointer = false
variableManager.addVariable(identifier.text, assignExpression, scopeDepth)
return null
}
is LLVMConstant -> {
val newVar = LLVMVariable("%${identifier!!.text}.addr", type = LLVMIntType(), kotlinName = identifier.text, pointer = true)
codeBuilder.addConstant(newVar, assignExpression)
variableManager.addVariable(identifier.text, newVar, scopeDepth)
}
else -> {
codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}", null, identifier.text), assignExpression)
}
}
codeBuilder.addAssignment(LLVMVariable("%${identifier!!.text}", null, identifier.text), assignExpression)
return null
}
private fun evaluateReturnInstruction(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? {
val next = element.getNextSiblingIgnoringWhitespaceAndComments()
val retVar = evaluateExpression(next, scopeDepth) as LLVMVariable
val retVar = evaluateExpression(next, scopeDepth) as LLVMSingleValue
codeBuilder.addReturnOperator(retVar)
return null
@@ -2,16 +2,15 @@ package org.kotlinnative.translator.llvm
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.lexer.KtTokens
import org.kotlinnative.translator.llvm.types.LLVMIntType
import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMBuilder {
private var llvmCode: StringBuilder = StringBuilder()
private var variableCount = 0
fun getNewVariable(type: LLVMType?, pointer: Boolean = false): LLVMVariable {
fun getNewVariable(type: LLVMType?, pointer: Boolean = false, kotlinName: String? = null): LLVMVariable {
variableCount++
return LLVMVariable("%var$variableCount", type, "", pointer)
return LLVMVariable("%var$variableCount", type, kotlinName = kotlinName, pointer = pointer)
}
fun addLLVMCode(code: String) {
@@ -26,18 +25,29 @@ class LLVMBuilder {
llvmCode.appendln("}")
}
fun addPrimitiveBinaryOperation(operation: IElementType, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMVariable {
val newVar = getNewVariable(LLVMIntType())
fun receiveNativeValue(firstOp: LLVMSingleValue) = when (firstOp) {
is LLVMConstant -> firstOp
is LLVMVariable -> when (firstOp.pointer) {
false -> firstOp
else -> loadAndGetVariable(firstOp)
}
else -> throw UnsupportedOperationException()
}
fun addPrimitiveBinaryOperation(operation: IElementType, resultOp: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable {
val firstNativeOp = receiveNativeValue(firstOp)
val secondNativeOp = receiveNativeValue(secondOp)
val llvmExpression = when (operation) {
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.PLUS -> firstOp.type!!.operatorPlus(resultOp, firstNativeOp, secondNativeOp)
KtTokens.MINUS -> firstOp.type!!.operatorMinus(resultOp, firstNativeOp, secondNativeOp)
KtTokens.MUL -> firstOp.type!!.operatorTimes(resultOp, firstNativeOp, secondNativeOp)
KtTokens.EQ -> return resultOp
else -> throw UnsupportedOperationException("Unknown binary operator")
}
addAssignment(newVar, llvmExpression)
addAssignment(resultOp, llvmExpression)
return newVar
return resultOp
}
fun clean() {
@@ -48,7 +58,7 @@ class LLVMBuilder {
llvmCode.appendln("$llvmVariable = $rhs")
}
fun addReturnOperator(llvmVariable: LLVMVariable) {
fun addReturnOperator(llvmVariable: LLVMSingleValue) {
llvmCode.appendln("ret ${llvmVariable.type} $llvmVariable")
}
@@ -56,6 +66,16 @@ class LLVMBuilder {
llvmCode.appendln("ret void")
}
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) {
val code = "$target = getelementptr inbounds ${source.type}, ${source.type}* $source, i32 0, i32 $offset"
llvmCode.appendln(code)
}
fun storeVariable(target: LLVMVariable, source: LLVMVariable) {
val code = "store ${source.type} $source, ${target.getType()} $target, align ${source.type?.align!!}"
llvmCode.appendln(code)
}
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true) {
addVariableByRef(LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, true), llvmVariable, store)
}
@@ -65,16 +85,6 @@ class LLVMBuilder {
llvmCode.appendln(code)
}
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) {
var code = "$target = getelementptr inbounds ${source.type}, ${source.type}* $source, i32 0, i32 $offset"
llvmCode.appendln(code)
}
fun storeVariable(target: LLVMVariable, source: LLVMVariable) {
var code = "store ${source.type} $source, ${target.getType()} $target, align ${source.type?.align!!}"
llvmCode.appendln(code)
}
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) {
llvmCode.appendln("$targetVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type?.align}")
@@ -83,18 +93,22 @@ class LLVMBuilder {
}
}
fun addVariableByValue(targetVariable: LLVMVariable, sourceVariable: LLVMVariable) {
val tmp = getNewVariable(targetVariable.type, 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 addVariableByValue(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, allocVariable: LLVMVariable) {
llvmCode.appendln("$allocVariable = alloca ${allocVariable.type}, align ${allocVariable.type?.align}")
llvmCode.appendln("store ${allocVariable.type} $sourceVariable, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type?.align}")
llvmCode.appendln("$targetVariable = load ${targetVariable.type}, ${allocVariable.getType()} $allocVariable, align ${targetVariable.type?.align}")
}
fun addConstant(sourceVariable: LLVMVariable): LLVMVariable {
val target = getNewVariable(sourceVariable.type, sourceVariable.pointer)
addVariableByValue(target, sourceVariable)
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}")
}
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
assert(!source.pointer)
val target = getNewVariable(type = source.type, pointer = source.pointer, kotlinName = source.kotlinName)
val code = "$target = load ${target.type}, ${source.getType()} $source, align ${target.type?.align!!}"
llvmCode.appendln(code)
return target
}
@@ -104,15 +118,15 @@ class LLVMBuilder {
}
fun bitcast(dst: LLVMVariable, llvmType: LLVMType): LLVMVariable {
var empty = getNewVariable(llvmType, true)
var code = "$empty = bitcast ${dst.getType()} $dst to $llvmType*"
val empty = getNewVariable(llvmType, true)
val code = "$empty = bitcast ${dst.getType()} $dst to $llvmType*"
llvmCode.appendln(code)
return empty
}
fun memcpy(castedDst: LLVMVariable, castedSrc: LLVMVariable, size: Int, align: Int = 4, volatile: Boolean = false) {
var code = "call void @llvm.memcpy.p0i8.p0i8.i64(i8* $castedDst, i8* $castedSrc, i64 $size, i32 $align, i1 $volatile)"
fun memcpy(castedDst: LLVMVariable, castedSrc: LLVMVariable, size: Int, align: Int = 4, volatile: Boolean = false) {
val code = "call void @llvm.memcpy.p0i8.p0i8.i64(i8* $castedDst, i8* $castedSrc, i64 $size, i32 $align, i1 $volatile)"
llvmCode.appendln(code)
}
@@ -0,0 +1,10 @@
package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMConstant(val value: String, override val type: LLVMType? = null, override var pointer: Boolean = false) : LLVMSingleValue(type, pointer) {
override fun getType(): String = type.toString() + if (pointer) "*" else " "
override fun toString(): String = value
}
@@ -0,0 +1,9 @@
package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.exceptions.UnimplementedException
import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMSingleValue(open val type: LLVMType? = null, open var pointer: Boolean = false) : LLVMNode() {
open fun getType(): String = throw UnimplementedException()
}
@@ -2,9 +2,9 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMVariable(val label: String, val type: LLVMType? = null, var kotlinName: String? = null, var pointer: Boolean = false) : LLVMNode() {
open class LLVMVariable(val label: String, override val type: LLVMType? = null, var kotlinName: String? = null, override var pointer: Boolean = false) : LLVMSingleValue() {
fun getType(): String = type.toString() + if (pointer) "*" else ""
override fun getType(): String = type.toString() + if (pointer) "*" else ""
override fun toString(): String = label
}
@@ -1,21 +1,22 @@
package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMDoubleType() : LLVMType() {
//TODO switch by types: int + double = int
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMDoubleType(), "fsub double i32 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMDoubleType(), "fmul double i32 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp")
override val align = 8
@@ -1,21 +1,22 @@
package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
class LLVMIntType() : LLVMType() {
//TODO switch by types: int + double = int
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
override fun operatorMinus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "sub nsw i32 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
override fun operatorTimes(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "mul nsw i32 $firstOp, $secondOp")
//TODO switch by types: int + double = int
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression =
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp")
override val align = 4
@@ -2,13 +2,14 @@ package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.exceptions.UnimplementedException
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
abstract class LLVMType() : Cloneable {
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()
open fun operatorPlus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorTimes(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorMinus(result: LLVMVariable, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
fun makeClone() = clone()