translator: refactor LLVMBuilder and LLVMCodegen

This commit is contained in:
Alexey Stepanov
2016-08-30 11:41:09 +03:00
parent 8030c745e7
commit ddaf41e214
13 changed files with 229 additions and 328 deletions
+2
View File
@@ -36,6 +36,8 @@ class IntIterator(first: Int, last: Int, val step: Int) {
private val finalElement = last
private var hasNext: Boolean = if (step > 0) first <= last else first >= last
final fun next() = nextInt ()
fun hasNext(): Boolean = hasNext
fun nextInt(): Int {
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.kotlinnative.translator.llvm.*
import org.kotlinnative.translator.llvm.types.*
import java.rmi.UnexpectedException
import java.util.*
import kotlin.comparisons.compareBy
@@ -44,7 +43,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
result = codeBuilder.loadAndGetVariable(result)
}
if (result.type is LLVMReferenceType) {
genReferenceReturn(result)
generateReferenceReturn(result)
} else {
codeBuilder.addReturnOperator(result)
}
@@ -123,9 +122,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return evaluateConstructorCallExpression(LLVMVariable(structCodegen.fullName + LLVMType.mangleFunctionArguments(names), structCodegen.type, scope = LLVMVariableScope()), args)
}
private fun evaluateThisExpression(): LLVMSingleValue? {
return variableManager["this"]
}
private fun evaluateThisExpression(): LLVMSingleValue? =
variableManager["this"]
fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? {
val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)
@@ -246,11 +244,11 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val standardType = LLVMMapStandardType(receiverType!!.type!!, state)
val targetFunction = state.bindingContext.get(BindingContext.CALL, selector.calleeExpression)
val resolvedCall = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction)
val targetFunctionName = resolvedCall!!.candidateDescriptor.fqNameSafe.convertToNativeName()
val nameWithoutMangling = resolvedCall.candidateDescriptor.name.asString().replace(Regex("""(.?)<init>"""), "")
val candidateDescriptor = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction)!!.candidateDescriptor
val targetFunctionName = candidateDescriptor.fqNameSafe.convertToNativeName()
val nameWithoutMangling = candidateDescriptor.name.asString().replace(Regex("""(.?)<init>"""), "")
val packageNameFirst = targetFunction?.calleeExpression?.getContainingKtFile()?.packageFqName?.convertToNativeName() ?: ""
val packageNameSecond = resolvedCall.candidateDescriptor.containingDeclaration.fqNameSafe.convertToNativeName()
val packageNameSecond = candidateDescriptor.containingDeclaration.fqNameSafe.convertToNativeName()
val names = parseArgList(selector, scopeDepth)
val type = LLVMType.mangleFunctionArguments(names)
@@ -264,12 +262,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
?: throw UnexpectedException(constructedFunctionName)
val receiverExpression = receiverExpressionArgument ?: evaluateExpression(receiver, scopeDepth + 1)!!
val typeThisArgument = when (standardType) {
is LLVMReferenceType -> LLVMVariable("type", standardType, pointer = 1)
else -> LLVMVariable("type", standardType, pointer = 0)
}
val typeThisArgument = LLVMVariable("type", standardType, pointer = if (standardType is LLVMReferenceType) 1 else 0)
val args = mutableListOf(codeBuilder.loadArgumentIfRequired(receiverExpression, typeThisArgument))
val args = mutableListOf(codeBuilder.loadOneArgumentIfRequired(receiverExpression, typeThisArgument))
args.addAll(codeBuilder.loadArgsIfRequired(names, extensionCodegen.args))
return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args)
}
@@ -530,17 +525,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val returnType = function.type
when (returnType) {
is LLVMVoidType -> {
codeBuilder.addLLVMCode(LLVMCall(LLVMVoidType(), function.toString(), names).toString())
codeBuilder.addLLVMCodeToLocalPlace(LLVMCall(LLVMVoidType(), function.toString(), names).toString())
}
is LLVMReferenceType -> {
val returnVar = codeBuilder.getNewVariable(returnType, pointer = 2)
codeBuilder.allocStaticVar(returnVar, pointer = true)
val args = ArrayList<LLVMSingleValue>()
args.add(returnVar)
val args = mutableListOf<LLVMSingleValue>(returnVar)
args.addAll(names)
codeBuilder.addLLVMCode(LLVMCall(LLVMVoidType(), function.toString(), args).toString())
codeBuilder.addLLVMCodeToLocalPlace(LLVMCall(LLVMVoidType(), function.toString(), args).toString())
if (returnVar.pointer == 2) {
return returnVar
} else {
@@ -569,11 +563,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.allocStackVar(result, pointer = true)
codeBuilder.storeVariable(result, store)
val args = ArrayList<LLVMSingleValue>()
args.add(store)
val args = mutableListOf<LLVMSingleValue>(store)
args.addAll(names)
codeBuilder.addLLVMCode(LLVMCall(
codeBuilder.addLLVMCodeToLocalPlace(LLVMCall(
LLVMVoidType(),
function.toString(),
args
@@ -659,13 +652,12 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
codeBuilder.addAssignment(resultOp, llvmExpression)
codeBuilder.storeVariable(firstOp, resultOp)
return oldValue
}
KtTokens.EXCLEXCL -> {
var result = firstOp
codeBuilder.addComment("start EXCLEXCL postfix operator")
val nullLabel = codeBuilder.getNewLabel(prefix = "nullCheck")
val notNullLabel = codeBuilder.getNewLabel(prefix = "nullCheck")
val nullCheck = codeBuilder.nullCheck(firstOp)
@@ -677,7 +669,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
if (firstOp.type.isPrimitive()) {
result = codeBuilder.downLoadArgument(firstOp, 0) as LLVMVariable
}
codeBuilder.addComment("end EXCLEXCL postfix operator")
return result
}
else -> throw UnsupportedOperationException()
@@ -740,6 +731,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
fun addPrimitiveReferenceOperationByName(operator: String, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
return when (operator) {
"||",
"or" -> firstNativeOp.type!!.operatorOr(firstNativeOp, secondNativeOp)
@@ -747,60 +739,23 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
"&&",
"and" -> firstNativeOp.type!!.operatorAnd(firstNativeOp, secondNativeOp)
"%" -> firstNativeOp.type!!.operatorMod(firstNativeOp, secondNativeOp)
"shl" -> {
var secondNativeOpWithRequiredType = secondNativeOp
if (firstNativeOp.type != secondNativeOp.type) {
val convertedExpression = firstNativeOp.type!!.convertFrom(secondNativeOp)
secondNativeOpWithRequiredType = codeBuilder.getNewVariable(convertedExpression.variableType)
codeBuilder.addAssignment(secondNativeOpWithRequiredType, convertedExpression)
}
firstNativeOp.type!!.operatorShl(firstNativeOp, secondNativeOpWithRequiredType)
}
"shr" -> {
var secondNativeOpWithRequiredType = secondNativeOp
if (firstNativeOp.type != secondNativeOp.type) {
val convertedExpression = firstNativeOp.type!!.convertFrom(secondNativeOp)
secondNativeOpWithRequiredType = codeBuilder.getNewVariable(convertedExpression.variableType)
codeBuilder.addAssignment(secondNativeOpWithRequiredType, convertedExpression)
}
firstNativeOp.type!!.operatorShr(firstNativeOp, secondNativeOpWithRequiredType)
}
"ushr" -> {
var secondNativeOpWithRequiredType = secondNativeOp
if (firstNativeOp.type != secondNativeOp.type) {
val convertedExpression = firstNativeOp.type!!.convertFrom(secondNativeOp)
secondNativeOpWithRequiredType = codeBuilder.getNewVariable(convertedExpression.variableType)
codeBuilder.addAssignment(secondNativeOpWithRequiredType, convertedExpression)
}
firstNativeOp.type!!.operatorUshr(firstNativeOp, secondNativeOpWithRequiredType)
}
"shl" -> firstNativeOp.type!!.operatorShl(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type!!))
"shr" -> firstNativeOp.type!!.operatorShr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type!!))
"ushr" -> firstNativeOp.type!!.operatorUshr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type!!))
"+=" -> {
val llvmExpression = firstNativeOp.type!!.operatorPlus(firstNativeOp, secondNativeOp)
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
codeBuilder.addAssignment(resultOp, llvmExpression)
codeBuilder.storeVariable(firstOp, resultOp)
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type!!.operatorPlus(firstNativeOp, secondNativeOp))
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}")
}
"-=" -> {
val llvmExpression = firstNativeOp.type!!.operatorMinus(firstNativeOp, secondNativeOp)
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
codeBuilder.addAssignment(resultOp, llvmExpression)
codeBuilder.storeVariable(firstOp, resultOp)
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type!!.operatorMinus(firstNativeOp, secondNativeOp))
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}")
}
"*=" -> {
val llvmExpression = firstNativeOp.type!!.operatorTimes(firstNativeOp, secondNativeOp)
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
codeBuilder.addAssignment(resultOp, llvmExpression)
codeBuilder.storeVariable(firstOp, resultOp)
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type!!.operatorTimes(firstNativeOp, secondNativeOp))
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}")
}
"%=" -> {
val llvmExpression = firstNativeOp.type!!.operatorMod(firstNativeOp, secondNativeOp)
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
codeBuilder.addAssignment(resultOp, llvmExpression)
codeBuilder.storeVariable(firstOp, resultOp)
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type!!.operatorMod(firstNativeOp, secondNativeOp))
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}")
}
".." -> {
@@ -814,17 +769,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
}
private fun receivePointedArgument(variable: LLVMSingleValue, pointer: Int): LLVMSingleValue {
var currentVariable = variable
while (currentVariable.pointer > pointer) {
currentVariable = codeBuilder.receiveNativeValue(variable)
}
return currentVariable
}
private fun addPrimitiveBinaryOperation(operator: IElementType, referenceName: KtSimpleNameExpression?, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
val secondNativeOp = codeBuilder.receiveNativeValue(secondOp)
val llvmExpression = when (operator) {
KtTokens.PLUS -> firstOp.type!!.operatorPlus(firstNativeOp, secondNativeOp)
KtTokens.MINUS -> firstOp.type!!.operatorMinus(firstNativeOp, secondNativeOp)
@@ -835,47 +783,39 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
KtTokens.LTEQ -> firstOp.type!!.operatorLeq(firstNativeOp, secondNativeOp)
KtTokens.GTEQ -> firstOp.type!!.operatorGeq(firstNativeOp, secondNativeOp)
KtTokens.EQEQ ->
if (firstOp.type is LLVMReferred)
if (secondOp.type is LLVMReferred) {
val firstPointedArgument = receivePointedArgument(firstOp, 1)
val secondPointedArgument = receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorEq(firstPointedArgument, secondPointedArgument)
} else
firstOp.type!!.operatorEq(firstNativeOp, secondOp)
else
if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) {
val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1)
val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorEq(firstPointedArgument, secondPointedArgument)
} else
firstOp.type!!.operatorEq(firstNativeOp, secondNativeOp)
KtTokens.EQEQEQ -> {
val firstPointedArgument = receivePointedArgument(firstOp, 1)
val secondPointedArgument = receivePointedArgument(secondOp, 1)
val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1)
val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorEq(firstPointedArgument, secondPointedArgument)
}
KtTokens.EXCLEQ -> {
if (firstOp.type is LLVMReferred)
if (secondOp.type is LLVMReferred) {
val firstPointedArgument = receivePointedArgument(firstOp, 1)
val secondPointedArgument = receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorNeq(firstPointedArgument, secondPointedArgument)
} else
firstOp.type!!.operatorNeq(firstNativeOp, secondOp)
else
if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) {
val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1)
val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorNeq(firstPointedArgument, secondPointedArgument)
} else
firstOp.type!!.operatorNeq(firstNativeOp, secondNativeOp)
}
KtTokens.EXCLEQEQEQ -> {
val firstPointedArgument = receivePointedArgument(firstOp, 1)
val secondPointedArgument = receivePointedArgument(secondOp, 1)
val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1)
val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorNeq(firstPointedArgument, secondPointedArgument)
}
KtTokens.EQ -> {
codeBuilder.addComment("start variable assignment")
if (secondOp.type is LLVMNullType) {
codeBuilder.storeNull(firstOp as LLVMVariable)
codeBuilder.addComment("end null variable assignment")
return firstOp
}
val result = firstOp as LLVMVariable
val sourceArgument: LLVMSingleValue
if (secondOp.type!!.isPrimitive() && (secondOp.pointer == 0) && (firstOp.pointer == 2)) {
if ((firstOp.pointer == 2) && secondOp.type!!.isPrimitive() && (secondOp.pointer == 0)) {
sourceArgument = codeBuilder.getNewVariable(secondOp.type!!, 1)
codeBuilder.allocStaticVar(sourceArgument, asValue = true)
codeBuilder.storeVariable(sourceArgument, secondOp)
@@ -884,7 +824,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
codeBuilder.storeVariable(result, sourceArgument)
codeBuilder.addComment("end variable assignment")
return result
}
else -> addPrimitiveReferenceOperation(referenceName!!, firstOp, secondNativeOp)
@@ -905,7 +844,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return when (element) {
is LeafPsiElement -> evaluateLeafPsiElement(element, scopeDepth)
is KtConstantExpression -> evaluateConstantExpression(element)
KtTokens.INTEGER_LITERAL -> null
else -> null
}
}
@@ -927,36 +865,32 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val exitLabel = codeBuilder.getNewLabel(prefix = "for_exit")
val rangeTypeName = (range.type as LLVMReferenceType).type
val descriptor = state.classes[rangeTypeName]
val method = descriptor!!.methods["$rangeTypeName.iterator"] ?: throw UnexpectedException("$rangeTypeName.iterator")
val descriptor = state.classes[rangeTypeName] ?: throw UnexpectedException("Error occurred in evaluating range expression")
val method = descriptor.methods["$rangeTypeName.iterator"] ?: throw UnexpectedException("Cant receive iterator $rangeTypeName.iterator")
val returnType = method.returnType!!.type
val returnTypeName = (returnType as LLVMReferenceType).type
val iteratorDescriptor = state.classes[returnTypeName]
val nextDescriptor = iteratorDescriptor!!.methods["$returnTypeName.nextInt"] ?: throw UnexpectedException("$returnTypeName.hasNext")
val nextDescriptor = iteratorDescriptor!!.methods["$returnTypeName.next"] ?: throw UnexpectedException("$returnTypeName.nextInt")
val conditionIterator = evaluateFunctionCallExpression(LLVMVariable("$rangeTypeName.iterator", returnType, scope = LLVMVariableScope()), listOf(range))!!
val iteratorThisArgument = codeBuilder.loadArgumentIfRequired(conditionIterator, LLVMVariable("type", descriptor.type, pointer = 1))
val iteratorThisArgument = codeBuilder.loadOneArgumentIfRequired(conditionIterator, LLVMVariable("type", descriptor.type, pointer = 1))
codeBuilder.addUnconditionalJump(conditionLabel)
codeBuilder.markWithLabel(conditionLabel)
var conditionResult = evaluateFunctionCallExpression(LLVMVariable("$returnTypeName.hasNext", LLVMBooleanType(), scope = LLVMVariableScope()), listOf(iteratorThisArgument))!!
while (conditionResult.pointer > 0) {
conditionResult = codeBuilder.loadAndGetVariable(conditionResult as LLVMVariable)
}
conditionResult = codeBuilder.downLoadArgument(conditionResult, 0)
codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel)
codeBuilder.addUnconditionalJump(bodyLabel)
codeBuilder.markWithLabel(bodyLabel)
val currentParameter = evaluateFunctionCallExpression(LLVMVariable("$returnTypeName.nextInt", LLVMIntType(), scope = LLVMVariableScope()), listOf(iteratorThisArgument))!!
val loopParameter = state.bindingContext.get(BindingContext.VALUE_PARAMETER, expr.loopParameter!!)?.fqNameSafe?.asString() ?: expr.loopParameter!!.name!!
val loopParameter = evaluateFunctionCallExpression(LLVMVariable("$returnTypeName.next", LLVMIntType(), scope = LLVMVariableScope()), listOf(iteratorThisArgument))!!
val loopParameterDescriptor = state.bindingContext.get(BindingContext.VALUE_PARAMETER, expr.loopParameter!!)?.fqNameSafe?.asString() ?: expr.loopParameter!!.name!!
val allocVar = variableManager.receiveVariable(loopParameter, nextDescriptor.returnType!!.type, LLVMRegisterScope(), pointer =
val allocVar = variableManager.receiveVariable(loopParameterDescriptor, nextDescriptor.returnType!!.type, LLVMRegisterScope(), pointer =
nextDescriptor.returnType!!.pointer + 1)
variableManager.addVariable(loopParameter, allocVar, scopeDepth + 1)
variableManager.addVariable(loopParameterDescriptor, allocVar, scopeDepth + 1)
codeBuilder.allocStackVar(allocVar, pointer = true)
addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, currentParameter)
addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, loopParameter)
evaluateCodeBlock(expr.body, null, conditionLabel, exitLabel, scopeDepth + 1)
codeBuilder.markWithLabel(exitLabel)
@@ -981,7 +915,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
codeBuilder.markWithLabel(nextLabel)
codeBuilder.addComment("last condition item")
codeBuilder.addUnconditionalJump(if (isElse) successConditionsLabel else elseLabel)
codeBuilder.markWithLabel(successConditionsLabel)
@@ -990,12 +923,11 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
successExpression = codeBuilder.loadAndGetVariable(successExpression)
}
if (successExpression != null && resultVariable.type !is LLVMVoidType && resultVariable.type !is LLVMNullType) {
if (successExpression != null && !LLVMType.nullOrVoidType(resultVariable.type)) {
codeBuilder.storeVariable(resultVariable, successExpression)
}
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.addComment("end last condition item")
}
private fun evaluateWhenExpression(expr: KtWhenExpression, scopeDepth: Int): LLVMVariable? {
@@ -1004,7 +936,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
val expressionType = LLVMMapStandardType(kotlinType, state)
val targetExpression = evaluateExpression(whenExpression, scopeDepth + 1)!!
val targetExpression = evaluateExpression(whenExpression, scopeDepth + 1) ?: LLVMConstant("true", LLVMBooleanType())
val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1)
when (expressionType) {
@@ -1019,18 +951,14 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val endLabel = codeBuilder.getNewLabel(prefix = "when_end")
codeBuilder.addUnconditionalJump(nextLabel)
for (item in expr.entries) {
codeBuilder.addComment("start new when item")
codeBuilder.markWithLabel(nextLabel)
nextLabel = codeBuilder.getNewLabel(prefix = "when_item")
evaluateWhenItem(item, targetExpression, resultVariable, nextLabel, endLabel, item.isElse, scopeDepth + 1)
codeBuilder.addComment("end new when item")
}
codeBuilder.addComment("else branch of when expression")
codeBuilder.markWithLabel(nextLabel)
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(endLabel)
codeBuilder.addComment("end when expression")
return resultVariable
}
@@ -1057,7 +985,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
private fun evaluateIfOperator(element: KtIfExpression, scopeDepth: Int, isExpression: Boolean = true): LLVMVariable? {
codeBuilder.addComment("begin evaluate if")
val conditionResult = evaluateExpression(element.condition, scopeDepth)!!
val conditionNativeResult = codeBuilder.downLoadArgument(conditionResult, 0)
@@ -1072,7 +999,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val expressionType = LLVMInstanceOfStandardType("type", kotlinType, LLVMVariableScope(), state).type
val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1)
codeBuilder.addComment("start if expression")
when (resultVariable.type) {
is LLVMReferenceType -> codeBuilder.allocStaticVar(resultVariable, asValue = true)
else -> codeBuilder.allocStackVar(resultVariable, asValue = true)
@@ -1083,18 +1009,17 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
codeBuilder.markWithLabel(thenLabel)
val thenResultExpression = evaluateExpression(thenExpression, scopeDepth + 1) ?: return null
val thenResultExpression = evaluateExpression(thenExpression, scopeDepth + 1) ?: throw UnexpectedException("Can't evaluate then in if expression")
val thenResultNativeExpression = codeBuilder.receiveNativeValue(thenResultExpression)
codeBuilder.storeVariable(resultVariable, thenResultNativeExpression)
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(elseLabel)
val elseResultExpression = evaluateExpression(elseExpression, scopeDepth + 1) ?: return null
val elseResultExpression = evaluateExpression(elseExpression, scopeDepth + 1) ?: throw UnexpectedException("Can't evaluate else in if expression")
val elseResultNativeExpression = codeBuilder.receiveNativeValue(elseResultExpression)
codeBuilder.storeVariable(resultVariable, elseResultNativeExpression)
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(endLabel)
codeBuilder.addComment("end if expression")
return resultVariable
}
@@ -1103,7 +1028,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
val endLabel = codeBuilder.getNewLabel(prefix = "if")
codeBuilder.addComment("start if operator")
codeBuilder.addCondition(conditionResult, thenLabel, if (elseExpression != null) elseLabel else endLabel)
evaluateCodeBlock(thenExpression, thenLabel, endLabel, endLabel, scopeDepth + 1)
@@ -1112,7 +1036,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
codeBuilder.markWithLabel(endLabel)
codeBuilder.addComment("end if operator")
return null
}
@@ -1123,7 +1046,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val assignExpression = evaluateExpression(element.delegateExpressionOrInitializer, scopeDepth)
val expectedExpressionType = LLVMInstanceOfStandardType("", variable.type, state = state)
val primitivePointer = LLVMMapStandardType(variable.type, state) !is LLVMReferred
val primitivePointer = !LLVMType.isReferredType(LLVMMapStandardType(variable.type, state))
val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer = expectedExpressionType.pointer + 1)
codeBuilder.allocStackVar(allocVar, pointer = true)
@@ -1145,14 +1068,14 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val type = retVar?.type ?: LLVMVoidType()
when (type) {
is LLVMReferenceType -> genReferenceReturn(retVar!!)
is LLVMReferenceType -> generateReferenceReturn(retVar!!)
is LLVMNullType -> {
retVar = when (retVar) {
is LLVMConstant -> LLVMConstant(retVar.value, LLVMNullType(returnType!!.type), returnType!!.pointer - 1)
is LLVMVariable -> LLVMVariable(retVar.label, LLVMNullType(returnType!!.type), retVar.kotlinName, retVar.scope, returnType!!.pointer - 1)
else -> throw IllegalStateException()
else -> throw UnexpectedException("Unknown inheritor of LLVMSingleValue")
}
genReferenceReturn(retVar)
generateReferenceReturn(retVar)
}
is LLVMVoidType -> {
codeBuilder.addAnyReturn(LLVMVoidType())
@@ -1168,7 +1091,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return null
}
private fun genReferenceReturn(retVar: LLVMSingleValue) {
private fun generateReferenceReturn(retVar: LLVMSingleValue) {
var result = retVar
if (result.pointer == 2) {
result = codeBuilder.loadAndGetVariable(retVar as LLVMVariable)
@@ -134,7 +134,7 @@ class FunctionCodegen(state: TranslationState,
actualArgs.addAll(args)
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName, actualArgs, actualReturnType, external))
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(fullName, actualArgs, actualReturnType, external))
}
private fun generateLoadArguments() {
@@ -149,7 +149,7 @@ abstract class StructCodegen(val state: TranslationState,
argFields.addAll(secondaryConstructorArguments)
val currentConstructorIndex = LLVMType.mangleFunctionArguments(secondaryConstructorArguments)
constructorFields.put(currentConstructorIndex, argFields)
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName + currentConstructorIndex, argFields, LLVMVoidType()))
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(fullName + currentConstructorIndex, argFields, LLVMVoidType()))
codeBuilder.addStartExpression()
@@ -175,7 +175,7 @@ abstract class StructCodegen(val state: TranslationState,
argFields.add(classVal)
argFields.addAll(constructorFields[primaryConstructorIndex]!!)
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName + primaryConstructorIndex, argFields, LLVMVoidType()))
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(fullName + primaryConstructorIndex, argFields, LLVMVoidType()))
codeBuilder.addStartExpression()
generateLoadArguments(classVal)
@@ -207,8 +207,7 @@ abstract class StructCodegen(val state: TranslationState,
codeBuilder.storeVariable(classField, it)
}
else -> {
val argument = codeBuilder.getNewVariable(it.type, it.pointer)
codeBuilder.loadVariable(argument, LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = it.pointer + 1))
val argument = codeBuilder.loadVariable(LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = it.pointer + 1))
val classField = codeBuilder.getNewVariable(it.type, pointer = 1)
codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
codeBuilder.storeVariable(classField, argument)
@@ -10,19 +10,19 @@ class LLVMBuilder(val arm: Boolean = false) {
private var globalCode: StringBuilder = StringBuilder()
private var variableCount = 0
private var labelCount = 0
var exceptions: Map<String, LLVMVariable> = mapOf()
object UniqueGenerator {
private var unique = 0
fun generateUniqueString() =
".unique." + unique++
}
init {
initBuilder()
}
var exceptions: Map<String, LLVMVariable> = mapOf()
private fun initBuilder() {
val declares = arrayOf(
"declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)",
@@ -31,14 +31,14 @@ class LLVMBuilder(val arm: Boolean = false) {
"%class.Nothing = type { }",
"declare void @abort()")
declares.forEach { globalCode.appendln(it) }
declares.forEach { addLLVMCodeToGlobalPlace(it) }
exceptions = mapOf(
Pair("KotlinNullPointerException", initializeString("Exception in thread main kotlin.KotlinNullPointerException")))
Pair("KotlinNullPointerException", initializeExceptionString("Exception in thread main kotlin.KotlinNullPointerException")))
val funcAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }"""
if (arm) {
globalCode.appendln(funcAttributes)
val functionAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }"""
addLLVMCodeToGlobalPlace(functionAttributes)
}
}
@@ -52,17 +52,20 @@ class LLVMBuilder(val arm: Boolean = false) {
return LLVMLabel("label.$prefix.$labelCount", scope)
}
fun addLLVMCode(code: String) {
localCode.appendln(code)
}
fun addLLVMCodeToLocalPlace(code: String) =
localCode.appendln(code)
fun addStartExpression() {
localCode.appendln("{")
}
fun addEndExpression() {
localCode.appendln("}")
}
fun addLLVMCodeToGlobalPlace(code: String) =
globalCode.appendln(code)
fun addStartExpression() =
addLLVMCodeToLocalPlace("{")
fun addEndExpression() =
addLLVMCodeToLocalPlace("}")
fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue =
when (firstOp) {
@@ -71,36 +74,38 @@ class LLVMBuilder(val arm: Boolean = false) {
else -> throw UnsupportedOperationException()
}
fun receivePointedArgument(variable: LLVMSingleValue, pointer: Int): LLVMSingleValue {
var currentVariable = variable
while (currentVariable.pointer > pointer) {
currentVariable = receiveNativeValue(currentVariable)
}
return currentVariable
}
fun loadArgsIfRequired(names: List<LLVMSingleValue>, args: List<LLVMVariable>) =
names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue {
return loadArgumentIfRequired(value, args[i])
return loadOneArgumentIfRequired(value, args[i])
}).toList()
fun loadArgumentIfRequired(value: LLVMSingleValue, argument: LLVMVariable): LLVMSingleValue {
fun loadOneArgumentIfRequired(value: LLVMSingleValue, argument: LLVMVariable): LLVMSingleValue {
var result = value
while (argument.pointer < result.pointer) {
val currentArgument = getNewVariable(result.type!!, pointer = result.pointer - 1)
loadVariable(currentArgument, result as LLVMVariable)
result = currentArgument
result = loadVariable(result as LLVMVariable)
}
when (value.type) {
is LLVMStringType -> if (!(value.type as LLVMStringType).isLoaded) {
val newVariable = getNewVariable(value.type!!, pointer = result.pointer + 1)
allocStackVar(newVariable, asValue = true)
copyVariable(result as LLVMVariable, newVariable)
result = getNewVariable(argument.type, pointer = newVariable.pointer - 1)
loadVariable(result, newVariable)
}
if ((value.type is LLVMStringType) && (!(value.type as LLVMStringType).isLoaded)) {
val newVariable = getNewVariable(value.type!!, pointer = result.pointer + 1)
allocStackVar(newVariable, asValue = true)
copyVariable(result as LLVMVariable, newVariable)
result = loadVariable(newVariable)
}
return result
}
fun downLoadArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue =
loadArgumentIfRequired(value, LLVMVariable("", value.type!!, pointer = pointer))
loadOneArgumentIfRequired(value, LLVMVariable("", value.type!!, pointer = pointer))
fun clean() {
localCode = StringBuilder()
@@ -108,27 +113,36 @@ class LLVMBuilder(val arm: Boolean = false) {
initBuilder()
}
fun addAssignment(lhs: LLVMVariable, rhs: LLVMNode) {
localCode.appendln("$lhs = $rhs")
}
fun addAssignment(lhs: LLVMVariable, rhs: LLVMNode) =
addLLVMCodeToLocalPlace("$lhs = $rhs")
fun addReturnOperator(llvmVariable: LLVMSingleValue) {
localCode.appendln("ret ${llvmVariable.type} $llvmVariable")
}
fun addAnyReturn(type: LLVMType, value: String = type.defaultValue, pointer: Int = 0) {
localCode.appendln("ret $type${"*".repeat(pointer)} $value")
}
fun addReturnOperator(llvmVariable: LLVMSingleValue) =
addLLVMCodeToLocalPlace("ret ${llvmVariable.type} $llvmVariable")
private fun initializeString(string: String): LLVMVariable {
fun addAnyReturn(type: LLVMType, value: String = type.defaultValue, pointer: Int = 0) =
addLLVMCodeToLocalPlace("ret $type${"*".repeat(pointer)} $value")
private fun initializeExceptionString(string: String): LLVMVariable {
val result = getNewVariable(LLVMStringType(string.length), pointer = 0, scope = LLVMVariableScope(), prefix = "exceptions.str.")
addStringConstant(result, string)
return result
}
fun addStringConstant(variable: LLVMVariable, value: String) {
val type = variable.type as LLVMStringType
globalCode.appendln("$variable = private unnamed_addr constant ${type.fullType()} c\"${value.replace("\"", "\\\"")}\\00\", align 1")
fun addStringConstant(variable: LLVMVariable, value: String) =
addLLVMCodeToGlobalPlace("$variable = private unnamed_addr constant ${(variable.type as LLVMStringType).fullType()} c\"${value.replace("\"", "\\\"")}\\00\", align 1")
fun convertVariableToType(variable: LLVMSingleValue, targetType: LLVMType): LLVMSingleValue {
var resultVariable = variable
if (variable.type != targetType) {
val convertedExpression = targetType.convertFrom(variable)
resultVariable = getNewVariable(convertedExpression.variableType)
addAssignment(resultVariable, convertedExpression)
}
return resultVariable
}
fun addGlobalInitialize(target: LLVMVariable, fields: ArrayList<LLVMVariable>, initializers: Map<LLVMVariable, String>, classType: LLVMType) {
@@ -139,64 +153,60 @@ class LLVMBuilder(val arm: Boolean = false) {
}
fun storeString(target: LLVMVariable, source: LLVMVariable, offset: Int) {
val stringType = source.type as LLVMStringType
val code = "store ${target.type} getelementptr inbounds (" +
"${stringType.fullType()}* $source, i32 0, i32 $offset), ${target.getType()} $target, align ${stringType.align}"
"${(source.type as LLVMStringType).fullType()}* $source, i32 0, i32 $offset), ${target.getType()} $target, align ${source.type.align}"
(target.type as LLVMStringType).isLoaded = true
localCode.appendln(code)
}
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) {
val code = "$target = getelementptr inbounds ${source.getType()} $source, i32 0, i32 $offset"
localCode.appendln(code)
}
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) =
addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.getType()} $source, i32 0, i32 $offset")
fun markWithLabel(label: LLVMLabel?) {
if (label != null)
localCode.appendln("${label.label}:")
addLLVMCodeToLocalPlace("${label.label}:")
}
fun storeVariable(target: LLVMSingleValue, source: LLVMSingleValue) {
if ((source.type is LLVMStringType) && (!(source.type as LLVMStringType).isLoaded)) {
storeString(target as LLVMVariable, source as LLVMVariable, 0)
} else {
val code = "store ${source.getType()} $source, ${target.getType()} $target, align ${source.type?.align!!}"
localCode.appendln(code)
}
fun storeVariable(target: LLVMSingleValue, source: LLVMSingleValue) =
if ((source.type is LLVMStringType) && (!(source.type as LLVMStringType).isLoaded)) {
storeString(target as LLVMVariable, source as LLVMVariable, 0)
} else {
addLLVMCodeToLocalPlace("store ${source.getType()} $source, ${target.getType()} $target, align ${source.type?.align!!}")
}
fun storeExpression(target: LLVMSingleValue, expression: LLVMExpression): LLVMVariable {
val resultOp = getNewVariable(expression.variableType)
addAssignment(resultOp, expression)
storeVariable(target, resultOp)
return resultOp
}
fun storeNull(result: LLVMVariable) {
val code = "store ${result.getType().dropLast(1)} null, ${result.getType()} $result, align ${TranslationState.pointerAlign}"
localCode.appendln(code)
}
fun storeNull(result: LLVMVariable) =
addLLVMCodeToLocalPlace("store ${result.getType().dropLast(1)} null, ${result.getType()} $result, align ${TranslationState.pointerAlign}")
fun nullCheck(variable: LLVMVariable): LLVMVariable {
val result = getNewVariable(LLVMBooleanType(), pointer = 0)
val loaded = loadVariable(variable)
val loaded = getNewVariable(variable.type, pointer = variable.pointer - 1)
loadVariable(loaded, variable)
val code = "$result = icmp eq ${loaded.getType()} null, $loaded"
localCode.appendln(code)
addLLVMCodeToLocalPlace("$result = icmp eq ${loaded.getType()} null, $loaded")
return result
}
fun addComment(comment: String) {
localCode.appendln("; " + comment)
}
fun addComment(comment: String) =
addLLVMCodeToLocalPlace("; " + comment)
fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) {
val code = "$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}"
localCode.appendln(code)
}
fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) =
addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}")
fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) {
private fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) {
var from = source
if (source.pointer > 0) {
from = getNewVariable(source.type, source.pointer)
localCode.appendln("$from = load ${source.getType()} $source, align ${from.type.align}")
addLLVMCodeToLocalPlace("$from = load ${source.getType()} $source, align ${from.type.align}")
}
localCode.appendln("store ${target.type} $from, ${target.getType()} $target, align ${from.type.align}")
addLLVMCodeToLocalPlace("store ${target.type} $from, ${target.getType()} $target, align ${from.type.align}")
}
fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) {
@@ -210,38 +220,37 @@ class LLVMBuilder(val arm: Boolean = false) {
return allocVar
}
fun loadVariable(target: LLVMVariable, source: LLVMVariable) {
val code = "$target = load ${source.getType()} $source, align ${target.type.align}"
localCode.appendln(code)
fun loadVariable(source: LLVMVariable): LLVMVariable {
val target = getNewVariable(source.type, pointer = source.pointer - 1)
addLLVMCodeToLocalPlace("$target = load ${source.getType()} $source, align ${target.type.align}")
return target
}
fun allocStackVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) {
val type = if (asValue) target.type.toString() else target.getType()
localCode.appendln("$target = alloca ${if (pointer) type.removeSuffix("*") else type}, align ${target.type.align}")
addLLVMCodeToLocalPlace("$target = alloca ${if (pointer) type.removeSuffix("*") else type}, align ${target.type.align}")
}
fun allocStaticVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) {
val allocated = getNewVariable(LLVMCharType(), pointer = 1)
val size = if ((target.pointer >= 2) || (target.pointer >= 1 && !pointer)) TranslationState.pointerSize else target.type.size
val alloc = "$allocated = call i8* @malloc_heap(i32 $size)"
localCode.appendln(alloc)
addLLVMCodeToLocalPlace("$allocated = call i8* @malloc_heap(i32 $size)")
val cast = "$target = bitcast ${allocated.getType()} $allocated to ${if (asValue) target.type.toString() else target.getType()}" + if (pointer) "" else "*"
localCode.appendln(cast)
addLLVMCodeToLocalPlace("$target = bitcast ${allocated.getType()} $allocated to ${if (asValue) target.type.toString() else target.getType()}" + if (pointer) "" else "*")
}
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) {
localCode.appendln("$targetVariable = alloca ${sourceVariable.type}${"*".repeat(sourceVariable.pointer)}, align ${sourceVariable.type.align}")
addLLVMCodeToLocalPlace("$targetVariable = alloca ${sourceVariable.getType()}, align ${sourceVariable.type.align}")
if (store) {
localCode.appendln("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type.align}")
addLLVMCodeToLocalPlace("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type.align}")
}
}
fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) {
localCode.appendln("$variable = global ${variable.getType()} $defaultValue, align ${variable.type.align}")
}
fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) =
addLLVMCodeToLocalPlace("$variable = global ${variable.getType()} $defaultValue, align ${variable.type.align}")
fun makeStructInitializer(args: List<LLVMVariable>, values: List<String>)
= "{ ${args.mapIndexed { i: Int, variable: LLVMVariable -> "${variable.type} ${values[i]}" }.joinToString()} }"
@@ -249,49 +258,45 @@ class LLVMBuilder(val arm: Boolean = false) {
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
assert(source.pointer > 0)
val target = getNewVariable(source.type, source.pointer - 1, source.kotlinName)
val code = "$target = load ${source.getType()} $source, align ${target.type.align}"
localCode.appendln(code)
addLLVMCodeToLocalPlace("$target = load ${source.getType()} $source, align ${target.type.align}")
return target
}
fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) {
localCode.appendln("br ${condition.getType()} $condition, label $thenLabel, label $elseLabel")
}
fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) =
addLLVMCodeToLocalPlace("br ${condition.getType()} $condition, label $thenLabel, label $elseLabel")
fun addUnconditionalJump(label: LLVMLabel) {
localCode.appendln("br label $label")
}
fun createClass(name: String, fields: List<LLVMVariable>) {
val code = "%class.$name = type { ${fields.map { it.getType() }.joinToString()} }"
globalCode.appendln(code)
}
fun addUnconditionalJump(label: LLVMLabel) =
addLLVMCodeToLocalPlace("br label $label")
fun createClass(name: String, fields: List<LLVMVariable>) =
addLLVMCodeToGlobalPlace("%class.$name = type { ${fields.map { it.getType() }.joinToString()} }")
fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable {
val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer)
val code = "$empty = bitcast ${src.getType()} $src to ${llvmType.getType()}"
localCode.appendln(code)
addLLVMCodeToLocalPlace("$empty = bitcast ${src.getType()} $src to ${llvmType.getType()}")
return empty
}
fun addExceptionCall(exceptionName: String) {
val exception = exceptions[exceptionName]
val printResult = getNewVariable(LLVMIntType(), pointer = 0)
localCode.appendln("$printResult = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds (${(exception!!.type as LLVMStringType).fullType()}* $exception, i32 0, i32 0))")
addLLVMCodeToLocalPlace("$printResult = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds (${(exception!!.type as LLVMStringType).fullType()}* $exception, i32 0, i32 0))")
addFunctionCall(LLVMVariable("abort", LLVMVoidType(), scope = LLVMVariableScope()), emptyList())
}
fun addFunctionCall(functionName: LLVMVariable, arguments: List<LLVMVariable>) {
localCode.appendln("call ${functionName.type} $functionName(${arguments.joinToString { it -> "${it.type} $it" }})")
}
fun addFunctionCall(functionName: LLVMVariable, arguments: List<LLVMVariable>) =
addLLVMCodeToLocalPlace("call ${functionName.type} $functionName(${arguments.joinToString { it -> "${it.type} $it" }})")
fun memcpy(castedDst: LLVMVariable, castedSrc: LLVMVariable, size: Int, align: Int = 4, volatile: Boolean = false) =
addLLVMCodeToLocalPlace("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)"
localCode.appendln(code)
}
fun declareEntryPoint(name: String) {
localCode.appendln("define weak void @main()")
addLLVMCodeToLocalPlace("define weak void @main()")
addStartExpression()
addFunctionCall(LLVMVariable(name, LLVMVoidType(), scope = LLVMVariableScope()), listOf())
addAnyReturn(LLVMVoidType())
@@ -1,22 +1,19 @@
package org.kotlinnative.translator.llvm.types
class LLVMNullType(var basetype: LLVMType? = null) : LLVMReferred, LLVMType() {
override val align: Int = 1
override var size: Int = 0
override val defaultValue: String = "null"
class LLVMNullType(var baseType: LLVMType? = null) : LLVMType() {
override val align = 1
override var size = 0
override val defaultValue = "null"
override val typename = baseType?.typename ?: ""
override fun mangle() = ""
override val typename = basetype?.typename ?: ""
override fun equals(other: Any?): Boolean {
return other is LLVMNullType
}
override fun parseArg(inputArg: String) = "null"
override fun toString() = baseType?.toString() ?: ""
override fun equals(other: Any?): Boolean =
other is LLVMNullType
override fun hashCode() =
"null".hashCode()
override fun toString() = basetype?.toString() ?: ""
}
}
@@ -9,30 +9,26 @@ class LLVMReferenceType(val type: String,
var prefix: String = "",
override var align: Int = TranslationState.pointerAlign,
override var size: Int = TranslationState.pointerSize,
var byRef: Boolean = true) : LLVMReferred, LLVMType() {
var byRef: Boolean = true) : LLVMType() {
override val defaultValue: String = "null"
override val typename: String
get() = "$prefix${if (prefix.length > 0) "." else ""}" +
"$type"
override fun toString() = "%$typename"
override fun mangle() = "Ref_$type"
val location = ArrayList<String>()
override fun mangle() = "Ref_$type"
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "icmp ne ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
override fun equals(other: Any?): Boolean {
return (other is LLVMReferenceType) and (typename.equals((other as LLVMReferenceType).typename))
}
override fun equals(other: Any?) =
(other is LLVMReferenceType) and (typename.equals((other as LLVMReferenceType).typename))
override fun hashCode() =
typename.hashCode()
@@ -1,4 +0,0 @@
package org.kotlinnative.translator.llvm.types
interface LLVMReferred {
}
@@ -4,6 +4,7 @@ import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
class LLVMShortType() : LLVMType() {
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMBooleanType(), "icmp slt i16 $firstOp, $secondOp")
@@ -28,18 +29,18 @@ class LLVMShortType() : LLVMType() {
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
LLVMExpression(LLVMShortType(), "sdiv i16 $firstOp, $secondOp")
override fun equals(other: Any?): Boolean {
return other is LLVMShortType
}
override var size: Int = 2
override val align = 2
override val defaultValue = "0"
override val typename = "i16"
override fun mangle() = "Short"
override val typename = "i16"
override fun isPrimitive() = true
override fun equals(other: Any?) =
other is LLVMShortType
override fun hashCode() =
mangle().hashCode()
}
}
@@ -5,21 +5,20 @@ class LLVMStringType(override val length: Int, var isLoaded: Boolean = true) : L
override var size: Int = 1
override val align = 8
override val defaultValue = ""
override val typename = "i8*"
override fun mangle() = "String"
override fun basicType() = LLVMCharType()
override fun fullType() = "[${length + 1} x i8]"
override fun equals(other: Any?): Boolean =
override fun equals(other: Any?) =
when (other) {
is LLVMStringType -> this.length == other.length
else -> false
}
override fun hashCode() =
length * 31 + if (isLoaded) 1 else 0 +
mangle().hashCode()
override fun basicType() = LLVMCharType()
override val typename = "i8*"
override fun fullType() = "[${length + 1} x i8]"
override fun hashCode(): Int {
return length * 31 + if (isLoaded) 1 else 0 +
mangle().hashCode()
}
}
}
@@ -25,18 +25,17 @@ abstract class LLVMType() : Cloneable {
open fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorInc(firstOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun operatorDec(firstOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
open fun parseArg(inputArg: String) = inputArg
open fun convertFrom(source: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
abstract fun mangle(): String
open fun mangle(): String = throw UnimplementedException()
open fun isPrimitive(): Boolean = false
override fun toString() = typename
abstract val align: Int
abstract val typename: String
override fun toString() = typename
abstract var size: Int
abstract val defaultValue: String
open fun isPrimitive(): Boolean = false
companion object {
fun mangleFunctionArguments(names: List<LLVMSingleValue>) =
@@ -44,18 +43,12 @@ abstract class LLVMType() : Cloneable {
fun mangleFunctionTypes(names: List<LLVMType>) =
if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.mangle() })}" else ""
fun nullOrVoidType(type: LLVMType): Boolean =
(type is LLVMNullType) or (type is LLVMVoidType)
fun isReferredType(type: LLVMType?): Boolean =
(type is LLVMNullType) or (type is LLVMReferenceType)
}
}
fun parseLLVMType(type: String): LLVMType = when (type) {
"i64" -> LLVMLongType()
"i32" -> LLVMIntType()
"i16" -> LLVMShortType()
"i8" -> LLVMCharType()
"i1" -> LLVMBooleanType()
"double" -> LLVMDoubleType()
"float" -> LLVMFloatType()
"Unit" -> LLVMVoidType()
else -> LLVMReferenceType(type)
}
}
@@ -1,9 +0,0 @@
package org.kotlinnative.translator.llvm.types
//TODO skeleton for typeList
enum class LLVMTypes {
int, double, float, char
}
val typesMap = mapOf(Pair(LLVMTypes.int, ::LLVMIntType))
@@ -3,17 +3,16 @@ package org.kotlinnative.translator.llvm.types
class LLVMVoidType() : LLVMType() {
override val align = 0
override var size: Int = 0
override var size = 0
override val defaultValue = ""
override fun mangle() = ""
override val typename = "void"
override fun equals(other: Any?): Boolean {
return other is LLVMVoidType
}
override fun mangle() = ""
override fun equals(other: Any?) =
other is LLVMVoidType
override fun hashCode() =
typename.hashCode()
}
}