translator: refactor fucntion arguments, fix naming, use factory in TranslationState
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<String>) {
|
||||
// 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<String>) {
|
||||
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)
|
||||
|
||||
@@ -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<LLVMVariable>, scopeDepth: Int): LLVMSingleValue? {
|
||||
fun evaluateConstructorDelegationReferenceExpression(expr: KtConstructorDelegationReferenceExpression,
|
||||
structCodegen: StructCodegen,
|
||||
constructorArguments: List<LLVMVariable>,
|
||||
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>): LLVMSingleValue? {
|
||||
private fun evaluateFunctionCallExpression(function: LLVMVariable,
|
||||
names: List<LLVMSingleValue>): 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>): LLVMSingleValue? {
|
||||
private fun evaluateConstructorCallExpression(function: LLVMVariable,
|
||||
names: List<LLVMSingleValue>): 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<LLVMSingleValue> =
|
||||
private fun parseArgList(expr: KtCallExpression,
|
||||
scopeDepth: Int): List<LLVMSingleValue> =
|
||||
parseValueArguments(expr.getValueArgumentsInParentheses(), scopeDepth)
|
||||
|
||||
private fun parseValueArguments(args: List<ValueArgument>, scopeDepth: Int): List<LLVMSingleValue> =
|
||||
@@ -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()
|
||||
|
||||
@@ -2,7 +2,8 @@ package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class ProjectTranslator(val files: List<KtFile>, val state: TranslationState) {
|
||||
class ProjectTranslator(val files: List<KtFile>,
|
||||
val state: TranslationState) {
|
||||
private var codeBuilder = state.codeBuilder
|
||||
|
||||
fun generateCode(): String {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<LLVMVariable>()
|
||||
val fields = ArrayList<LLVMClassVariable>()
|
||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||
val nestedClasses = HashMap<String, ClassCodegen>()
|
||||
val enumFields = HashMap<String, LLVMVariable>()
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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<String, FunctionCodegen>()
|
||||
var functions = HashMap<String, FunctionCodegen>()
|
||||
val globalVariableCollection = HashMap<String, LLVMVariable>()
|
||||
@@ -45,60 +42,71 @@ class TranslationState(val environment: KotlinCoreEnvironment, val bindingContex
|
||||
val codeBuilder = LLVMBuilder(arm)
|
||||
val extensionFunctions = HashMap<String, HashMap<String, FunctionCodegen>>()
|
||||
|
||||
}
|
||||
|
||||
fun parseAndAnalyze(sources: List<String>, 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<String>, 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
|
||||
}
|
||||
@@ -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<LLVMVariable>, initializers: Map<LLVMVariable, String>, classType: LLVMType) {
|
||||
fun addGlobalInitialize(target: LLVMVariable, fields: ArrayList<LLVMClassVariable>, initializers: Map<LLVMVariable, String>, 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
|
||||
}
|
||||
|
||||
|
||||
@@ -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>) : LLVMSingleValue(returnType) {
|
||||
class LLVMCall(val returnType: LLVMType,
|
||||
val name: String,
|
||||
val arguments: Collection<LLVMSingleValue>) : LLVMSingleValue(returnType) {
|
||||
|
||||
override fun toString() = "call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})"
|
||||
|
||||
|
||||
@@ -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)
|
||||
class LLVMClassVariable(label: String,
|
||||
type: LLVMType,
|
||||
pointer: Int = 0,
|
||||
var offset: Int = 0) : LLVMVariable(label, type, pointer = pointer)
|
||||
@@ -10,13 +10,19 @@ import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
|
||||
|
||||
fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnType: LLVMType, declare: Boolean = false) =
|
||||
fun LLVMFunctionDescriptor(name: String,
|
||||
argTypes: List<LLVMVariable>?,
|
||||
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 =
|
||||
|
||||
@@ -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<LLVMSingleValue>) =
|
||||
|
||||
Reference in New Issue
Block a user