diff --git a/translator/Makefile b/translator/Makefile index 222e8dc9f1e..224f39eed52 100644 --- a/translator/Makefile +++ b/translator/Makefile @@ -7,11 +7,15 @@ lightRed = '\033[1;31m' orange = '\033[0;33m' nc = '\033[0m' +stdlib: + cd ../kotstd && make clean && make -%.out: %.txt +%.out: stdlib %.txt @./run_one_test.sh $(@:.out=.txt) -all: $(OBJECTS) - @echo "ok" +tests: stdlib $(OBJECTS) + @date -.PHONY: all +.DEFAULT_GOAL := tests + +.PHONY: tests, stdlib diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index 6bdaf1f6720..8aac280d197 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -43,7 +43,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va if (result.pointer == 1 && result.type !is LLVMReferenceType) { result = codeBuilder.loadAndGetVariable(result) } - if (result.type is LLVMReferenceType) { genReferenceReturn(result) } else { @@ -119,7 +118,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va fun evaluateConstructorDelegationReferenceExpression(expr: KtConstructorDelegationReferenceExpression, structCodegen: StructCodegen, constructorArguments: List, scopeDepth: Int): LLVMSingleValue? { val targetCall = state.bindingContext.get(BindingContext.CALL, expr) - val names = parseValueArguments(targetCall!!.valueArguments, scopeDepth) val args = codeBuilder.loadArgsIfRequired(names, constructorArguments) return evaluateConstructorCallExpression(LLVMVariable(structCodegen.fullName + LLVMType.mangleFunctionArguments(names), structCodegen.type, scope = LLVMVariableScope()), args) @@ -157,9 +155,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va expectedType.prefix = "class" } - val result = codeBuilder.getNewVariable(expectedType, pointer = 1) - codeBuilder.allocStaticVar(result) - result.pointer++ + 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") @@ -168,8 +165,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val conditionResult = codeBuilder.getNewVariable(condition.variableType) codeBuilder.addAssignment(conditionResult, condition) - codeBuilder.addCondition(conditionResult, thenLabel, elseLabel) + codeBuilder.markWithLabel(thenLabel) codeBuilder.storeNull(result) codeBuilder.addUnconditionalJump(endLabel) @@ -201,7 +198,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va is KtBinaryExpression -> evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable is KtDotQualifiedExpression -> { val codegen = resolveCodegenByName(receiverName, receiverName.split(".")) - if (codegen != null) null else evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable } is KtNameReferenceExpression -> { @@ -251,19 +247,20 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val targetFunction = state.bindingContext.get(BindingContext.CALL, selector.calleeExpression) val resolvedCall = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction) - val targetFunctionName = resolvedCall!!.candidateDescriptor.fqNameSafe.asString().removeSuffix(".") + val targetFunctionName = resolvedCall!!.candidateDescriptor.fqNameSafe.convertToNativeName() val nameWithoutMangling = resolvedCall.candidateDescriptor.name.asString().replace(Regex("""(.?)"""), "") - val packageNameFirst = targetFunction?.calleeExpression?.getContainingKtFile()?.packageFqName?.asString()?.removeSuffix(".") ?: "" - val packageNameSecond = resolvedCall.candidateDescriptor.containingDeclaration.fqNameSafe.asString().removeSuffix(".") + val packageNameFirst = targetFunction?.calleeExpression?.getContainingKtFile()?.packageFqName?.convertToNativeName() ?: "" + val packageNameSecond = resolvedCall.candidateDescriptor.containingDeclaration.fqNameSafe.convertToNativeName() val names = parseArgList(selector, scopeDepth) val type = if (names.size > 0) LLVMType.mangleFunctionArguments(names) else "" val constructedFunctionName = standardType.mangle() + nameWithoutMangling.addBeforeIfNotEmpty(".") + type + val targetExtension = state.extensionFunctions[standardType.toString()] - val extensionCodegen = state.extensionFunctions[standardType.toString()]?.get(packageNameFirst.addAfterIfNotEmpty(".") + constructedFunctionName) ?: - state.extensionFunctions[standardType.toString()]?.get(packageNameSecond.addAfterIfNotEmpty(".") + constructedFunctionName) ?: - state.extensionFunctions[standardType.toString()]?.get(targetFunctionName) + val extensionCodegen = targetExtension?.get(packageNameFirst.addAfterIfNotEmpty(".") + constructedFunctionName) ?: + targetExtension?.get(packageNameSecond.addAfterIfNotEmpty(".") + constructedFunctionName) ?: + targetExtension?.get(targetFunctionName) ?: throw UnexpectedException(constructedFunctionName) val receiverExpression = receiverExpressionArgument ?: evaluateExpression(receiver, scopeDepth + 1)!! @@ -373,7 +370,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: StructCodegen? = null): LLVMSingleValue? { - val targetName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)?.fqNameSafe?.asString()?.replace(".", "") + val targetName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)?.fqNameSafe?.convertToNativeName() return when { expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1) isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope) @@ -438,7 +435,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va if (resolvedCall is VariableAsFunctionResolvedCallImpl) { resolvedCall = resolvedCall.variableCall } - val targetFunctionName = resolvedCall!!.candidateDescriptor.fqNameSafe.asString().removeSuffix(".") + + val targetFunctionName = resolvedCall!!.candidateDescriptor.fqNameSafe.convertToNativeName() val functionDescriptor = expr.getFunctionResolvedCallWithAssert(state.bindingContext).candidateDescriptor val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values @@ -530,9 +528,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.addLLVMCode(LLVMCall(LLVMVoidType(), function.toString(), names).toString()) } is LLVMReferenceType -> { - val returnVar = codeBuilder.getNewVariable(returnType, pointer = 1) - codeBuilder.allocStaticVar(returnVar) - returnVar.pointer++ + val returnVar = codeBuilder.getNewVariable(returnType, pointer = 2) + codeBuilder.allocStaticVar(returnVar, pointer = true) val args = ArrayList() args.add(returnVar) @@ -549,9 +546,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val result = codeBuilder.getNewVariable(returnType) codeBuilder.addAssignment(result, LLVMCall(returnType, function.toString(), names)) - val resultPtr = codeBuilder.getNewVariable(returnType) - codeBuilder.allocStackVar(resultPtr) - resultPtr.pointer = 1 + val resultPtr = codeBuilder.getNewVariable(returnType, pointer = 1) + codeBuilder.allocStackVar(resultPtr, pointer = true) codeBuilder.storeVariable(resultPtr, result) return resultPtr } @@ -561,14 +557,11 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List): LLVMSingleValue? { - val store = codeBuilder.getNewVariable(function.type) - codeBuilder.allocStaticVar(store) - store.pointer++ - - val result = codeBuilder.getNewVariable(function.type, pointer = 1) - codeBuilder.allocStackVar(result) - result.pointer++ + val store = codeBuilder.getNewVariable(function.type, pointer = 1) + codeBuilder.allocStaticVar(store, pointer = true) + val result = codeBuilder.getNewVariable(function.type, pointer = 2) + codeBuilder.allocStackVar(result, pointer = true) codeBuilder.storeVariable(result, store) val args = ArrayList() @@ -595,6 +588,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va for (arg in args) { result.add(parseOneValueArgument(arg, scopeDepth)) } + return result } @@ -616,6 +610,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable? { val operator = expr.operationToken + if (operator == KtTokens.ELVIS) { return evaluateElvisOperator(expr, scopeDepth) } @@ -628,20 +623,24 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } } - left ?: throw UnsupportedOperationException("Wrong binary exception: ${expr.text}") - val right = evaluateExpression(expr.right, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception: ${expr.text}") + left ?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}") + val right = evaluateExpression(expr.right, scopeDepth) + ?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}") + return executeBinaryExpression(operator, expr.operationReference, left, right) } private fun evaluatePostfixExpression(expr: KtPostfixExpression, scopeDepth: Int): LLVMSingleValue? { val operator = expr.operationToken - val left = evaluateExpression(expr.baseExpression, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception: ${expr.text}") + val left = evaluateExpression(expr.baseExpression, scopeDepth) + ?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}") return executePostfixExpression(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 exception") + val left = evaluateExpression(expr.baseExpression, scopeDepth) + ?: throw UnsupportedOperationException("Wrong binary expression") return executePrefixExpression(operator, expr.operationReference, left) } @@ -713,7 +712,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va = addPrimitiveBinaryOperation(operator, referenceName, left, right) private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable { - val left = evaluateExpression(expr.firstChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception") + val left = evaluateExpression(expr.firstChild, scopeDepth) + ?: throw UnsupportedOperationException("Wrong binary expression") val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable) val condition = lptr.type.operatorEq(lptr, LLVMVariable("", LLVMNullType())) @@ -726,7 +726,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val endLabel = codeBuilder.getNewLabel(prefix = "elvis") codeBuilder.addCondition(conditionResult, elseLabel, thenLabel) - codeBuilder.markWithLabel(thenLabel) codeBuilder.addUnconditionalJump(endLabel) @@ -738,8 +737,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } codeBuilder.addUnconditionalJump(endLabel) - codeBuilder.markWithLabel(endLabel) + return left } @@ -881,16 +880,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return firstOp } - val result = firstOp as LLVMVariable val sourceArgument: LLVMSingleValue if (secondOp.type!!.isPrimitive() && (secondOp.pointer == 0) && (firstOp.pointer == 2)) { sourceArgument = codeBuilder.getNewVariable(secondOp.type!!, 1) - codeBuilder.allocStaticVar(sourceArgument, true) + codeBuilder.allocStaticVar(sourceArgument, asValue = true) codeBuilder.storeVariable(sourceArgument, secondOp) } else { sourceArgument = if (result.pointer == secondOp.pointer + 1) secondOp else secondNativeOp } + codeBuilder.storeVariable(result, sourceArgument) codeBuilder.addComment("end variable assignment") return result @@ -960,11 +959,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val loopParameter = state.bindingContext.get(BindingContext.VALUE_PARAMETER, expr.loopParameter!!)?.fqNameSafe?.asString() ?: expr.loopParameter!!.name!! val allocVar = variableManager.receiveVariable(loopParameter, nextDescriptor.returnType!!.type, LLVMRegisterScope(), pointer = - nextDescriptor.returnType!!.pointer) + nextDescriptor.returnType!!.pointer+1) variableManager.addVariable(loopParameter, allocVar, scopeDepth + 1) - codeBuilder.allocStackVar(allocVar) - allocVar.pointer++ - allocVar.kotlinName = loopParameter + codeBuilder.allocStackVar(allocVar, pointer = true) addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, currentParameter) @@ -1128,17 +1125,15 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va private fun evaluateValExpression(element: KtProperty, scopeDepth: Int): LLVMVariable? { val variable = state.bindingContext.get(BindingContext.VARIABLE, element)!! - val identifier = variable.fqNameSafe.asString().replace(".", "") + val identifier = variable.fqNameSafe.convertToNativeName() val assignExpression = evaluateExpression(element.delegateExpressionOrInitializer, scopeDepth) val expectedExpressionType = LLVMInstanceOfStandardType("", variable.type, state = state) val primitivePointer = LLVMMapStandardType(variable.type, state) !is LLVMReferred - val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer = expectedExpressionType.pointer) - codeBuilder.allocStackVar(allocVar) - allocVar.pointer++ - allocVar.kotlinName = identifier + val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer = expectedExpressionType.pointer+1) + codeBuilder.allocStackVar(allocVar, pointer = true) variableManager.addVariable(identifier, allocVar, scopeDepth) if (assignExpression != null) { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt index 7384b5bcc18..0823191fb57 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt @@ -68,5 +68,4 @@ class ProjectTranslator(val files: List, val state: TranslationState) { } } -} - +} \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt index 85be1dd3966..679bb0d40a2 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt @@ -146,7 +146,7 @@ abstract class StructCodegen(val state: TranslationState, variableManager.addVariable("this", classVal, 0) val secondaryConstructorArguments = descriptor!!.valueParameters.map { - LLVMInstanceOfStandardType(it.fqNameSafe.asString().replace(".", ""), it.type, state = state) + LLVMInstanceOfStandardType(it.fqNameSafe.convertToNativeName(), it.type, state = state) } argFields.add(classVal) @@ -222,7 +222,7 @@ abstract class StructCodegen(val state: TranslationState, val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {} val receiverThis = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1) - codeBuilder.addComment("field initilizers starts") + codeBuilder.addComment("field initializers starts") variableManager.addVariable("this", receiverThis, 2) for ((variable, initializer) in initializedFields) { @@ -235,7 +235,7 @@ abstract class StructCodegen(val state: TranslationState, } variableManager.pullOneUpwardLevelVariable("this") - codeBuilder.addComment("field initilizers ends") + codeBuilder.addComment("field initializers ends") } private fun generateReturn(src: LLVMVariable) { @@ -249,7 +249,7 @@ abstract class StructCodegen(val state: TranslationState, protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType): LLVMClassVariable { val annotations = parseFieldAnnotations(field) - val fieldName = state.bindingContext.get(BindingContext.VALUE_PARAMETER, field as?KtParameter)?.fqNameSafe?.asString()?.replace(".", "") + val fieldName = state.bindingContext.get(BindingContext.VALUE_PARAMETER, field as?KtParameter)?.fqNameSafe?.convertToNativeName() ?: field.fqName?.asString() ?: field.name!! val result = LLVMInstanceOfStandardType(fieldName, ktType, LLVMRegisterScope(), state = state) 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 e160643c362..7c92baddb8b 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -14,7 +14,7 @@ class LLVMBuilder(val arm: Boolean = false) { object UniqueGenerator { private var unique = 0 fun generateUniqueString(): String { - unique += 1 + unique++ return ".unique." + unique } } @@ -66,11 +66,12 @@ class LLVMBuilder(val arm: Boolean = false) { localCode.appendln("}") } - fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue = when (firstOp) { - is LLVMConstant -> firstOp - is LLVMVariable -> if (firstOp.pointer == 0) firstOp else loadAndGetVariable(firstOp) - else -> throw UnsupportedOperationException() - } + fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue = + when (firstOp) { + is LLVMConstant -> firstOp + is LLVMVariable -> if (firstOp.pointer == 0) firstOp else loadAndGetVariable(firstOp) + else -> throw UnsupportedOperationException() + } fun loadArgsIfRequired(names: List, args: List) = names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue { @@ -157,10 +158,6 @@ class LLVMBuilder(val arm: Boolean = false) { localCode.appendln("${label.label}:") } - fun addNopInstruction() { - localCode.appendln(getNewVariable(LLVMIntType()).toString() + " = add i1 0, 0 ; nop instruction") - } - fun storeVariable(target: LLVMSingleValue, source: LLVMSingleValue) { if ((source.type is LLVMStringType) && (!(source.type as LLVMStringType).isLoaded)) { storeString(target as LLVMVariable, source as LLVMVariable, 0) @@ -220,18 +217,19 @@ class LLVMBuilder(val arm: Boolean = false) { localCode.appendln(code) } - fun allocStackVar(target: LLVMVariable, asValue: Boolean = false) { - localCode.appendln("$target = alloca ${if (asValue) target.type.toString() else target.getType()}, align ${target.type.align}") + 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}") } - fun allocStaticVar(target: LLVMVariable, asValue: Boolean = false) { + fun allocStaticVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) { val allocated = getNewVariable(LLVMCharType(), pointer = 1) - val size = if (target.pointer > 0) TranslationState.pointerSize else target.type.size + 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) - val cast = "$target = bitcast ${allocated.getType()} $allocated to ${if (asValue) target.type.toString() else target.getType()}*" + val cast = "$target = bitcast ${allocated.getType()} $allocated to ${if (asValue) target.type.toString() else target.getType()}" + if (pointer) "" else "*" localCode.appendln(cast) } 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 a6183f464f4..572d48df4a1 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -3,6 +3,7 @@ package org.kotlinnative.translator.llvm import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype import org.jetbrains.kotlin.cfg.pseudocode.getSubtypesPredicate import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isUnit @@ -52,10 +53,13 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope fun LLVMMapStandardType(type: KotlinType, state: TranslationState): LLVMType = LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type -fun String.addBeforeIfNotEmpty(add: String): String { - return if (this.length > 0) add + this else this -} +fun String.addBeforeIfNotEmpty(add: String): String = + if (this.length > 0) add + this else this -fun String.addAfterIfNotEmpty(add: String): String { - return if (this.length > 0) this + add else this -} \ No newline at end of file + +fun String.addAfterIfNotEmpty(add: String): String = + if (this.length > 0) this + add else this + + +fun FqName.convertToNativeName(): String = + this.asString().replace(".", "") \ No newline at end of file diff --git a/translator/src/test/kotlin/tests/bytearray_1/bytearray_1.kt b/translator/src/test/kotlin/tests/bytearray_1/bytearray_1.kt index 94c54ef72eb..416ad831173 100644 --- a/translator/src/test/kotlin/tests/bytearray_1/bytearray_1.kt +++ b/translator/src/test/kotlin/tests/bytearray_1/bytearray_1.kt @@ -15,9 +15,11 @@ fun bytearray_1_array(): Int { } val newInstance = z.clone() ind = 0 + var result = true while(ind < size){ - assert(newInstance[ind] == ind.toByte()) + result = result and (newInstance[ind] == ind.toByte()) ind += 1 } + assert(result) return 1 }