From f2cc0337cde84b06f8c724b0a29633da9a221ee9 Mon Sep 17 00:00:00 2001 From: Alexey Stepanov Date: Thu, 1 Sep 2016 20:39:42 +0300 Subject: [PATCH] translator: refactor fucntion arguments, fix naming, use factory in TranslationState --- kotstd/include/BooleanArray.kt | 11 +- kotstd/include/ByteArray.kt | 8 +- kotstd/include/CodedInputStream.kt | 1 + kotstd/include/IntArray.kt | 8 +- kotstd/include/LongArray.kt | 8 +- kotstd/include/ShortArray.kt | 8 +- .../src/main/kotlin/DefaultArguments.kt | 3 +- translator/src/main/kotlin/main.kt | 11 +- .../kotlinnative/translator/BlockCodegen.kt | 213 +++++++++++++----- .../translator/ProjectTranslator.kt | 3 +- .../translator/PropertyCodegen.kt | 5 +- .../kotlinnative/translator/StructCodegen.kt | 10 +- .../translator/TranslationState.kt | 118 +++++----- .../translator/llvm/LLVMBuilder.kt | 8 +- .../kotlinnative/translator/llvm/LLVMCall.kt | 4 +- .../translator/llvm/LLVMClassVariable.kt | 5 +- .../translator/llvm/generators.kt | 13 +- .../translator/llvm/types/LLVMType.kt | 2 +- 18 files changed, 283 insertions(+), 156 deletions(-) diff --git a/kotstd/include/BooleanArray.kt b/kotstd/include/BooleanArray.kt index 7df7eb81e46..9c34c90ca11 100644 --- a/kotstd/include/BooleanArray.kt +++ b/kotstd/include/BooleanArray.kt @@ -3,13 +3,13 @@ package kotlin external fun kotlinclib_boolean_size(): Int class BooleanArray(var size: Int) { - val data: Int + val dataRawPtr: Int /** Returns the number of elements in the array. */ //size: Int init { - this.data = malloc_array(kotlinclib_boolean_size() * this.size) + this.dataRawPtr = malloc_array(kotlinclib_boolean_size() * this.size) var index = 0 while (index < this.size) { set(index, false) @@ -19,7 +19,7 @@ class BooleanArray(var size: Int) { /** Returns the array element at the given [index]. This method can be called using the index operator. */ operator fun get(index: Int): Boolean { - val res = kotlinclib_get_byte(this.data, index) == 1.toByte() + val res = kotlinclib_get_byte(this.dataRawPtr, index) == 1.toByte() return res } @@ -27,13 +27,12 @@ class BooleanArray(var size: Int) { /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ operator fun set(index: Int, value: Boolean) { if (value == true) { - kotlinclib_set_byte(this.data, index, 1.toByte()) + kotlinclib_set_byte(this.dataRawPtr, index, 1.toByte()) } else { - kotlinclib_set_byte(this.data, index, 0.toByte()) + kotlinclib_set_byte(this.dataRawPtr, index, 0.toByte()) } } - fun clone(): BooleanArray { val newInstance = BooleanArray(this.size) var index = 0 diff --git a/kotstd/include/ByteArray.kt b/kotstd/include/ByteArray.kt index 8952a07eb1f..b222fd43e99 100644 --- a/kotstd/include/ByteArray.kt +++ b/kotstd/include/ByteArray.kt @@ -7,13 +7,13 @@ external fun kotlinclib_byte_size(): Int class ByteArray(var size: Int) { - val data: Int + val dataRawPtr: Int /** Returns the number of elements in the array. */ //size: Int init { - this.data = malloc_array(kotlinclib_byte_size() * this.size) + this.dataRawPtr = malloc_array(kotlinclib_byte_size() * this.size) var index = 0 while (index < this.size) { @@ -24,13 +24,13 @@ class ByteArray(var size: Int) { /** Returns the array element at the given [index]. This method can be called using the index operator. */ operator fun get(index: Int): Byte { - return kotlinclib_get_byte(this.data, index) + return kotlinclib_get_byte(this.dataRawPtr, index) } /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ operator fun set(index: Int, value: Byte) { - kotlinclib_set_byte(this.data, index, value) + kotlinclib_set_byte(this.dataRawPtr, index, value) } diff --git a/kotstd/include/CodedInputStream.kt b/kotstd/include/CodedInputStream.kt index bb5b6e47cae..38cd0a28561 100644 --- a/kotstd/include/CodedInputStream.kt +++ b/kotstd/include/CodedInputStream.kt @@ -8,6 +8,7 @@ * */ +// TODO get this out of native translator stdlib // TODO: refactor correctness checks into readTag class CodedInputStream(val buffer: ByteArray) { val inputStream: KotlinInputStream diff --git a/kotstd/include/IntArray.kt b/kotstd/include/IntArray.kt index 09767b162b9..da6b43d9a94 100644 --- a/kotstd/include/IntArray.kt +++ b/kotstd/include/IntArray.kt @@ -6,13 +6,13 @@ external fun kotlinclib_int_size(): Int class IntArray(var size: Int) { - val data: Int + val dataRawPtr: Int /** Returns the number of elements in the array. */ //size: Int init { - this.data = malloc_array(kotlinclib_int_size() * this.size) + this.dataRawPtr = malloc_array(kotlinclib_int_size() * this.size) var index = 0 while (index < this.size) { set(index, 0) @@ -22,13 +22,13 @@ class IntArray(var size: Int) { /** Returns the array element at the given [index]. This method can be called using the index operator. */ operator fun get(index: Int): Int { - return kotlinclib_get_int(this.data, index) + return kotlinclib_get_int(this.dataRawPtr, index) } /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ operator fun set(index: Int, value: Int) { - kotlinclib_set_int(this.data, index, value) + kotlinclib_set_int(this.dataRawPtr, index, value) } diff --git a/kotstd/include/LongArray.kt b/kotstd/include/LongArray.kt index f8ae4fe7d03..e06dbf57f20 100644 --- a/kotstd/include/LongArray.kt +++ b/kotstd/include/LongArray.kt @@ -6,13 +6,13 @@ external fun kotlinclib_long_size(): Int class LongArray(var size: Int) { - val data: Int + val dataRawPtr: Int /** Returns the number of elements in the array. */ //size: Int init { - this.data = malloc_array(kotlinclib_long_size() * this.size) + this.dataRawPtr = malloc_array(kotlinclib_long_size() * this.size) var index = 0 while (index < this.size) { set(index, 0) @@ -22,13 +22,13 @@ class LongArray(var size: Int) { /** Returns the array element at the given [index]. This method can be called using the index operator. */ operator fun get(index: Int): Long { - return kotlinclib_get_long(this.data, index) + return kotlinclib_get_long(this.dataRawPtr, index) } /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ operator fun set(index: Int, value: Long) { - kotlinclib_set_long(this.data, index, value) + kotlinclib_set_long(this.dataRawPtr, index, value) } diff --git a/kotstd/include/ShortArray.kt b/kotstd/include/ShortArray.kt index 3d1cf82a40e..b3225f57086 100644 --- a/kotstd/include/ShortArray.kt +++ b/kotstd/include/ShortArray.kt @@ -6,13 +6,13 @@ external fun kotlinclib_short_size(): Int class ShortArray(var size: Int) { - val data: Int + val dataRawPtr: Int /** Returns the number of elements in the array. */ //size: Int init { - this.data = malloc_array(kotlinclib_short_size() * this.size) + this.dataRawPtr = malloc_array(kotlinclib_short_size() * this.size) var index = 0 while (index < this.size) { set(index, 0) @@ -22,13 +22,13 @@ class ShortArray(var size: Int) { /** Returns the array element at the given [index]. This method can be called using the index operator. */ operator fun get(index: Int): Short { - return kotlinclib_get_short(this.data, index) + return kotlinclib_get_short(this.dataRawPtr, index) } /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */ operator fun set(index: Int, value: Short) { - kotlinclib_set_short(this.data, index, value) + kotlinclib_set_short(this.dataRawPtr, index, value) } diff --git a/translator/src/main/kotlin/DefaultArguments.kt b/translator/src/main/kotlin/DefaultArguments.kt index f54bd2b048b..4f5bfcbd9a1 100644 --- a/translator/src/main/kotlin/DefaultArguments.kt +++ b/translator/src/main/kotlin/DefaultArguments.kt @@ -18,7 +18,7 @@ class DefaultArguments(raw: RawArguments) : Arguments(raw, name = "default") { val output = optionalParameter( name = "output", - description = "output file", + description = "output file path", shortNames = listOf('o') ) @@ -29,6 +29,7 @@ class DefaultArguments(raw: RawArguments) : Arguments(raw, name = "default") { shortNames = listOf('M') ) + //[TODO] files with [] or another marking val sources = positionalArguments( name = "sources", description = "source files", diff --git a/translator/src/main/kotlin/main.kt b/translator/src/main/kotlin/main.kt index 82a89f20e3a..5a91b7b8633 100644 --- a/translator/src/main/kotlin/main.kt +++ b/translator/src/main/kotlin/main.kt @@ -1,10 +1,11 @@ import com.intellij.openapi.util.Disposer import com.jshmrsn.karg.parseArguments import org.kotlinnative.translator.ProjectTranslator -import org.kotlinnative.translator.parseAndAnalyze +import org.kotlinnative.translator.TranslationState import java.io.* fun main(args: Array) { + // TODO make good help message (ex. is rm --help) val arguments = parseArguments(args, ::DefaultArguments) val disposer = Disposer.newDisposable() val analyzedFiles = arguments.sources.toMutableList() @@ -14,9 +15,11 @@ fun main(args: Array) { analyzedFiles.addAll(libraryFiles) } - val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm) - val files = state.environment.getSourceFiles() - val code = ProjectTranslator(files, state).generateCode() + val translationState = TranslationState.createTranslationState(analyzedFiles, disposer, arguments.mainClass, arguments.arm) + val code:String = ProjectTranslator( + translationState.environment.getSourceFiles(), + translationState + ).generateCode() if (arguments.output == null) { println(code) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index 373327f7458..70d924b3991 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -23,18 +23,26 @@ import java.rmi.UnexpectedException import kotlin.comparisons.compareBy -abstract class BlockCodegen(val state: TranslationState, val variableManager: VariableManager, val codeBuilder: LLVMBuilder) { +abstract class BlockCodegen(val state: TranslationState, + val variableManager: VariableManager, + val codeBuilder: LLVMBuilder) { val topLevelScopeDepth = 2 var returnType: LLVMVariable? = null var wasReturnOnTopLevel = false - fun evaluateCodeBlock(expr: PsiElement?, startLabel: LLVMLabel? = null, nextIterationLabel: LLVMLabel? = null, breakLabel: LLVMLabel? = null, scopeDepth: Int = 0, isBlock: Boolean = true) { + fun evaluateCodeBlock(expr: PsiElement?, + startLabel: LLVMLabel? = null, + nextIterationLabel: LLVMLabel? = null, + breakLabel: LLVMLabel? = null, + scopeDepth: Int = 0, + isBlock: Boolean = true) { codeBuilder.markWithLabel(startLabel) if (isBlock) { expressionWalker(expr, breakLabel, scopeDepth) } else { - var result = evaluateExpression(expr, scopeDepth) ?: throw UnexpectedException("Can't evaluate expression " + expr!!.text) + var result = evaluateExpression(expr, scopeDepth) + ?: throw UnexpectedException("Can't evaluate expression " + expr!!.text) when (result) { is LLVMVariable -> { if (result.type is LLVMReferenceType) { @@ -52,7 +60,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.addUnconditionalJump(nextIterationLabel ?: return) } - fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? = + fun evaluateExpression(expr: PsiElement?, + scopeDepth: Int): LLVMSingleValue? = when (expr) { is KtBlockExpression -> { expressionWalker(expr.lBrace, breakLabel = null, scopeDepth = scopeDepth + 1) @@ -78,26 +87,41 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va else -> throw UnsupportedOperationException() } - fun evaluateConstructorDelegationReferenceExpression(expr: KtConstructorDelegationReferenceExpression, structCodegen: StructCodegen, constructorArguments: List, scopeDepth: Int): LLVMSingleValue? { + 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.structName + LLVMType.mangleFunctionArguments(names), structCodegen.type, scope = LLVMVariableScope()), args) + return evaluateConstructorCallExpression( + LLVMVariable(structCodegen.structName + LLVMType.mangleFunctionArguments(names), + structCodegen.type, + scope = LLVMVariableScope()), + args) } - fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? { + fun evaluateMemberMethodOrField(receiver: LLVMVariable, + selectorName: String, + scopeDepth: Int, + call: PsiElement? = null): LLVMSingleValue? { val type = receiver.type as LLVMReferenceType - val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString() + receiver.toString()) + val clazz = resolveClassOrObjectLocation(type) + ?: throw UnexpectedException(type.toString() + receiver.toString()) val field = clazz.fieldsIndex[selectorName] if (field != null) { return evaluateClassField(receiver, field) } else { - return evaluateMemberMethod(receiver, clazz, scopeDepth, call as? KtCallExpression ?: throw UnexpectedException("$receiver:$selectorName")) + return evaluateMemberMethod(receiver, clazz, scopeDepth, call as? KtCallExpression + ?: throw UnexpectedException("$receiver:$selectorName")) } } - fun addPrimitiveBinaryOperation(operator: IElementType, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue, referenceName: KtSimpleNameExpression? = null): LLVMVariable { + fun addPrimitiveBinaryOperation(operator: IElementType, + firstOp: LLVMSingleValue, + secondOp: LLVMSingleValue, + referenceName: KtSimpleNameExpression? = null): LLVMVariable { val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) val secondNativeOp = codeBuilder.receiveNativeValue(secondOp) @@ -159,7 +183,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return codeBuilder.saveExpression(llvmExpression) } - private fun expressionWalker(expr: PsiElement?, breakLabel: LLVMLabel?, scopeDepth: Int) { + private fun expressionWalker(expr: PsiElement?, + breakLabel: LLVMLabel?, + scopeDepth: Int) { when (expr) { is KtBlockExpression -> expressionWalker(expr.lBrace, breakLabel, scopeDepth + 1) is KtProperty -> evaluateValExpression(expr, scopeDepth) @@ -193,7 +219,11 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? { 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) + val variable = + variableManager.receiveVariable(".str", + LLVMStringType(value.toString().length, isLoaded = false), + LLVMVariableScope(), + pointer = 0) codeBuilder.addStringConstant(variable, value.toString()) return variable @@ -202,10 +232,15 @@ 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.callableReference.text, kotlinType, LLVMVariableScope(), state) - return LLVMVariable("${result.label}${(result.type as LLVMFunctionType).mangleArgs()}", result.type, result.kotlinName, result.scope, result.pointer) + return LLVMVariable(result.label + (result.type as LLVMFunctionType).mangleArgs(), + result.type, + result.kotlinName, + result.scope, + result.pointer) } - private fun evaluateSafeAccessExpression(expr: KtSafeQualifiedExpression, scopeDepth: Int): LLVMSingleValue? { + private fun evaluateSafeAccessExpression(expr: KtSafeQualifiedExpression, + scopeDepth: Int): LLVMSingleValue? { val receiver = expr.receiverExpression val selector = expr.selectorExpression @@ -239,14 +274,17 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return result } - private fun evaluateDotExpression(expr: KtDotQualifiedExpression, scopeDepth: Int): LLVMSingleValue? { + private fun evaluateDotExpression(expr: KtDotQualifiedExpression, + scopeDepth: Int): LLVMSingleValue? { val receiverExpr = expr.receiverExpression val selectorExpr = expr.selectorExpression!! return evaluateDotBody(receiverExpr, selectorExpr, scopeDepth) } - private fun evaluateDotBody(receiverExpr: KtExpression, selectorExpr: KtExpression, scopeDepth: Int): LLVMSingleValue? { + private fun evaluateDotBody(receiverExpr: KtExpression, + selectorExpr: KtExpression, + scopeDepth: Int): LLVMSingleValue? { var receiverName = receiverExpr.text var receiver = when (receiverExpr) { is KtCallExpression, @@ -271,14 +309,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va else -> variableManager[receiverName] } - val isExtension = selectorExpr is KtCallExpression && selectorExpr.getFunctionResolvedCallWithAssert(state.bindingContext).extensionReceiver != null + val isExtension = selectorExpr is KtCallExpression && + selectorExpr.getFunctionResolvedCallWithAssert(state.bindingContext).extensionReceiver != null if (isExtension) { return evaluateExtensionExpression(receiverExpr, receiver, selectorExpr as KtCallExpression, scopeDepth) } val selectorName = when (selectorExpr) { - is KtNameReferenceExpression -> state.bindingContext.get(BindingContext.REFERENCE_TARGET, selectorExpr)?.fqNameSafe?.asString() ?: selectorExpr.text + is KtNameReferenceExpression -> state.bindingContext.get(BindingContext.REFERENCE_TARGET, selectorExpr) + ?.fqNameSafe?.asString() ?: selectorExpr.text else -> selectorExpr.text } @@ -298,7 +338,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth, receiver) } - private fun evaluateExtensionExpression(receiver: KtExpression, receiverExpressionArgument: LLVMVariable?, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? { + private fun evaluateExtensionExpression(receiver: KtExpression, + receiverExpressionArgument: LLVMVariable?, + selector: KtCallExpression, + scopeDepth: Int): LLVMSingleValue? { val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)!!.type!! val receiverType = LLVMMapStandardType(kotlinType, state) @@ -326,20 +369,27 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args) } - private fun evaluateClassScopedDotExpression(clazz: StructCodegen, selector: KtExpression, scopeDepth: Int, receiver: LLVMVariable? = null): LLVMSingleValue? = + private fun evaluateClassScopedDotExpression(clazz: StructCodegen, + selector: KtExpression, + scopeDepth: Int, + receiver: LLVMVariable? = null): LLVMSingleValue? = when (selector) { is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz, caller = receiver) is KtReferenceExpression -> evaluateReferenceExpression(selector, scopeDepth, clazz) else -> throw UnsupportedOperationException() } - private fun evaluateClassField(receiver: LLVMVariable, field: LLVMClassVariable): LLVMVariable { + private fun evaluateClassField(receiver: LLVMVariable, + field: LLVMClassVariable): LLVMVariable { val result = codeBuilder.getNewVariable(field.type, pointer = field.pointer + 1) codeBuilder.loadClassField(result, receiver, field.offset) return result } - private fun evaluateMemberMethod(receiver: LLVMVariable, clazz: StructCodegen, scopeDepth: Int, call: KtCallExpression): LLVMSingleValue? { + private 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) } @@ -387,7 +437,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return if (codegen?.structName == type.type) codegen else codegen?.nestedClasses?.get(type.type) } - private fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, scope: Int): LLVMSingleValue? { + private fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, + scope: Int): LLVMSingleValue? { val arrayNameVariable = evaluateExpression(expr.arrayExpression, scope) as LLVMVariable return when (arrayNameVariable.type) { is LLVMReferenceType -> { @@ -404,7 +455,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va val names = parseValueArguments(callMaker.valueArguments, scope) val methodName = "$targetClassName.$arrayActionType${LLVMType.mangleFunctionArguments(names)}" - val clazz = resolveClassOrObjectLocation(receiver.type) ?: throw UnexpectedException(receiver.type.toString()) + val clazz = resolveClassOrObjectLocation(receiver.type) + ?: throw UnexpectedException(receiver.type.toString()) val method = clazz.methods[methodName] ?: throw UnexpectedException(expr.text) val returnType = method.returnType!!.type @@ -429,13 +481,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } } - private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: StructCodegen? = null): LLVMSingleValue? { + private fun evaluateReferenceExpression(expr: KtReferenceExpression, + scopeDepth: Int, + classScope: StructCodegen? = null): LLVMSingleValue? { 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) (targetName != null) && variableManager.contains(targetName) -> variableManager[targetName] - ((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(targetName!!, classScope.parentCodegen!! as ClassCodegen) + ((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"] @@ -445,7 +500,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } } - private fun evaluateNameReferenceExpression(fieldName: String, classScope: ClassCodegen): LLVMSingleValue? { + private fun evaluateNameReferenceExpression(fieldName: String, + classScope: ClassCodegen): LLVMSingleValue? { val companionObject = classScope.companionObjectCodegen!! val field = companionObject.fieldsIndex[fieldName] ?: return null val receiver = variableManager[companionObject.structName]!! @@ -455,10 +511,12 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return result } - private fun resolveEnumClassField(expr: KtReferenceExpression, classScope: StructCodegen?): LLVMSingleValue = + private fun resolveEnumClassField(expr: KtReferenceExpression, + classScope: StructCodegen?): LLVMSingleValue = (classScope ?: resolveCodegen(expr))!!.enumFields[expr.text]!! - private fun isEnumClassField(expr: KtReferenceExpression, classScope: StructCodegen?): Boolean = + private fun isEnumClassField(expr: KtReferenceExpression, + classScope: StructCodegen?): Boolean = (classScope ?: resolveCodegen(expr))?.enumFields?.containsKey(expr.text) ?: false private fun resolveCodegen(expr: KtExpression): StructCodegen? { @@ -473,7 +531,10 @@ 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? { + 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) var resolvedCall = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction) @@ -537,7 +598,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return resolveCodegenByName(name) } - private fun evaluateFunctionCallExpression(function: LLVMVariable, names: List): LLVMSingleValue? { + private fun evaluateFunctionCallExpression(function: LLVMVariable, + names: List): LLVMSingleValue? { val returnType = function.type when (returnType) { is LLVMVoidType -> { @@ -569,7 +631,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } } - private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List): LLVMSingleValue? { + private fun evaluateConstructorCallExpression(function: LLVMVariable, + names: List): LLVMSingleValue? { val store = codeBuilder.getNewVariable(function.type, pointer = 1) codeBuilder.allocStaticVar(store, pointer = true) @@ -589,7 +652,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return result } - private fun parseArgList(expr: KtCallExpression, scopeDepth: Int): List = + private fun parseArgList(expr: KtCallExpression, + scopeDepth: Int): List = parseValueArguments(expr.getValueArgumentsInParentheses(), scopeDepth) private fun parseValueArguments(args: List, scopeDepth: Int): List = @@ -604,7 +668,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } }).toList() - private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable? { + private fun evaluateBinaryExpression(expr: KtBinaryExpression, + scopeDepth: Int): LLVMVariable? { val operator = expr.operationToken if (operator == KtTokens.ELVIS) { @@ -626,21 +691,24 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return addPrimitiveBinaryOperation(operator, left, right, expr.operationReference) } - private fun evaluatePostfixExpression(expr: KtPostfixExpression, scopeDepth: Int): LLVMSingleValue? { + 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 addPrimitivePostfixOperation(operator, left as LLVMVariable) } - private fun evaluatePrefixExpression(expr: KtPrefixExpression, scopeDepth: Int): LLVMSingleValue? { + private fun evaluatePrefixExpression(expr: KtPrefixExpression, + scopeDepth: Int): LLVMSingleValue? { val operator = expr.operationToken val left = evaluateExpression(expr.baseExpression, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary expression") return addPrimitivePrefixOperation(operator, left) } - private fun addPrimitivePostfixOperation(operator: IElementType?, firstOp: LLVMVariable): LLVMSingleValue? = + private fun addPrimitivePostfixOperation(operator: IElementType?, + firstOp: LLVMVariable): LLVMSingleValue? = when (operator) { KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> { val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) @@ -677,7 +745,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } - private fun addPrimitivePrefixOperation(operator: IElementType?, firstOp: LLVMSingleValue): LLVMSingleValue? = + private fun addPrimitivePrefixOperation(operator: IElementType?, + firstOp: LLVMSingleValue): LLVMSingleValue? = when (operator) { KtTokens.MINUS, KtTokens.PLUS -> addPrimitiveBinaryOperation(operator!!, LLVMConstant("0", firstOp.type), firstOp) @@ -690,7 +759,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } - private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable { + private fun evaluateElvisOperator(expr: KtBinaryExpression, + scopeDepth: Int): LLVMVariable { val left = evaluateExpression(expr.left, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary expression") val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable) @@ -717,7 +787,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return left } - private fun addPrimitiveReferenceOperationByName(operator: String, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression { + private fun addPrimitiveReferenceOperationByName(operator: String, + firstOp: LLVMSingleValue, + secondNativeOp: LLVMSingleValue): LLVMExpression { val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) return when (operator) { @@ -768,7 +840,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return LLVMConstant(expressionValue?.toString().orEmpty(), type, pointer = 0) } - private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMSingleValue? = + private fun evaluatePsiElement(element: PsiElement, + scopeDepth: Int): LLVMSingleValue? = when (element) { is LeafPsiElement -> evaluateLeafPsiElement(element, scopeDepth) is KtConstantExpression -> evaluateConstantExpression(element) @@ -776,7 +849,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } - private fun evaluateLeafPsiElement(element: LeafPsiElement, scopeDepth: Int): LLVMVariable? { + private fun evaluateLeafPsiElement(element: LeafPsiElement, + scopeDepth: Int): LLVMVariable? { return when (element.elementType) { KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth) KtTokens.IF_KEYWORD -> evaluateIfOperator(element.context as KtIfExpression, scopeDepth, isExpression = false) @@ -786,7 +860,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va } } - private fun evaluateForOperator(expr: KtForExpression, scopeDepth: Int): LLVMVariable? { + private fun evaluateForOperator(expr: KtForExpression, + scopeDepth: Int): LLVMVariable? { val range = evaluateExpression(expr.loopRange, scopeDepth + 1)!! val conditionLabel = codeBuilder.getNewLabel(prefix = "for_condition") val bodyLabel = codeBuilder.getNewLabel(prefix = "for_body") @@ -820,13 +895,19 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va addPrimitiveBinaryOperation(KtTokens.EQ, allocVar, loopParameter, null) - evaluateCodeBlock(expr.body, null, conditionLabel, exitLabel, scopeDepth + 1) + evaluateCodeBlock(expr.body, startLabel = null, nextIterationLabel = conditionLabel, breakLabel = exitLabel, scopeDepth = scopeDepth + 1) codeBuilder.markWithLabel(exitLabel) return null } - private fun evaluateWhenItem(item: KtWhenEntry, target: LLVMSingleValue, resultVariable: LLVMVariable, elseLabel: LLVMLabel, endLabel: LLVMLabel, isElse: Boolean, scopeDepth: Int) { + private fun evaluateWhenItem(item: KtWhenEntry, + target: LLVMSingleValue, + resultVariable: LLVMVariable, + elseLabel: LLVMLabel, + endLabel: LLVMLabel, + isElse: Boolean, + scopeDepth: Int) { val successConditionsLabel = codeBuilder.getNewLabel(prefix = "when_condition_success") var nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition") @@ -836,7 +917,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.markWithLabel(nextLabel) nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition") - val currentConditionExpression = evaluateExpression((condition as KtWhenConditionWithExpression).expression, scopeDepth + 1)!! + val currentConditionExpression = + evaluateExpression((condition as KtWhenConditionWithExpression).expression, scopeDepth + 1)!! val conditionResult = addPrimitiveBinaryOperation(KtTokens.EQEQ, target, currentConditionExpression) codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel) @@ -856,7 +938,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va codeBuilder.addUnconditionalJump(endLabel) } - private fun evaluateWhenExpression(expr: KtWhenExpression, scopeDepth: Int): LLVMVariable? { + private fun evaluateWhenExpression(expr: KtWhenExpression, + scopeDepth: Int): LLVMVariable? { codeBuilder.addComment("start when expression") val whenExpression = expr.subjectExpression val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!! @@ -888,7 +971,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return resultVariable } - private fun evaluateWhileOperator(expr: KtWhileExpression, scopeDepth: Int): LLVMVariable? = + private fun evaluateWhileOperator(expr: KtWhileExpression, + scopeDepth: Int): LLVMVariable? = executeWhileBlock(expr.condition!!, expr.body!!, scopeDepth, checkConditionBeforeExecute = true) private fun executeWhileBlock(condition: KtExpression, bodyExpression: PsiElement, scopeDepth: Int, checkConditionBeforeExecute: Boolean): LLVMVariable? { @@ -902,13 +986,15 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va conditionResult = codeBuilder.receivePointedArgument(conditionResult, requirePointer = 0) codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel) - evaluateCodeBlock(bodyExpression, bodyLabel, conditionLabel, exitLabel, scopeDepth + 1) + evaluateCodeBlock(bodyExpression, startLabel = bodyLabel, nextIterationLabel = conditionLabel, breakLabel = exitLabel, scopeDepth = scopeDepth + 1) codeBuilder.markWithLabel(exitLabel) return null } - private fun evaluateIfOperator(element: KtIfExpression, scopeDepth: Int, isExpression: Boolean = true): LLVMVariable? { + private fun evaluateIfOperator(element: KtIfExpression, + scopeDepth: Int, + isExpression: Boolean = true): LLVMVariable? { val conditionResult = evaluateExpression(element.condition, scopeDepth)!! val conditionNativeResult = codeBuilder.receivePointedArgument(conditionResult, requirePointer = 0) @@ -918,7 +1004,11 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va executeIfBlock(conditionNativeResult, element.then!!, element.`else`, scopeDepth + 1) } - private fun executeIfExpression(conditionResult: LLVMSingleValue, thenExpression: KtExpression, elseExpression: PsiElement?, ifExpression: KtIfExpression, scopeDepth: Int): LLVMVariable? { + private fun executeIfExpression(conditionResult: LLVMSingleValue, + thenExpression: KtExpression, + elseExpression: PsiElement?, + ifExpression: KtIfExpression, + scopeDepth: Int): LLVMVariable? { val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, ifExpression)!!.type!! val expressionType = LLVMInstanceOfStandardType("type", kotlinType, LLVMVariableScope(), state).type val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1) @@ -927,9 +1017,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va is LLVMReferenceType -> codeBuilder.allocStaticVar(resultVariable, asValue = true) else -> codeBuilder.allocStackVar(resultVariable, asValue = true) } - val thenLabel = codeBuilder.getNewLabel(prefix = "if") - val elseLabel = codeBuilder.getNewLabel(prefix = "if") - val endLabel = codeBuilder.getNewLabel(prefix = "if") + val thenLabel = codeBuilder.getNewLabel(prefix = "if_then") + val elseLabel = codeBuilder.getNewLabel(prefix = "if_else") + val endLabel = codeBuilder.getNewLabel(prefix = "if_end") codeBuilder.addCondition(conditionResult, thenLabel, elseLabel) codeBuilder.markWithLabel(thenLabel) @@ -947,23 +1037,27 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return resultVariable } - private fun executeIfBlock(conditionResult: LLVMSingleValue, thenExpression: PsiElement, elseExpression: PsiElement?, scopeDepth: Int): LLVMVariable? { + private fun executeIfBlock(conditionResult: LLVMSingleValue, + thenExpression: PsiElement, + elseExpression: PsiElement?, + scopeDepth: Int): LLVMVariable? { val thenLabel = codeBuilder.getNewLabel(prefix = "if") val elseLabel = codeBuilder.getNewLabel(prefix = "if") val endLabel = codeBuilder.getNewLabel(prefix = "if") codeBuilder.addCondition(conditionResult, thenLabel, if (elseExpression != null) elseLabel else endLabel) - evaluateCodeBlock(thenExpression, thenLabel, endLabel, endLabel, scopeDepth + 1) + evaluateCodeBlock(thenExpression, startLabel = thenLabel, nextIterationLabel = endLabel, breakLabel = endLabel, scopeDepth = scopeDepth + 1) if (elseExpression != null) { - evaluateCodeBlock(elseExpression, elseLabel, endLabel, endLabel, scopeDepth + 1) + evaluateCodeBlock(elseExpression, startLabel = elseLabel, nextIterationLabel = endLabel, breakLabel = endLabel, scopeDepth = scopeDepth + 1) } codeBuilder.markWithLabel(endLabel) return null } - private fun evaluateValExpression(element: KtProperty, scopeDepth: Int): LLVMVariable? { + private fun evaluateValExpression(element: KtProperty, + scopeDepth: Int): LLVMVariable? { val variable = state.bindingContext.get(BindingContext.VARIABLE, element)!! val identifier = variable.fqNameSafe.convertToNativeName() @@ -986,7 +1080,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va return null } - private fun evaluateReturnInstruction(element: PsiElement, scopeDepth: Int): LLVMVariable? { + private fun evaluateReturnInstruction(element: PsiElement, + scopeDepth: Int): LLVMVariable? { val next = element.getNextSiblingIgnoringWhitespaceAndComments() var retVar = evaluateExpression(next, scopeDepth) val type = retVar?.type ?: LLVMVoidType() diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt index 74bd27b53da..3b80f5a0cca 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ProjectTranslator.kt @@ -2,7 +2,8 @@ package org.kotlinnative.translator import org.jetbrains.kotlin.psi.* -class ProjectTranslator(val files: List, val state: TranslationState) { +class ProjectTranslator(val files: List, + val state: TranslationState) { private var codeBuilder = state.codeBuilder fun generateCode(): String { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt index 4c508a1cdfa..b54ee5a75c3 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt @@ -9,7 +9,10 @@ import org.kotlinnative.translator.llvm.LLVMVariable import org.kotlinnative.translator.llvm.LLVMVariableScope -class PropertyCodegen(val state: TranslationState, val variableManager: VariableManager, val property: KtProperty, val codeBuilder: LLVMBuilder) { +class PropertyCodegen(val state: TranslationState, + val variableManager: VariableManager, + val property: KtProperty, + val codeBuilder: LLVMBuilder) { fun generate() { val varInfo = state.bindingContext.get(BindingContext.VARIABLE, property)?.compileTimeInitializer ?: return diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt index a36057bcf6f..c0eba0c4635 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt @@ -12,13 +12,17 @@ import org.kotlinnative.translator.llvm.types.LLVMType import org.kotlinnative.translator.llvm.types.LLVMVoidType import java.util.* +/* + * TODO make high level description of code generation process + * and structure of generated code. + */ abstract class StructCodegen(val state: TranslationState, val variableManager: VariableManager, val classOrObject: KtClassOrObject, val codeBuilder: LLVMBuilder, val parentCodegen: StructCodegen? = null) { - val fields = ArrayList() + val fields = ArrayList() val fieldsIndex = HashMap() val nestedClasses = HashMap() val enumFields = HashMap() @@ -208,8 +212,8 @@ abstract class StructCodegen(val state: TranslationState, private fun generateReturn(src: LLVMVariable) { val dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1) - val castedDst = codeBuilder.bitcast(dst, LLVMVariable("", LLVMCharType(), pointer = 1)) - val castedSrc = codeBuilder.bitcast(src, LLVMVariable("", LLVMCharType(), pointer = 1)) + val castedDst = codeBuilder.bitcast(dst, LLVMCharType(), pointer = 1) + val castedSrc = codeBuilder.bitcast(src, LLVMCharType(), pointer = 1) codeBuilder.memcpy(castedDst, castedSrc, size) } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt index 35b72d97c75..ca42610b186 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt @@ -25,17 +25,14 @@ import org.kotlinnative.translator.llvm.LLVMBuilder import org.kotlinnative.translator.llvm.LLVMVariable import java.util.* -class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val mainFunction: String, arm: Boolean) { - companion object { - var POINTER_ALIGN = 4 - var POINTER_SIZE = 4 - } - - init { - POINTER_ALIGN = if (arm) 4 else 8 - POINTER_SIZE = if (arm) 4 else 8 - } +class TranslationState +private constructor +( + val environment: KotlinCoreEnvironment, + val bindingContext: BindingContext, + val mainFunction: String, arm: Boolean +) { var externalFunctions = HashMap() var functions = HashMap() val globalVariableCollection = HashMap() @@ -45,60 +42,71 @@ class TranslationState(val environment: KotlinCoreEnvironment, val bindingContex val codeBuilder = LLVMBuilder(arm) val extensionFunctions = HashMap>() -} - -fun parseAndAnalyze(sources: List, disposer: Disposable, mainFunction: String, arm: Boolean = false): TranslationState { - - val configuration = CompilerConfiguration() - val messageCollector = object : MessageCollector { - private var hasError = false - - override fun hasErrors(): Boolean = hasError - - override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) { - if (severity.isError) { - System.err.println("[${severity.toString()}]${location.path} ${location.line}:${location.column} $message") - hasError = true - } - } + init { + POINTER_ALIGN = if (arm) 4 else 8 + POINTER_SIZE = if (arm) 4 else 8 } - configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector) - configuration.put(JVMConfigurationKeys.MODULE_NAME, JvmAbi.DEFAULT_MODULE_NAME) + companion object { + var POINTER_ALIGN = 4 + var POINTER_SIZE = 4 - configuration.addKotlinSourceRoots(sources) + fun createTranslationState(sources: List, disposer: Disposable, mainFunction: String, arm: Boolean = false): TranslationState { - val environment = KotlinCoreEnvironment.createForProduction(disposer, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) - val bindingContext = analyze(environment)?.bindingContext ?: throw TranslationException("Can't initialize binding context for project") + val configuration = CompilerConfiguration() + val messageCollector = object : MessageCollector { + private var hasError = false - return TranslationState(environment, bindingContext, mainFunction, arm) -} + override fun hasErrors(): Boolean = hasError -fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? { - val collector = environment.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) { + if (severity.isError) { + System.err.println("[${severity.toString()}]${location.path} ${location.line}:${location.column} $message") + hasError = true + } + } + } - val analyzer = AnalyzerWithCompilerReport(collector) - analyzer.analyzeAndReport(environment.getSourceFiles(), object : AnalyzerWithCompilerReport.Analyzer { - override fun analyze(): AnalysisResult { - val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace() - val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project, environment.getModuleName()) + configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector) + configuration.put(JVMConfigurationKeys.MODULE_NAME, JvmAbi.DEFAULT_MODULE_NAME) - return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext( - moduleContext, - environment.getSourceFiles(), - sharedTrace, - environment.configuration.get(JVMConfigurationKeys.MODULES), - environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS), - JvmPackagePartProvider(environment)) + configuration.addKotlinSourceRoots(sources) + + val environment = KotlinCoreEnvironment.createForProduction(disposer, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) + val bindingContext = analyze(environment)?.bindingContext ?: throw TranslationException("Can't initialize binding context for project") + + return TranslationState(environment, bindingContext, mainFunction, arm) } - override fun reportEnvironmentErrors() { - val files = environment.configuration.jvmClasspathRoots - val runtimes = files.map { it.canonicalFile }.filter { it.name == PathUtil.KOTLIN_JAVA_RUNTIME_JAR && it.exists() } - collector.report(CompilerMessageSeverity.ERROR, runtimes.joinToString { it.path }, CompilerMessageLocation.NO_LOCATION) - System.err.println(runtimes.joinToString { it.toString() }) - } - }) + private fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? { + val collector = environment.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + + val analyzer = AnalyzerWithCompilerReport(collector) + analyzer.analyzeAndReport(environment.getSourceFiles(), object : AnalyzerWithCompilerReport.Analyzer { + override fun analyze(): AnalysisResult { + val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace() + val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project, environment.getModuleName()) + + return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext( + moduleContext, + environment.getSourceFiles(), + sharedTrace, + environment.configuration.get(JVMConfigurationKeys.MODULES), + environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS), + JvmPackagePartProvider(environment)) + } + + override fun reportEnvironmentErrors() { + val files = environment.configuration.jvmClasspathRoots + val runtimes = files.map { it.canonicalFile }.filter { it.name == PathUtil.KOTLIN_JAVA_RUNTIME_JAR && it.exists() } + collector.report(CompilerMessageSeverity.ERROR, runtimes.joinToString { it.path }, CompilerMessageLocation.NO_LOCATION) + System.err.println(runtimes.joinToString { it.toString() }) + } + }) + + return if (analyzer.hasErrors()) null else analyzer.analysisResult + } + + } - return if (analyzer.hasErrors()) null else analyzer.analysisResult } \ No newline at end of file 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 0bf1ea74eb7..e4646d7eef5 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -95,16 +95,16 @@ class LLVMBuilder(arm: Boolean = false) { addLLVMCodeToLocalPlace("$target = bitcast ${allocated.pointedType} $allocated to ${if (asValue) target.type.toString() else target.pointedType}" + if (pointer) "" else "*") } - fun addGlobalInitialize(target: LLVMVariable, fields: ArrayList, initializers: Map, classType: LLVMType) { + fun addGlobalInitialize(target: LLVMVariable, fields: ArrayList, initializers: Map, classType: LLVMType) { val code = "$target = internal global $classType { ${ fields.map { it.pointedType + " " + if (initializers.containsKey(it)) initializers[it] else "0" }.joinToString() } }, align ${classType.align}" addLLVMCodeToGlobalPlace(code) } - fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable { - val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer) - addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.pointedType}") + fun bitcast(src: LLVMVariable, llvmType: LLVMType, pointer: Int): LLVMVariable { + val empty = getNewVariable(llvmType, pointer = pointer) + addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.toString() + "*".repeat(pointer)}") return empty } 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 df641a2a523..b704798aa0d 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt @@ -2,7 +2,9 @@ package org.kotlinnative.translator.llvm import org.kotlinnative.translator.llvm.types.LLVMType -class LLVMCall(val returnType: LLVMType, val name: String, val arguments: Collection) : LLVMSingleValue(returnType) { +class LLVMCall(val returnType: LLVMType, + val name: String, + val arguments: Collection) : LLVMSingleValue(returnType) { override fun toString() = "call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})" 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 e7cadf53d86..780fb40d759 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMClassVariable.kt @@ -2,4 +2,7 @@ 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 +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/generators.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt index 2f4a9bffc6e..ea1b234f28a 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -10,13 +10,19 @@ import org.kotlinnative.translator.TranslationState import org.kotlinnative.translator.llvm.types.* -fun LLVMFunctionDescriptor(name: String, argTypes: List?, returnType: LLVMType, declare: Boolean = false) = +fun LLVMFunctionDescriptor(name: String, + argTypes: List?, + returnType: LLVMType, + declare: Boolean = false) = "${if (declare) "declare" else "define weak"} $returnType @$name(${ argTypes?.mapIndexed { i: Int, s: LLVMVariable -> "${s.pointedType} ${if (s.type is LLVMReferenceType && !s.type.byRef) "byval" else ""} %${s.label}" }?.joinToString()}) #0" -fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable { +fun LLVMInstanceOfStandardType(name: String, + type: KotlinType, + scope: LLVMScope = LLVMRegisterScope(), + state: TranslationState): LLVMVariable { val typeName = type.toString().dropLastWhile { it == '?' } val pointerMark = if (type.isMarkedNullable) 1 else 0 return when { @@ -43,7 +49,8 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope } } -fun LLVMMapStandardType(type: KotlinType, state: TranslationState) = +fun LLVMMapStandardType(type: KotlinType, + state: TranslationState) = LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type fun String.addBeforeIfNotEmpty(add: String): String = diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt index 08279e0b37d..09bb453ae22 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt @@ -4,7 +4,7 @@ import org.kotlinnative.translator.exceptions.UnimplementedException import org.kotlinnative.translator.llvm.LLVMExpression import org.kotlinnative.translator.llvm.LLVMSingleValue -abstract class LLVMType() : Cloneable { +abstract class LLVMType() { companion object { fun mangleFunctionArguments(names: List) =