translator: refactor LLVMBuilder and LLVMCodegen
This commit is contained in:
@@ -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() ?: ""
|
||||
}
|
||||
}
|
||||
+6
-10
@@ -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()
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user