translator: add resolving variable, LLVMConstant and LLVMSingleValue
This commit is contained in:
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user