From ddaf41e214097def03f687b435f113b1263d30b9 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Tue, 30 Aug 2016 11:41:09 +0300 Subject: [PATCH] translator: refactor LLVMBuilder and LLVMCodegen --- kotstd/include/Iterators.kt | 2 + .../kotlinnative/translator/BlockCodegen.kt | 193 +++++---------- .../translator/FunctionCodegen.kt | 2 +- .../kotlinnative/translator/StructCodegen.kt | 7 +- .../translator/llvm/LLVMBuilder.kt | 229 +++++++++--------- .../translator/llvm/types/LLVMNullType.kt | 23 +- .../llvm/types/LLVMReferenceType.kt | 16 +- .../translator/llvm/types/LLVMReferred.kt | 4 - .../translator/llvm/types/LLVMShortType.kt | 13 +- .../translator/llvm/types/LLVMStringType.kt | 17 +- .../translator/llvm/types/LLVMType.kt | 29 +-- .../translator/llvm/types/LLVMTypes.kt | 9 - .../translator/llvm/types/LLVMVoidType.kt | 13 +- 13 files changed, 229 insertions(+), 328 deletions(-) delete mode 100644 translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferred.kt delete mode 100644 translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMTypes.kt diff --git a/kotstd/include/Iterators.kt b/kotstd/include/Iterators.kt index a1891334dcd..836b06babe9 100644 --- a/kotstd/include/Iterators.kt +++ b/kotstd/include/Iterators.kt @@ -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 { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index c326bd34010..6de9080194c 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -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("""(.?)"""), "") + val candidateDescriptor = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction)!!.candidateDescriptor + val targetFunctionName = candidateDescriptor.fqNameSafe.convertToNativeName() + val nameWithoutMangling = candidateDescriptor.name.asString().replace(Regex("""(.?)"""), "") 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() - args.add(returnVar) + val args = mutableListOf(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() - args.add(store) + val args = mutableListOf(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) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index 82d8d56692c..5e3a9c13f0d 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -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() { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt index d3412fbbcda..1aaa9813708 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt @@ -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) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt index e55ee07508e..9e1da5c5efe 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -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 = mapOf() object UniqueGenerator { private var unique = 0 fun generateUniqueString() = ".unique." + unique++ + } init { initBuilder() } - var exceptions: Map = 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, args: List) = 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, initializers: Map, 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, values: List) = "{ ${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) { - 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) = + 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) { - localCode.appendln("call ${functionName.type} $functionName(${arguments.joinToString { it -> "${it.type} $it" }})") - } + fun addFunctionCall(functionName: LLVMVariable, arguments: List) = + 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()) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMNullType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMNullType.kt index ba938d56bf7..48ad96254e0 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMNullType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMNullType.kt @@ -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() ?: "" -} +} \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt index fab4d607a96..7b973ea7b0b 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt @@ -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() - 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() diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferred.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferred.kt deleted file mode 100644 index 29cad384926..00000000000 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferred.kt +++ /dev/null @@ -1,4 +0,0 @@ -package org.kotlinnative.translator.llvm.types - -interface LLVMReferred { -} \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMShortType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMShortType.kt index deb5817446a..2d0be10a0de 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMShortType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMShortType.kt @@ -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() -} +} \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMStringType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMStringType.kt index 14c91e9aeec..d155eddbba0 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMStringType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMStringType.kt @@ -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() - } -} +} \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt index f7d1492c6a2..e67226e1567 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt @@ -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) = @@ -44,18 +43,12 @@ abstract class LLVMType() : Cloneable { fun mangleFunctionTypes(names: List) = 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) -} +} \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMTypes.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMTypes.kt deleted file mode 100644 index f66b9bc5504..00000000000 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMTypes.kt +++ /dev/null @@ -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)) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMVoidType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMVoidType.kt index 6a63e9f929a..4097b1cf985 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMVoidType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMVoidType.kt @@ -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() -} +} \ No newline at end of file