From baddaa075576d0658d80d928f285f9f27b2612a5 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Wed, 31 Aug 2016 18:06:16 +0300 Subject: [PATCH] translator: complex refactoring, merge functions in LLVMBuilder, delete unused parts of code --- .../src/main/kotlin/DefaultArguments.kt | 3 +- translator/src/main/kotlin/main.kt | 14 +- .../kotlinnative/translator/BlockCodegen.kt | 281 +++++++----------- .../kotlinnative/translator/ClassCodegen.kt | 7 +- .../translator/FunctionCodegen.kt | 35 +-- .../kotlinnative/translator/ObjectCodegen.kt | 7 +- .../translator/ProjectTranslator.kt | 10 +- .../kotlinnative/translator/StructCodegen.kt | 38 +-- .../translator/TranslationState.kt | 8 +- .../translator/VariableManager.kt | 15 +- .../translator/llvm/LLVMBuilder.kt | 152 ++++------ .../kotlinnative/translator/llvm/LLVMCall.kt | 3 +- .../translator/llvm/LLVMClassVariable.kt | 1 - .../translator/llvm/LLVMConstant.kt | 8 +- .../translator/llvm/LLVMExpression.kt | 2 +- .../kotlinnative/translator/llvm/LLVMLabel.kt | 2 +- .../kotlinnative/translator/llvm/LLVMScope.kt | 2 +- .../translator/llvm/LLVMVariable.kt | 2 +- .../translator/llvm/generators.kt | 9 +- .../translator/llvm/types/LLVMFloatType.kt | 26 +- .../translator/llvm/types/LLVMIntType.kt | 2 +- .../translator/llvm/types/LLVMLongType.kt | 2 +- .../translator/llvm/types/LLVMNullType.kt | 6 +- .../llvm/types/LLVMReferenceType.kt | 4 +- 24 files changed, 257 insertions(+), 382 deletions(-) diff --git a/translator/src/main/kotlin/DefaultArguments.kt b/translator/src/main/kotlin/DefaultArguments.kt index de4f61bc078..f54bd2b048b 100644 --- a/translator/src/main/kotlin/DefaultArguments.kt +++ b/translator/src/main/kotlin/DefaultArguments.kt @@ -12,7 +12,8 @@ class DefaultArguments(raw: RawArguments) : Arguments(raw, name = "default") { val arm = optionalFlag( name = "arm", description = "enable arm build", - aliasNames = listOf("arm") + aliasNames = listOf("arm"), + default = false ) val output = optionalParameter( diff --git a/translator/src/main/kotlin/main.kt b/translator/src/main/kotlin/main.kt index 72d357a13e4..82a89f20e3a 100644 --- a/translator/src/main/kotlin/main.kt +++ b/translator/src/main/kotlin/main.kt @@ -3,24 +3,18 @@ import com.jshmrsn.karg.parseArguments import org.kotlinnative.translator.ProjectTranslator import org.kotlinnative.translator.parseAndAnalyze import java.io.* -import java.util.* fun main(args: Array) { val arguments = parseArguments(args, ::DefaultArguments) val disposer = Disposer.newDisposable() - val analyzedFiles = ArrayList() - - val stdlib = mutableListOf() + val analyzedFiles = arguments.sources.toMutableList() if (arguments.includeDir != null) { - val libraryFile = File(arguments.includeDir).walk().filter { !it.isDirectory }.map { it.absolutePath } - stdlib.addAll(libraryFile) - analyzedFiles.addAll(stdlib) + val libraryFiles = File(arguments.includeDir).walk().filter { !it.isDirectory }.map { it.absolutePath } + analyzedFiles.addAll(libraryFiles) } - analyzedFiles.addAll(arguments.sources) - - val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm ?: false) + val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm) val files = state.environment.getSourceFiles() val code = ProjectTranslator(files, state).generateCode() diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index c744a961f6a..5e8cb735e70 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -26,7 +26,7 @@ import kotlin.comparisons.compareBy abstract class BlockCodegen(val state: TranslationState, val variableManager: VariableManager, val codeBuilder: LLVMBuilder) { - val topLevel = 2 + val topLevelScopeDepth = 2 var returnType: LLVMVariable? = null var wasReturnOnTopLevel = false @@ -38,12 +38,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va var result = evaluateExpression(expr, scopeDepth) ?: throw UnexpectedException("Can't evaluate expression " + expr!!.text) when (result) { is LLVMVariable -> { - if (result.pointer == 1 && result.type !is LLVMReferenceType) { - result = codeBuilder.loadAndGetVariable(result) - } if (result.type is LLVMReferenceType) { generateReferenceReturn(result) } else { + result = codeBuilder.receivePointedArgument(result, 0) codeBuilder.addReturnOperator(result) } } @@ -105,9 +103,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va is KtThisExpression -> evaluateThisExpression() is KtSafeQualifiedExpression -> evaluateSafeAccessExpression(expr, scopeDepth) is KtParenthesizedExpression -> evaluateExpression(expr.expression, scopeDepth) + null, is PsiWhiteSpace -> null is PsiElement -> evaluatePsiElement(expr, scopeDepth) - null -> null else -> throw UnsupportedOperationException() } } @@ -123,10 +121,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va variableManager["this"] fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? { - val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr) - val type = (receiveValue as TypedCompileTimeConstant).type - val value = receiveValue.getValue(type) ?: return null - val variable = variableManager.receiveVariable(".str" + LLVMBuilder.UniqueGenerator.generateUniqueString(), LLVMStringType(value.toString().length, isLoaded = false), LLVMVariableScope(), pointer = 0) + val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr) as TypedCompileTimeConstant + val value = receiveValue.getValue(receiveValue.type) ?: return null + val variable = variableManager.receiveVariable(".str", LLVMStringType(value.toString().length, isLoaded = false), LLVMVariableScope(), pointer = 0) codeBuilder.addStringConstant(variable, value.toString()) return variable @@ -134,7 +131,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? { val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!! - val result = LLVMInstanceOfStandardType(expr.text.substring(2), kotlinType, LLVMVariableScope(), state) + val result = LLVMInstanceOfStandardType(expr.callableReference.text, kotlinType, LLVMVariableScope(), state) return LLVMVariable("${result.label}${(result.type as LLVMFunctionType).mangleArgs()}", result.type, result.kotlinName, result.scope, result.pointer) } @@ -146,27 +143,22 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val loadedLeft = codeBuilder.receiveNativeValue(left) val expectedType = LLVMMapStandardType(state.bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expr)!!, state) as LLVMReferenceType - if (state.classes.containsKey(expectedType.type)) { - expectedType.prefix = "class" - } - val result = codeBuilder.getNewVariable(expectedType, pointer = 2) codeBuilder.allocStaticVar(result, pointer = true) val condition = left.type.operatorEq(loadedLeft, LLVMVariable("", LLVMNullType())) - val thenLabel = codeBuilder.getNewLabel(prefix = "safe.access") - val elseLabel = codeBuilder.getNewLabel(prefix = "safe.access") + val nullLabel = codeBuilder.getNewLabel(prefix = "safe.access") + val notNullLabel = codeBuilder.getNewLabel(prefix = "safe.access") val endLabel = codeBuilder.getNewLabel(prefix = "safe.access") - val conditionResult = codeBuilder.getNewVariable(condition.variableType) - codeBuilder.addAssignment(conditionResult, condition) - codeBuilder.addCondition(conditionResult, thenLabel, elseLabel) + val conditionResult = codeBuilder.storeExpression(condition) + codeBuilder.addCondition(conditionResult, nullLabel, notNullLabel) - codeBuilder.markWithLabel(thenLabel) + codeBuilder.markWithLabel(nullLabel) codeBuilder.storeNull(result) codeBuilder.addUnconditionalJump(endLabel) - codeBuilder.markWithLabel(elseLabel) + codeBuilder.markWithLabel(notNullLabel) val right = evaluateDotBody(receiver, selector!!, scopeDepth) as LLVMVariable val rightLoaded = codeBuilder.loadAndGetVariable(right) codeBuilder.storeVariable(result, rightLoaded) @@ -201,7 +193,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va when (referenceContext) { is PropertyDescriptorImpl -> { val receiverThis = variableManager["this"]!! - evaluateMemberMethodOrField(receiverThis, receiverName, topLevel, call = null)!! as LLVMVariable + evaluateMemberMethodOrField(receiverThis, receiverName, topLevelScopeDepth, call = null)!! as LLVMVariable } else -> variableManager[receiverName] } @@ -237,21 +229,21 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } private fun evaluateExtensionExpression(receiver: KtExpression, receiverExpressionArgument: LLVMVariable?, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? { - val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver) - val standardType = LLVMMapStandardType(receiverType!!.type!!, state) + val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)!!.type!! + val receiverType = LLVMMapStandardType(kotlinType, state) val targetFunction = state.bindingContext.get(BindingContext.CALL, selector.calleeExpression) 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 packageNameFirst = targetFunction?.calleeExpression?.getContainingKtFile()?.packageFqName?.convertToNativeName().orEmpty() val packageNameSecond = candidateDescriptor.containingDeclaration.fqNameSafe.convertToNativeName() val names = parseArgList(selector, scopeDepth) val type = LLVMType.mangleFunctionArguments(names) - val constructedFunctionName = standardType.mangle + nameWithoutMangling.addBeforeIfNotEmpty(".") + type - val targetExtension = state.extensionFunctions[standardType.toString()] + val constructedFunctionName = receiverType.mangle + nameWithoutMangling.addBeforeIfNotEmpty(".") + type + val targetExtension = state.extensionFunctions[receiverType.toString()] val extensionCodegen = targetExtension?.get(packageNameFirst.addAfterIfNotEmpty(".") + constructedFunctionName) ?: targetExtension?.get(packageNameSecond.addAfterIfNotEmpty(".") + constructedFunctionName) ?: @@ -259,9 +251,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va ?: throw UnexpectedException(constructedFunctionName) val receiverExpression = receiverExpressionArgument ?: evaluateExpression(receiver, scopeDepth + 1)!! - val typeThisArgument = LLVMVariable("type", standardType, pointer = if (standardType is LLVMReferenceType) 1 else 0) - - val args = mutableListOf(codeBuilder.loadOneArgumentIfRequired(receiverExpression, typeThisArgument)) + val args = mutableListOf(codeBuilder.receivePointedArgument(receiverExpression, if (receiverType is LLVMReferenceType) 1 else 0)) args.addAll(codeBuilder.loadArgsIfRequired(names, extensionCodegen.args)) return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args) } @@ -281,7 +271,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va if (field != null) { return evaluateClassField(receiver, field) } else { - return evaluateMemberMethod(receiver, selectorName, clazz, scopeDepth, call) + return evaluateMemberMethod(receiver, clazz, scopeDepth, call as? KtCallExpression ?: throw UnexpectedException("$receiver:$selectorName")) } } @@ -291,9 +281,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return result } - fun evaluateMemberMethod(receiver: LLVMVariable, selectorName: String, clazz: StructCodegen, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? { - (call as? KtCallExpression) ?: throw UnexpectedException("$receiver:$selectorName") - val resolvedCall = (call as KtCallExpression).getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext) + fun evaluateMemberMethod(receiver: LLVMVariable, clazz: StructCodegen, scopeDepth: Int, call: KtCallExpression): LLVMSingleValue? { + val resolvedCall = call.getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext) val functionDescriptor = resolvedCall.candidateDescriptor val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) } val methodName = functionDescriptor.fqNameSafe.asString() + LLVMType.mangleFunctionTypes(functionArguments) @@ -302,8 +291,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val returnType = method.returnType!!.type val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values - val names = parseNamedValueArguments(arguments, method.defaultValues, scopeDepth) - val loadedArgs = codeBuilder.loadArgsIfRequired(names, method.args) + val substitutionArguments = parseArgumentsWithDefaultValues(arguments, method.defaultValues, scopeDepth) + val loadedArgs = codeBuilder.loadArgsIfRequired(substitutionArguments, method.args) val callArgs = mutableListOf(receiver) callArgs.addAll(loadedArgs) @@ -351,14 +340,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val arrayActionType = if (callMaker.callType == Call.CallType.ARRAY_SET_METHOD) "set" else "get" val explicitReceiver = callMaker.explicitReceiver as ExpressionReceiver val receiver = evaluateExpression(explicitReceiver.expression, scope)!! as LLVMVariable - val pureReceiver = codeBuilder.downLoadArgument(receiver, 1) + val pureReceiver = codeBuilder.receivePointedArgument(receiver, 1) val targetClassName = (receiver.type as LLVMReferenceType).type val names = parseValueArguments(callMaker.valueArguments, scope) val methodName = "$targetClassName.$arrayActionType${LLVMType.mangleFunctionArguments(names)}" - val type = receiver.type - val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString()) + val clazz = resolveClassOrObjectLocation(receiver.type) ?: throw UnexpectedException(receiver.type.toString()) val method = clazz.methods[methodName] ?: throw UnexpectedException(expr.text) val returnType = clazz.methods[methodName]!!.returnType!!.type @@ -388,21 +376,19 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return when { expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1) isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope) - (targetName != null) && (variableManager[targetName] != null) -> variableManager[targetName] - ((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(expr, classScope.parentCodegen!!) + (targetName != null) && variableManager.contains(targetName) -> variableManager[targetName] + ((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(targetName!!, classScope.parentCodegen!! as ClassCodegen) else -> { val clazz = classScope ?: resolveCodegen(expr) val receiver = if (clazz != null) variableManager[clazz.structName] ?: variableManager["this"] else variableManager["this"] - targetName ?: throw RuntimeException(expr.firstChild.text) - evaluateMemberMethodOrField(receiver ?: throw UnexpectedException(targetName), targetName, topLevel) + targetName ?: throw UnexpectedException("Can't find target in reference expression " + expr.firstChild.text) + evaluateMemberMethodOrField(receiver ?: throw UnexpectedException(targetName), targetName, topLevelScopeDepth) } } } - - private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: StructCodegen): LLVMSingleValue? { - val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString() - val companionObject = (classScope as ClassCodegen).companionObjectCodegen ?: throw UnexpectedException(expr.text) + private fun evaluateNameReferenceExpression(fieldName: String, classScope: ClassCodegen): LLVMSingleValue? { + val companionObject = classScope.companionObjectCodegen!! val field = companionObject.fieldsIndex[fieldName] ?: return null val receiver = variableManager[companionObject.structName]!! val result = codeBuilder.getNewVariable(field.type, pointer = 1) @@ -419,7 +405,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va private fun resolveCodegen(expr: KtExpression): StructCodegen? { val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)?.type - ?: expr.getType(state.bindingContext) ?: expr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext) val name = type?.constructor?.declarationDescriptor?.fqNameSafe?.asString() ?: throw UnexpectedException(expr.text) @@ -430,7 +415,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va private fun resolveCodegenByName(name: String): StructCodegen? = resolveClassOrObjectLocation(LLVMReferenceType(name, prefix = "class")) - private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? { var names = parseArgList(expr, scopeDepth) val targetFunction = state.bindingContext.get(BindingContext.CALL, expr.calleeExpression) @@ -439,51 +423,34 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va resolvedCall = resolvedCall.variableCall } - val targetFunctionName = resolvedCall!!.candidateDescriptor.fqNameSafe.convertToNativeName() - val functionDescriptor = expr.getFunctionResolvedCallWithAssert(state.bindingContext).candidateDescriptor + val functionDescriptor = resolvedCall!!.candidateDescriptor + val targetFunctionName = functionDescriptor.fqNameSafe.convertToNativeName() val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values val external = state.externalFunctions.containsKey(targetFunctionName) val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) } val function = "$targetFunctionName${if (!external) LLVMType.mangleFunctionTypes(functionArguments) else ""}" - - if (state.functions.containsKey(function) || state.externalFunctions.containsKey(function)) { - val descriptor = state.functions[function] ?: state.externalFunctions[function] ?: return null - names = parseNamedValueArguments(arguments, descriptor.defaultValues, scopeDepth) + if (function in state.functions || function in state.externalFunctions) { + val descriptor = state.functions[function] ?: state.externalFunctions[function]!! + names = parseArgumentsWithDefaultValues(arguments, descriptor.defaultValues, scopeDepth) val args = codeBuilder.loadArgsIfRequired(names, descriptor.args) return evaluateFunctionCallExpression(LLVMVariable(function, descriptor.returnType!!.type, scope = LLVMVariableScope()), args) } - if (state.classes.containsKey(targetFunctionName) || classScope?.structName == targetFunctionName) { + if (targetFunctionName in state.classes || classScope?.structName == targetFunctionName) { val descriptor = state.classes[targetFunctionName] ?: classScope ?: return null val detectedConstructor = LLVMType.mangleFunctionTypes(functionArguments) val args = codeBuilder.loadArgsIfRequired(names, descriptor.constructorFields[detectedConstructor]!!) return evaluateConstructorCallExpression(LLVMVariable(descriptor.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), args) } - val localFunction = variableManager[targetFunctionName] - if (localFunction != null) { - val type = localFunction.type as LLVMFunctionType + if (targetFunctionName in variableManager) { + val type = variableManager[targetFunctionName]!!.type as LLVMFunctionType val args = codeBuilder.loadArgsIfRequired(names, type.arguments) return evaluateFunctionCallExpression(LLVMVariable(targetFunctionName, type.returnType.type, scope = LLVMRegisterScope()), args) } - if (classScope != null) { - if (classScope.methods.containsKey(function)) { - val descriptor = classScope.methods[function]!! - val parentDescriptor = descriptor.parentCodegen!! - val receiver = variableManager[parentDescriptor.structName] ?: throw UnexpectedException(parentDescriptor.structName) - val methodFullName = descriptor.name - val returnType = descriptor.returnType!!.type - val loadedArgs = codeBuilder.loadArgsIfRequired(names, descriptor.args) - val callArgs = mutableListOf(receiver) - callArgs.addAll(loadedArgs) - - return evaluateFunctionCallExpression(LLVMVariable(methodFullName, returnType, scope = LLVMVariableScope()), callArgs) - } - } - val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text) if (nestedConstructor != null) { val args = codeBuilder.loadArgsIfRequired(names, nestedConstructor.constructorFields[nestedConstructor.primaryConstructorIndex]!!) @@ -496,7 +463,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va if (caller != null) { args.add(caller) - } else if (variableManager[containingClass.structName] != null) { + } else if (containingClass.structName in variableManager) { args.add(variableManager[containingClass.structName]!!) } else { args.add(variableManager["this"]!!) @@ -517,6 +484,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va when (returnType) { is LLVMVoidType -> { codeBuilder.addLLVMCodeToLocalPlace(LLVMCall(LLVMVoidType(), function.toString(), names).toString()) + return null } is LLVMReferenceType -> { val returnVar = codeBuilder.getNewVariable(returnType, pointer = 2) @@ -542,8 +510,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return resultPtr } } - - return null } private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List): LLVMSingleValue? { @@ -575,7 +541,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va fun parseOneValueArgument(arg: ValueArgument, scopeDepth: Int): LLVMSingleValue = evaluateExpression(arg.getArgumentExpression(), scopeDepth) as LLVMSingleValue - private fun parseNamedValueArguments(args: MutableCollection, defaultValues: List, scopeDepth: Int): List = + private fun parseArgumentsWithDefaultValues(args: MutableCollection, defaultValues: List, scopeDepth: Int): List = args.mapIndexed(fun(i: Int, value: ResolvedValueArgument): LLVMSingleValue { return when (value) { is DefaultValueArgument -> evaluateExpression(defaultValues[i], scopeDepth)!! @@ -604,108 +570,92 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val right = evaluateExpression(expr.right, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}") - return executeBinaryExpression(operator, expr.operationReference, left, right) + return addPrimitiveBinaryOperation(operator, left, right, expr.operationReference) } private fun evaluatePostfixExpression(expr: KtPostfixExpression, scopeDepth: Int): LLVMSingleValue? { val operator = expr.operationToken val left = evaluateExpression(expr.baseExpression, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}") - return executePostfixExpression(operator, left as LLVMVariable) + return addPrimitivePostfixOperation(operator, left as LLVMVariable) } private fun evaluatePrefixExpression(expr: KtPrefixExpression, scopeDepth: Int): LLVMSingleValue? { val operator = expr.operationToken val left = evaluateExpression(expr.baseExpression, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary expression") - return executePrefixExpression(operator, expr.operationReference, left) + return addPrimitivePrefixOperation(operator, left) } - private fun executePostfixExpression(operator: IElementType?, left: LLVMVariable): LLVMSingleValue? - = addPrimitivePostfixOperation(operator, left) + private fun addPrimitivePostfixOperation(operator: IElementType?, firstOp: LLVMVariable): LLVMSingleValue? = + when (operator) { + KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> { + val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) + val oldValue = codeBuilder.getNewVariable(firstOp.type, firstOp.pointer) + codeBuilder.allocStackVar(oldValue, asValue = true) + codeBuilder.copyVariable(firstOp, oldValue) - private fun executePrefixExpression(operator: IElementType?, operationReference: KtSimpleNameExpression, left: LLVMSingleValue): LLVMSingleValue? - = addPrimitivePrefixOperation(operator, operationReference, left) + val llvmExpression = when (operator) { + KtTokens.PLUSPLUS -> firstOp.type.operatorInc(firstNativeOp) + KtTokens.MINUSMINUS -> firstOp.type.operatorDec(firstNativeOp) + else -> throw IllegalAccessError() + } - private fun addPrimitivePostfixOperation(operator: IElementType?, firstOp: LLVMVariable): LLVMSingleValue? { - val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) - when (operator) { - KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> { - val oldValue = codeBuilder.getNewVariable(firstOp.type, firstOp.pointer) - codeBuilder.allocStackVar(oldValue, asValue = true) - codeBuilder.copyVariable(firstOp, oldValue) + val resultOp = codeBuilder.storeExpression(llvmExpression) + codeBuilder.storeVariable(firstOp, resultOp) - val llvmExpression = when (operator) { - KtTokens.PLUSPLUS -> firstOp.type.operatorInc(firstNativeOp) - KtTokens.MINUSMINUS -> firstOp.type.operatorDec(firstNativeOp) - else -> throw IllegalAccessError() + oldValue } - - val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType) - codeBuilder.addAssignment(resultOp, llvmExpression) - codeBuilder.storeVariable(firstOp, resultOp) - - return oldValue - } - KtTokens.EXCLEXCL -> { - var result = firstOp - val nullLabel = codeBuilder.getNewLabel(prefix = "nullCheck") - val notNullLabel = codeBuilder.getNewLabel(prefix = "nullCheck") - val nullCheck = codeBuilder.nullCheck(firstOp) - codeBuilder.addCondition(nullCheck, nullLabel, notNullLabel) - codeBuilder.markWithLabel(nullLabel) - codeBuilder.addExceptionCall("KotlinNullPointerException") - codeBuilder.addUnconditionalJump(notNullLabel) - codeBuilder.markWithLabel(notNullLabel) - if (firstOp.type.isPrimitive) { - result = codeBuilder.downLoadArgument(firstOp, 0) as LLVMVariable + KtTokens.EXCLEXCL -> { + var result = firstOp + val nullLabel = codeBuilder.getNewLabel(prefix = "nullCheck") + val notNullLabel = codeBuilder.getNewLabel(prefix = "nullCheck") + val nullCheck = codeBuilder.nullCheck(firstOp) + codeBuilder.addCondition(nullCheck, nullLabel, notNullLabel) + codeBuilder.markWithLabel(nullLabel) + codeBuilder.addExceptionCall("KotlinNullPointerException") + codeBuilder.addUnconditionalJump(notNullLabel) + codeBuilder.markWithLabel(notNullLabel) + if (firstOp.type.isPrimitive) { + result = codeBuilder.receivePointedArgument(firstOp, 0) as LLVMVariable + } + result } - return result + else -> throw UnsupportedOperationException() } - else -> throw UnsupportedOperationException() - } - } - private fun addPrimitivePrefixOperation(operator: IElementType?, operationReference: KtSimpleNameExpression, firstOp: LLVMSingleValue): LLVMSingleValue? { + + private fun addPrimitivePrefixOperation(operator: IElementType?, firstOp: LLVMSingleValue): LLVMSingleValue? { when (operator) { KtTokens.MINUS, KtTokens.PLUS -> { - return addPrimitiveBinaryOperation(operator!!, operationReference, LLVMConstant("0", firstOp.type), firstOp) + return addPrimitiveBinaryOperation(operator!!, LLVMConstant("0", firstOp.type), firstOp) } KtTokens.EXCL -> { val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) val llvmExpression = addPrimitiveReferenceOperationByName("xor", LLVMConstant("true", LLVMBooleanType()), firstNativeOp) - val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType) - codeBuilder.addAssignment(resultOp, llvmExpression) - return resultOp + return codeBuilder.storeExpression(llvmExpression) } else -> throw UnsupportedOperationException() } } - fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue) - = addPrimitiveBinaryOperation(operator, referenceName, left, right) - private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable { - val left = evaluateExpression(expr.firstChild, scopeDepth) + val left = evaluateExpression(expr.left, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary expression") val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable) val condition = lptr.type.operatorEq(lptr, LLVMVariable("", LLVMNullType())) - val conditionResult = codeBuilder.getNewVariable(condition.variableType) - codeBuilder.addAssignment(conditionResult, condition) + val conditionResult = codeBuilder.storeExpression(condition) - val thenLabel = codeBuilder.getNewLabel(prefix = "elvis") - val elseLabel = codeBuilder.getNewLabel(prefix = "elvis") + val notNull = codeBuilder.getNewLabel(prefix = "elvis") val endLabel = codeBuilder.getNewLabel(prefix = "elvis") - codeBuilder.addCondition(conditionResult, elseLabel, thenLabel) - codeBuilder.markWithLabel(thenLabel) - codeBuilder.addUnconditionalJump(endLabel) + codeBuilder.addCondition(conditionResult, notNull, endLabel) - codeBuilder.markWithLabel(elseLabel) - var right = evaluateExpression(expr.lastChild, scopeDepth + 1) + codeBuilder.markWithLabel(notNull) + var right = evaluateExpression(expr.right, scopeDepth + 1) if (right != null) { right = codeBuilder.loadAndGetVariable(right as LLVMVariable) codeBuilder.storeVariable(left, right) @@ -717,9 +667,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return left } - fun addPrimitiveReferenceOperation(referenceName: KtSimpleNameExpression, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression - = addPrimitiveReferenceOperationByName(referenceName.getReferencedName(), firstOp, secondNativeOp) - fun addPrimitiveReferenceOperationByName(operator: String, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression { val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) @@ -734,23 +681,27 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va "shr" -> firstNativeOp.type.operatorShr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type)) "ushr" -> firstNativeOp.type.operatorUshr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type)) "+=" -> { - val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorPlus(firstNativeOp, secondNativeOp)) + val resultOp = codeBuilder.storeExpression(firstNativeOp.type.operatorPlus(firstNativeOp, secondNativeOp)) + codeBuilder.storeVariable(firstOp, resultOp) return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}") } "-=" -> { - val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorMinus(firstNativeOp, secondNativeOp)) + val resultOp = codeBuilder.storeExpression(firstNativeOp.type.operatorMinus(firstNativeOp, secondNativeOp)) + codeBuilder.storeVariable(firstOp, resultOp) return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}") } "*=" -> { - val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorTimes(firstNativeOp, secondNativeOp)) + val resultOp = codeBuilder.storeExpression(firstNativeOp.type.operatorTimes(firstNativeOp, secondNativeOp)) + codeBuilder.storeVariable(firstOp, resultOp) return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}") } "%=" -> { - val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorMod(firstNativeOp, secondNativeOp)) + val resultOp = codeBuilder.storeExpression(firstNativeOp.type.operatorMod(firstNativeOp, secondNativeOp)) + codeBuilder.storeVariable(firstOp, resultOp) return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}") } ".." -> { - val descriptor = state.classes["kotlin.ranges.IntRange"] + val descriptor = state.classes["kotlin.ranges.${firstOp.type.mangle}Range"] val arguments = listOf(firstOp, secondNativeOp) val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type }) val result = evaluateConstructorCallExpression(LLVMVariable(descriptor!!.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), arguments) @@ -760,7 +711,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } } - private fun addPrimitiveBinaryOperation(operator: IElementType, referenceName: KtSimpleNameExpression?, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable { + fun addPrimitiveBinaryOperation(operator: IElementType, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue, referenceName: KtSimpleNameExpression? = null): LLVMVariable { val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) val secondNativeOp = codeBuilder.receiveNativeValue(secondOp) @@ -817,18 +768,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.storeVariable(result, sourceArgument) return result } - else -> addPrimitiveReferenceOperation(referenceName!!, firstOp, secondNativeOp) + else -> addPrimitiveReferenceOperationByName(referenceName!!.getReferencedName(), firstOp, secondNativeOp) } - val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType, pointer = llvmExpression.pointer) - codeBuilder.addAssignment(resultOp, llvmExpression) - return resultOp + return codeBuilder.storeExpression(llvmExpression) } private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant { val expressionKotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!! val expressionValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)?.getValue(expressionKotlinType) val type = LLVMMapStandardType(expressionKotlinType, state) - return LLVMConstant(expressionValue?.toString() ?: "", type, pointer = 0) + return LLVMConstant(expressionValue?.toString().orEmpty(), type, pointer = 0) } private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMSingleValue? { @@ -864,11 +813,11 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val nextDescriptor = iteratorDescriptor!!.methods["$returnTypeName.next"] ?: throw UnexpectedException("$returnTypeName.nextInt") val conditionIterator = evaluateFunctionCallExpression(LLVMVariable("$rangeTypeName.iterator", returnType, scope = LLVMVariableScope()), listOf(range))!! - val iteratorThisArgument = codeBuilder.loadOneArgumentIfRequired(conditionIterator, LLVMVariable("type", descriptor.type, pointer = 1)) + val iteratorThisArgument = codeBuilder.receivePointedArgument(conditionIterator, 1) codeBuilder.addUnconditionalJump(conditionLabel) codeBuilder.markWithLabel(conditionLabel) var conditionResult = evaluateFunctionCallExpression(LLVMVariable("$returnTypeName.hasNext", LLVMBooleanType(), scope = LLVMVariableScope()), listOf(iteratorThisArgument))!! - conditionResult = codeBuilder.downLoadArgument(conditionResult, 0) + conditionResult = codeBuilder.receivePointedArgument(conditionResult, 0) codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel) codeBuilder.addUnconditionalJump(bodyLabel) @@ -881,7 +830,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va variableManager.addVariable(loopParameterDescriptor, allocVar, scopeDepth + 1) codeBuilder.allocStackVar(allocVar, pointer = true) - addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, loopParameter) + addPrimitiveBinaryOperation(KtTokens.EQ, allocVar, loopParameter, null) evaluateCodeBlock(expr.body, null, conditionLabel, exitLabel, scopeDepth + 1) codeBuilder.markWithLabel(exitLabel) @@ -899,8 +848,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.markWithLabel(nextLabel) nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition") - val currentConditionExpression = evaluateExpression(condition.firstChild, scopeDepth + 1)!! - val conditionResult = executeBinaryExpression(KtTokens.EQEQ, null, target, currentConditionExpression) + val currentConditionExpression = evaluateExpression((condition as KtWhenConditionWithExpression).expression, scopeDepth + 1)!! + val conditionResult = addPrimitiveBinaryOperation(KtTokens.EQEQ, target, currentConditionExpression) codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel) } @@ -910,11 +859,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.markWithLabel(successConditionsLabel) var successExpression = evaluateExpression(item.expression, scopeDepth + 1) - while (successExpression is LLVMVariable && successExpression.pointer > 0) { - successExpression = codeBuilder.loadAndGetVariable(successExpression) - } if (successExpression != null && !LLVMType.nullOrVoidType(resultVariable.type)) { + successExpression = codeBuilder.receivePointedArgument(successExpression, 0) codeBuilder.storeVariable(resultVariable, successExpression) } @@ -964,9 +911,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.addUnconditionalJump(if (checkConditionBeforeExecute) conditionLabel else bodyLabel) codeBuilder.markWithLabel(conditionLabel) var conditionResult = evaluateExpression(condition, scopeDepth + 1)!! - while (conditionResult.pointer > 0) { - conditionResult = codeBuilder.loadAndGetVariable(conditionResult as LLVMVariable) - } + conditionResult = codeBuilder.receivePointedArgument(conditionResult, 0) codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel) evaluateCodeBlock(bodyExpression, bodyLabel, conditionLabel, exitLabel, scopeDepth + 1) @@ -977,7 +922,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va private fun evaluateIfOperator(element: KtIfExpression, scopeDepth: Int, isExpression: Boolean = true): LLVMVariable? { val conditionResult = evaluateExpression(element.condition, scopeDepth)!! - val conditionNativeResult = codeBuilder.downLoadArgument(conditionResult, 0) + val conditionNativeResult = codeBuilder.receivePointedArgument(conditionResult, 0) return if (isExpression) executeIfExpression(conditionNativeResult, element.then!!, element.`else`, element, scopeDepth + 1) @@ -1037,7 +982,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 = !LLVMType.isReferredType(LLVMMapStandardType(variable.type, state)) + val primitivePointer = LLVMMapStandardType(variable.type, state).isPrimitive val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer = expectedExpressionType.pointer + 1) codeBuilder.allocStackVar(allocVar, pointer = true) @@ -1047,7 +992,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va if ((primitivePointer) && (assignExpression.type is LLVMReferenceType)) { throw UnexpectedException(element.text) } - addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, assignExpression) + addPrimitiveBinaryOperation(KtTokens.EQ, allocVar, assignExpression, null) } return null @@ -1068,15 +1013,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } generateReferenceReturn(retVar) } - is LLVMVoidType -> { - codeBuilder.addAnyReturn(LLVMVoidType()) - } + is LLVMVoidType -> codeBuilder.addAnyReturn(LLVMVoidType()) else -> { val retNativeValue = codeBuilder.receiveNativeValue(retVar!!) codeBuilder.addReturnOperator(retNativeValue) } } - if (scopeDepth == topLevel + 2) { + if (scopeDepth == topLevelScopeDepth + 2) { wasReturnOnTopLevel = true } return null diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt index 1e768f45fa9..a9836e830ec 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -27,13 +27,13 @@ class ClassCodegen(state: TranslationState, override val type: LLVMReferenceType init { - type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true) + type = LLVMReferenceType(structName, "class", align = TranslationState.POINTER_ALIGN, size = TranslationState.POINTER_SIZE, byRef = true) descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException("Can't receive descriptor of class " + clazz.name) annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS enum = descriptor.kind == ClassKind.ENUM_CLASS - type.align = TranslationState.pointerAlign + type.align = TranslationState.POINTER_ALIGN } private fun indexFields(parameters: MutableList) { @@ -53,8 +53,7 @@ class ClassCodegen(state: TranslationState, indexFields(parameterList) generateInnerFields(clazz.declarations) - calculateTypeSize() - type.size = size + type.size = calculateTypeSize() if (annotation) { return diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index c62eaa14683..c14bb063728 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -19,18 +19,17 @@ import java.util.* class FunctionCodegen(state: TranslationState, variableManager: VariableManager, val function: KtNamedFunction, - codeBuilder: LLVMBuilder, - val parentCodegen: StructCodegen? = null) : + codeBuilder: LLVMBuilder) : BlockCodegen(state, variableManager, codeBuilder) { var name: String var args = LinkedList() val isExtensionDeclaration = function.isExtensionDeclaration() var functionNamePrefix = "" - val fullName: String - get() = functionNamePrefix + name val external: Boolean val defaultValues: List + val fullName: String + get() = functionNamePrefix + name init { val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!! @@ -58,9 +57,8 @@ class FunctionCodegen(state: TranslationState, } defaultValues = mutableListOf() - val valueParameters = descriptor.valueParameters - for (index in valueParameters.indices) { - val parameterDescriptor = valueParameters[index] + for (index in descriptor.valueParameters.indices) { + val parameterDescriptor = descriptor.valueParameters[index] if (parameterDescriptor.declaresDefaultValue()) { val initializer = (parameterDescriptor.source as KotlinSourceElement).psi val defaultValue = (initializer as KtParameter).defaultValue @@ -69,21 +67,6 @@ class FunctionCodegen(state: TranslationState, defaultValues.add(null) } } - - val retType = returnType!!.type - when (retType) { - is LLVMReferenceType -> { - if (state.classes.containsKey(retType.type)) { - retType.prefix = "class" - returnType!!.pointer = 2 - } - - retType.byRef = true - } - } - if (retType is LLVMReferenceType && state.classes.containsKey(retType.type)) { - retType.prefix = "class" - } } fun generate(this_type: LLVMVariable? = null) { @@ -95,7 +78,7 @@ class FunctionCodegen(state: TranslationState, codeBuilder.addStartExpression() generateLoadArguments() - evaluateCodeBlock(function.bodyExpression, scopeDepth = topLevel, isBlock = function.hasBlockBody()) + evaluateCodeBlock(function.bodyExpression, scopeDepth = topLevelScopeDepth, isBlock = function.hasBlockBody()) if (!wasReturnOnTopLevel) codeBuilder.addAnyReturn(returnType!!.type) @@ -138,16 +121,16 @@ class FunctionCodegen(state: TranslationState, private fun generateLoadArguments() { args.forEach(fun(it: LLVMVariable) { if (it.type is LLVMFunctionType || (it.type is LLVMReferenceType && it.type.byRef)) { - variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 1), topLevel) + variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 1), topLevelScopeDepth) return } if (it.type !is LLVMReferenceType || it.type.byRef) { val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = it.pointer) val allocVar = codeBuilder.loadArgument(loadVariable) - variableManager.addVariable(it.label, allocVar, topLevel) + variableManager.addVariable(it.label, allocVar, topLevelScopeDepth) } else { - variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 0), topLevel) + variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 0), topLevelScopeDepth) } }) } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt index 058155454db..46e221586b3 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt @@ -20,16 +20,15 @@ class ObjectCodegen(state: TranslationState, override val type: LLVMReferenceType init { - type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true) + type = LLVMReferenceType(structName, "class", align = TranslationState.POINTER_ALIGN, size = TranslationState.POINTER_SIZE, byRef = true) primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList()) constructorFields.put(primaryConstructorIndex!!, arrayListOf()) } override fun prepareForGenerate() { generateInnerFields(objectDeclaration.declarations) - calculateTypeSize() - type.size = size - type.align = TranslationState.pointerAlign + type.size = calculateTypeSize() + type.align = TranslationState.POINTER_ALIGN super.prepareForGenerate() diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt index dd3efc9e38f..0cb5463adf5 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt @@ -7,10 +7,12 @@ class ProjectTranslator(val files: List, val state: TranslationState) { fun generateCode(): String { codeBuilder.clean() - files.map { addClassDeclarations(it) } - files.map { addObjectDeclarations(it) } - files.map { addFunctionDeclarations(it) } - files.map { addPropertyDeclarations(it) } + with(files) { + map { addClassDeclarations(it) } + map { addObjectDeclarations(it) } + map { addFunctionDeclarations(it) } + map { addPropertyDeclarations(it) } + } generateProjectBody() return codeBuilder.toString() } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt index e37626e3ff6..6561a3aa776 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt @@ -33,20 +33,19 @@ abstract class StructCodegen(val state: TranslationState, open fun prepareForGenerate() { generateStruct() - - for (declaration in classOrObject.declarations.filter { it is KtNamedFunction }) { - val function = FunctionCodegen(state, variableManager, declaration as KtNamedFunction, codeBuilder, this) + classOrObject.declarations.filter { it is KtNamedFunction }.map { + val function = FunctionCodegen(state, variableManager, it as KtNamedFunction, codeBuilder) methods.put(function.name, function) } } - fun calculateTypeSize() { + fun calculateTypeSize(): Int { val classAlignment = fields.map { it.type.align }.max()?.toInt() ?: 0 var alignmentRemainder = 0 size = 0 for (item in fields) { - val currentFieldSize = if (item.pointer > 0) TranslationState.pointerAlign else item.type.align + val currentFieldSize = if (item.pointer > 0) TranslationState.POINTER_ALIGN else item.type.align alignmentRemainder -= (alignmentRemainder % currentFieldSize) if (alignmentRemainder < currentFieldSize) { size += classAlignment @@ -55,6 +54,7 @@ abstract class StructCodegen(val state: TranslationState, alignmentRemainder -= currentFieldSize } } + return size } open fun generate() { @@ -143,7 +143,7 @@ abstract class StructCodegen(val state: TranslationState, variableManager.addVariable("this", mainConstructorThis, 0) blockCodegen.evaluateCodeBlock(secondaryConstructor.bodyExpression, scopeDepth = 1) - generateReturn(codeBuilder.downLoadArgument(variableManager["this"]!!, 1) as LLVMVariable) + generateReturn(codeBuilder.receivePointedArgument(variableManager["this"]!!, 1) as LLVMVariable) codeBuilder.addAnyReturn(LLVMVoidType()) codeBuilder.addEndExpression() } @@ -170,11 +170,9 @@ abstract class StructCodegen(val state: TranslationState, val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0) codeBuilder.loadArgument(thisVariable, false) - constructorFields[primaryConstructorIndex]!!.forEach { - if (it.type !is LLVMReferenceType) { - val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope()) - codeBuilder.loadArgument(loadVariable) - } + constructorFields[primaryConstructorIndex]!!.filter { it.type !is LLVMReferenceType }.forEach { + val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope()) + codeBuilder.loadArgument(loadVariable) } } @@ -187,7 +185,7 @@ abstract class StructCodegen(val state: TranslationState, codeBuilder.storeVariable(classField, it) } else -> { - val argument = codeBuilder.loadVariable(LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = it.pointer + 1)) + val argument = codeBuilder.loadAndGetVariable(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) @@ -200,9 +198,9 @@ abstract class StructCodegen(val state: TranslationState, variableManager.addVariable("this", receiverThis, 2) for ((variable, initializer) in initializedFields) { - val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevel, call = null)!! - val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevel)!! - blockCodegen.executeBinaryExpression(KtTokens.EQ, referenceName = null, left = left, right = right) + val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevelScopeDepth, call = null)!! + val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevelScopeDepth)!! + blockCodegen.addPrimitiveBinaryOperation(KtTokens.EQ, left, right) } variableManager.pullOneUpwardLevelVariable("this") @@ -220,15 +218,11 @@ abstract class StructCodegen(val state: TranslationState, protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType, offset: Int): LLVMClassVariable { val annotations = parseFieldAnnotations(field) val fieldName = state.bindingContext.get(BindingContext.VALUE_PARAMETER, field as?KtParameter)?.fqNameSafe?.convertToNativeName() - ?: field.fqName?.asString() ?: field.name!! + ?: field.fqName?.asString() + ?: field.name!! val result = LLVMInstanceOfStandardType(fieldName, ktType, LLVMRegisterScope(), state = state) - if (result.type is LLVMReferenceType) { - result.type.prefix = "class" - result.type.byRef = true - } - if (state.classes.containsKey(field.name!!)) { return LLVMClassVariable(result.label, state.classes[fieldName]!!.type, result.pointer) } @@ -246,7 +240,7 @@ abstract class StructCodegen(val state: TranslationState, protected fun genClassInitializers() = classOrObject.getAnonymousInitializers().map { object : BlockCodegen(state, variableManager, codeBuilder) { - fun generate() = evaluateCodeBlock(it.body, scopeDepth = topLevel) + fun generate() = evaluateCodeBlock(it.body, scopeDepth = topLevelScopeDepth) } }.map { it.generate() } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt index 3f5fbdffb48..35b72d97c75 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt @@ -27,13 +27,13 @@ import java.util.* class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val mainFunction: String, arm: Boolean) { companion object { - var pointerAlign = 4 - var pointerSize = 4 + var POINTER_ALIGN = 4 + var POINTER_SIZE = 4 } init { - pointerAlign = if (arm) 4 else 8 - pointerSize = if (arm) 4 else 8 + POINTER_ALIGN = if (arm) 4 else 8 + POINTER_SIZE = if (arm) 4 else 8 } var externalFunctions = HashMap() diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt b/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt index d0c9f990aa9..bb0ff4bb229 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt @@ -8,12 +8,21 @@ import java.util.* class VariableManager(val globalVariableCollection: HashMap) { private var fileVariableCollectionTree = HashMap>>() - private var variableVersion = HashMap() + + private companion object UniqueGenerator { + private var unique = 0 + fun generateUniqueString() = + ".unique." + unique++ + } operator fun get(variableName: String): LLVMVariable? { return fileVariableCollectionTree[variableName]?.peek()?.first ?: globalVariableCollection[variableName] } + operator fun contains(variableName: String): Boolean { + return (fileVariableCollectionTree.contains(variableName) && !fileVariableCollectionTree[variableName]!!.empty()) || globalVariableCollection.containsKey(variableName) + } + fun pullOneUpwardLevelVariable(variableName: String) { fileVariableCollectionTree[variableName]?.pop() } @@ -33,9 +42,7 @@ class VariableManager(val globalVariableCollection: HashMap = mapOf() - object UniqueGenerator { - private var unique = 0 - fun generateUniqueString() = - ".unique." + unique++ - } init { initBuilder() } - private fun initBuilder() { - val declares = arrayOf( - "declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)", - "declare i8* @malloc_heap(i32)", - "declare i32 @printf(i8*, ...)", - "%class.Nothing = type { }", - "declare void @abort()") - - declares.forEach { addLLVMCodeToGlobalPlace(it) } - - exceptions = mapOf( - Pair("KotlinNullPointerException", initializeExceptionString("Exception in thread main kotlin.KotlinNullPointerException"))) - - if (arm) { - val functionAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }""" - addLLVMCodeToGlobalPlace(functionAttributes) - } - } - fun getNewVariable(type: LLVMType, pointer: Int = 0, kotlinName: String? = null, scope: LLVMScope = LLVMRegisterScope(), prefix: String = "var"): LLVMVariable { variableCount++ return LLVMVariable("$prefix$variableCount", type, kotlinName, scope, pointer) @@ -54,58 +31,44 @@ class LLVMBuilder(val arm: Boolean = false) { fun addLLVMCodeToLocalPlace(code: String) = localCode.appendln(code) - fun addLLVMCodeToGlobalPlace(code: String) = globalCode.appendln(code) - fun addStartExpression() = addLLVMCodeToLocalPlace("{") fun addEndExpression() = addLLVMCodeToLocalPlace("}") - fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue = - when (firstOp) { - is LLVMConstant -> firstOp - is LLVMVariable -> if (firstOp.pointer == 0) firstOp else loadAndGetVariable(firstOp) - else -> throw UnsupportedOperationException() + when { + firstOp is LLVMConstant || firstOp.pointer == 0 -> firstOp + firstOp is LLVMVariable -> loadAndGetVariable(firstOp) + else -> throw UnexpectedException("Unknown inheritor of LLVMSingleValue") } - 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 loadOneArgumentIfRequired(value, args[i]) + return receivePointedArgument(value, args[i].pointer) }).toList() - fun loadOneArgumentIfRequired(value: LLVMSingleValue, argument: LLVMVariable): LLVMSingleValue { + fun receivePointedArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue { var result = value - while (argument.pointer < result.pointer) { - result = loadVariable(result as LLVMVariable) + while (result.pointer > pointer) { + result = receiveNativeValue(result) } if ((value.type is LLVMStringType) && !(value.type.isLoaded)) { val newVariable = getNewVariable(value.type, pointer = result.pointer + 1) allocStackVar(newVariable, asValue = true) copyVariable(result as LLVMVariable, newVariable) - result = loadVariable(newVariable) + result = loadAndGetVariable(newVariable) } return result } - fun downLoadArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue = - loadOneArgumentIfRequired(value, LLVMVariable("", value.type, pointer = pointer)) - fun clean() { localCode = StringBuilder() globalCode = StringBuilder() @@ -115,31 +78,20 @@ class LLVMBuilder(val arm: Boolean = false) { fun addAssignment(lhs: LLVMVariable, rhs: LLVMNode) = addLLVMCodeToLocalPlace("$lhs = $rhs") - fun addReturnOperator(llvmVariable: LLVMSingleValue) = addLLVMCodeToLocalPlace("ret ${llvmVariable.type} $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) = addLLVMCodeToGlobalPlace("$variable = private unnamed_addr constant ${(variable.type as LLVMStringType).fullArrayType} c\"${value.replace("\"", "\\\"")}\\00\", align 1") - - fun convertVariableToType(variable: LLVMSingleValue, tarpointedType: LLVMType): LLVMSingleValue { + fun convertVariableToType(variable: LLVMSingleValue, targetType: LLVMType): LLVMSingleValue { var resultVariable = variable - if (variable.type != tarpointedType) { - val convertedExpression = tarpointedType.convertFrom(variable) - resultVariable = getNewVariable(convertedExpression.variableType) - addAssignment(resultVariable, convertedExpression) + if (variable.type != targetType) { + val convertedExpression = targetType.convertFrom(variable) + resultVariable = storeExpression(convertedExpression) } return resultVariable } @@ -174,21 +126,18 @@ class LLVMBuilder(val arm: Boolean = false) { } } - - fun storeExpression(target: LLVMSingleValue, expression: LLVMExpression): LLVMVariable { - val resultOp = getNewVariable(expression.variableType) + fun storeExpression(expression: LLVMExpression): LLVMVariable { + val resultOp = getNewVariable(expression.variableType, pointer = expression.pointer) addAssignment(resultOp, expression) - storeVariable(target, resultOp) return resultOp } fun storeNull(result: LLVMVariable) = - addLLVMCodeToLocalPlace("store ${result.pointedType.dropLast(1)} null, ${result.pointedType} $result, align ${TranslationState.pointerAlign}") + addLLVMCodeToLocalPlace("store ${result.pointedType.dropLast(1)} null, ${result.pointedType} $result, align ${TranslationState.POINTER_ALIGN}") fun nullCheck(variable: LLVMVariable): LLVMVariable { val result = getNewVariable(LLVMBooleanType(), pointer = 0) - val loaded = loadVariable(variable) - + val loaded = loadAndGetVariable(variable) addLLVMCodeToLocalPlace("$result = icmp eq ${loaded.pointedType} null, $loaded") return result } @@ -199,20 +148,11 @@ class LLVMBuilder(val arm: Boolean = false) { fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) = addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}") - - private fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) { - var from = source - if (source.pointer > 0) { - from = getNewVariable(source.type, source.pointer) - addLLVMCodeToLocalPlace("$from = load ${source.pointedType} $source, align ${from.type.align}") - } - addLLVMCodeToLocalPlace("store ${target.type} $from, ${target.pointedType} $target, align ${from.type.align}") - } - - fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) { - is LLVMStringType -> if (from.type.isLoaded) copyVariableValue(to, from) else storeString(to, from, 0) - else -> copyVariableValue(to, from) - } + fun copyVariable(from: LLVMVariable, to: LLVMVariable) = + when { + from.type is LLVMStringType && !from.type.isLoaded -> storeString(to, from, 0) + else -> copyVariableValue(to, from) + } fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable { val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = llvmVariable.pointer + 1) @@ -220,12 +160,6 @@ class LLVMBuilder(val arm: Boolean = false) { return allocVar } - fun loadVariable(source: LLVMVariable): LLVMVariable { - val target = getNewVariable(source.type, pointer = source.pointer - 1) - addLLVMCodeToLocalPlace("$target = load ${source.pointedType} $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.pointedType addLLVMCodeToLocalPlace("$target = alloca ${if (pointer) type.removeSuffix("*") else type}, align ${target.type.align}") @@ -234,7 +168,7 @@ class LLVMBuilder(val arm: Boolean = false) { 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 size = if ((target.pointer >= 2) || (target.pointer >= 1 && !pointer)) TranslationState.POINTER_SIZE else target.type.size addLLVMCodeToLocalPlace("$allocated = call i8* @malloc_heap(i32 $size)") addLLVMCodeToLocalPlace("$target = bitcast ${allocated.pointedType} $allocated to ${if (asValue) target.type.toString() else target.pointedType}" + if (pointer) "" else "*") @@ -251,7 +185,6 @@ class LLVMBuilder(val arm: Boolean = false) { fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) = addLLVMCodeToLocalPlace("$variable = global ${variable.pointedType} $defaultValue, align ${variable.type.align}") - fun makeStructInitializer(args: List, values: List) = "{ ${args.mapIndexed { i: Int, variable: LLVMVariable -> "${variable.type} ${values[i]}" }.joinToString()} }" @@ -265,15 +198,12 @@ class LLVMBuilder(val arm: Boolean = false) { fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) = addLLVMCodeToLocalPlace("br ${condition.pointedType} $condition, label $thenLabel, label $elseLabel") - fun addUnconditionalJump(label: LLVMLabel) = addLLVMCodeToLocalPlace("br label $label") - fun createClass(name: String, fields: List) = addLLVMCodeToGlobalPlace("%class.$name = type { ${fields.map { it.pointedType }.joinToString()} }") - fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable { val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer) addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.pointedType}") @@ -305,4 +235,38 @@ class LLVMBuilder(val arm: Boolean = false) { override fun toString() = globalCode.toString() + localCode.toString() + private fun initBuilder() { + val declares = arrayOf( + "declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)", + "declare i8* @malloc_heap(i32)", + "declare i32 @printf(i8*, ...)", + "%class.Nothing = type { }", + "declare void @abort()") + + declares.forEach { addLLVMCodeToGlobalPlace(it) } + + exceptions = mapOf( + Pair("KotlinNullPointerException", initializeExceptionString("Exception in thread main kotlin.KotlinNullPointerException"))) + + if (arm) { + val functionAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }""" + addLLVMCodeToGlobalPlace(functionAttributes) + } + } + + private fun initializeExceptionString(string: String): LLVMVariable { + val result = getNewVariable(LLVMStringType(string.length), pointer = 0, scope = LLVMVariableScope(), prefix = "exceptions.str.") + addStringConstant(result, string) + return result + } + + private fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) { + var from = source + if (source.pointer > 0) { + from = getNewVariable(source.type, source.pointer) + addLLVMCodeToLocalPlace("$from = load ${source.pointedType} $source, align ${from.type.align}") + } + addLLVMCodeToLocalPlace("store ${target.type} $from, ${target.pointedType} $target, align ${from.type.align}") + } + } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt index 06ca87516dd..df641a2a523 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt @@ -4,7 +4,6 @@ import org.kotlinnative.translator.llvm.types.LLVMType class LLVMCall(val returnType: LLVMType, val name: String, val arguments: Collection) : LLVMSingleValue(returnType) { - override fun toString(): String = - "call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})" + override fun toString() = "call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})" } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt index a97484d9c15..e7cadf53d86 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt @@ -2,5 +2,4 @@ package org.kotlinnative.translator.llvm import org.kotlinnative.translator.llvm.types.LLVMType - class LLVMClassVariable(label: String, type: LLVMType, pointer: Int = 0, var offset: Int = 0) : LLVMVariable(label, type, pointer = pointer) \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMConstant.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMConstant.kt index d17270b4665..17a4bd69af2 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMConstant.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMConstant.kt @@ -6,12 +6,8 @@ open class LLVMConstant(value: String, type: LLVMType, pointer: Int = 0) : LLVMSingleValue(type, pointer) { - val value: String + val value = type.parseArg(value) - init { - this.value = type.parseArg(value) - } - - override fun toString(): String = value + override fun toString() = value } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMExpression.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMExpression.kt index c145f1fb8aa..b3d5e891b22 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMExpression.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMExpression.kt @@ -4,6 +4,6 @@ import org.kotlinnative.translator.llvm.types.LLVMType class LLVMExpression(val variableType: LLVMType, val llvmCode: String, val pointer: Int = 0) : LLVMNode() { - override fun toString(): String = llvmCode + override fun toString() = llvmCode } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMLabel.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMLabel.kt index 45a995b6314..ea6e23d2a07 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMLabel.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMLabel.kt @@ -2,6 +2,6 @@ package org.kotlinnative.translator.llvm class LLVMLabel(val label: String, val scope: LLVMScope) : LLVMNode() { - override fun toString(): String = "$scope$label" + override fun toString() = "$scope$label" } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMScope.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMScope.kt index 78023cab3e0..6932d837bc9 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMScope.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMScope.kt @@ -1,6 +1,6 @@ package org.kotlinnative.translator.llvm -open class LLVMScope +abstract class LLVMScope class LLVMVariableScope : LLVMScope() { override fun toString() = "@" diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt index d6bb94e22b7..342a12977db 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt @@ -8,6 +8,6 @@ open class LLVMVariable(val label: String, val scope: LLVMScope = LLVMRegisterScope(), pointer: Int = 0) : LLVMSingleValue(type, pointer) { - override fun toString(): String = "$scope$label" + override fun toString() = "$scope$label" } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt index 2ee8a7846d1..2f4a9bffc6e 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -18,7 +18,7 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List?, returnTy fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable { val typeName = type.toString().dropLastWhile { it == '?' } - val pointerMark = if (type.toString().last() == '?') 1 else 0 + val pointerMark = if (type.isMarkedNullable) 1 else 0 return when { type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1) typeName == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope, pointerMark) @@ -36,7 +36,7 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope else -> { val declarationDescriptor = type.constructor.declarationDescriptor!! val refName = declarationDescriptor.fqNameSafe.asString() - val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.pointerAlign, prefix = "class") + val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.POINTER_ALIGN, prefix = "class") LLVMVariable(name, refType, name, scope, pointer = 1) } @@ -52,10 +52,5 @@ fun String.addBeforeIfNotEmpty(add: String): String = fun String.addAfterIfNotEmpty(add: String): String = if (this.length > 0) this + add else this -fun String.indexOfOrLast(str: Char, startIndex: Int = 0): Int { - val pos = this.indexOf(str, startIndex) - return if (pos < 0) this.length else pos -} - fun FqName.convertToNativeName(): String = this.asString().replace(".", "") \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMFloatType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMFloatType.kt index 37b021e4c44..b98b18d0b59 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMFloatType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMFloatType.kt @@ -13,43 +13,43 @@ class LLVMFloatType() : LLVMType() { override val defaultValue = "0.0" override val isPrimitive = true - override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMFloatType(), "fsub float $firstOp, $secondOp") - override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMFloatType(), "fmul float $firstOp, $secondOp") - override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMFloatType(), "fadd float $firstOp, $secondOp") - override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMFloatType(), "fdiv float $firstOp, $secondOp") - override fun operatorInc(firstOp: LLVMSingleValue): LLVMExpression = + override fun operatorInc(firstOp: LLVMSingleValue) = LLVMExpression(LLVMDoubleType(), "fadd float $firstOp, 1.0") - override fun operatorDec(firstOp: LLVMSingleValue): LLVMExpression = + override fun operatorDec(firstOp: LLVMSingleValue) = LLVMExpression(LLVMDoubleType(), "fsub float $firstOp, 1.0") - override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMBooleanType(), "fcmp olt float $firstOp, $secondOp") - override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMBooleanType(), "fcmp ogt float $firstOp, $secondOp") - override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMBooleanType(), "fcmp ole float i32 $firstOp, $secondOp") - override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMBooleanType(), "fcmp oge float i32 $firstOp, $secondOp") - override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMBooleanType(), "fcmp oeq float" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp") - override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMBooleanType(), "fcmp one float" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp") - override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = + override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = LLVMExpression(LLVMFloatType(), "frem float $firstOp, $secondOp") override fun equals(other: Any?) = diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt index 8e52efea2d3..efd61f3a4ed 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt @@ -19,7 +19,7 @@ class LLVMIntType() : LLVMType() { is LLVMBooleanType, is LLVMByteType, is LLVMCharType, - is LLVMShortType -> LLVMExpression(LLVMBooleanType(), " sext ${source.type} $source to i32") + is LLVMShortType -> LLVMExpression(LLVMIntType(), " sext ${source.type} $source to i32") else -> throw UnimplementedException() } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt index 239330ab89c..eafcde9c8ef 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMLongType.kt @@ -20,7 +20,7 @@ class LLVMLongType() : LLVMType() { is LLVMByteType, is LLVMCharType, is LLVMShortType, - is LLVMIntType -> LLVMExpression(LLVMBooleanType(), " sext ${source.type} $source to i64") + is LLVMIntType -> LLVMExpression(LLVMLongType(), " sext ${source.type} $source to i64") else -> throw UnimplementedException() } 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 db9badcfee4..c5d3c935c2b 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 @@ -6,12 +6,12 @@ class LLVMNullType(var baseType: LLVMType? = null) : LLVMType() { override var size = 0 override val defaultValue = "null" override val mangle = "" - override val typename = baseType?.typename ?: "" + override val typename = baseType?.typename.orEmpty() override fun parseArg(inputArg: String) = "null" - override fun toString() = baseType?.toString() ?: "" + override fun toString() = baseType?.toString().orEmpty() - override fun equals(other: Any?): Boolean = + override fun equals(other: Any?) = other is LLVMNullType override fun hashCode() = 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 5bdad378a8a..86182e1ef4c 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 @@ -8,8 +8,8 @@ import org.kotlinnative.translator.llvm.addAfterIfNotEmpty class LLVMReferenceType(val type: String, var prefix: String = "", - override var align: Int = TranslationState.pointerAlign, - override var size: Int = TranslationState.pointerSize, + override var align: Int = TranslationState.POINTER_ALIGN, + override var size: Int = TranslationState.POINTER_SIZE, var byRef: Boolean = true) : LLVMType() { override val defaultValue: String = "null"