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
|
external fun kotlinclib_boolean_size(): Int
|
||||||
|
|
||||||
class BooleanArray(var size: Int) {
|
class BooleanArray(var size: Int) {
|
||||||
val data: Int
|
val dataRawPtr: Int
|
||||||
|
|
||||||
/** Returns the number of elements in the array. */
|
/** Returns the number of elements in the array. */
|
||||||
//size: Int
|
//size: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.data = malloc_array(kotlinclib_boolean_size() * this.size)
|
this.dataRawPtr = malloc_array(kotlinclib_boolean_size() * this.size)
|
||||||
var index = 0
|
var index = 0
|
||||||
while (index < this.size) {
|
while (index < this.size) {
|
||||||
set(index, false)
|
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. */
|
/** Returns the array element at the given [index]. This method can be called using the index operator. */
|
||||||
operator fun get(index: Int): Boolean {
|
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
|
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. */
|
/** 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) {
|
operator fun set(index: Int, value: Boolean) {
|
||||||
if (value == true) {
|
if (value == true) {
|
||||||
kotlinclib_set_byte(this.data, index, 1.toByte())
|
kotlinclib_set_byte(this.dataRawPtr, index, 1.toByte())
|
||||||
} else {
|
} else {
|
||||||
kotlinclib_set_byte(this.data, index, 0.toByte())
|
kotlinclib_set_byte(this.dataRawPtr, index, 0.toByte())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun clone(): BooleanArray {
|
fun clone(): BooleanArray {
|
||||||
val newInstance = BooleanArray(this.size)
|
val newInstance = BooleanArray(this.size)
|
||||||
var index = 0
|
var index = 0
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ external fun kotlinclib_byte_size(): Int
|
|||||||
|
|
||||||
|
|
||||||
class ByteArray(var size: Int) {
|
class ByteArray(var size: Int) {
|
||||||
val data: Int
|
val dataRawPtr: Int
|
||||||
|
|
||||||
/** Returns the number of elements in the array. */
|
/** Returns the number of elements in the array. */
|
||||||
//size: Int
|
//size: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.data = malloc_array(kotlinclib_byte_size() * this.size)
|
this.dataRawPtr = malloc_array(kotlinclib_byte_size() * this.size)
|
||||||
var index = 0
|
var index = 0
|
||||||
|
|
||||||
while (index < this.size) {
|
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. */
|
/** Returns the array element at the given [index]. This method can be called using the index operator. */
|
||||||
operator fun get(index: Int): Byte {
|
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. */
|
/** 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) {
|
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
|
// TODO: refactor correctness checks into readTag
|
||||||
class CodedInputStream(val buffer: ByteArray) {
|
class CodedInputStream(val buffer: ByteArray) {
|
||||||
val inputStream: KotlinInputStream
|
val inputStream: KotlinInputStream
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ external fun kotlinclib_int_size(): Int
|
|||||||
|
|
||||||
|
|
||||||
class IntArray(var size: Int) {
|
class IntArray(var size: Int) {
|
||||||
val data: Int
|
val dataRawPtr: Int
|
||||||
|
|
||||||
/** Returns the number of elements in the array. */
|
/** Returns the number of elements in the array. */
|
||||||
//size: Int
|
//size: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.data = malloc_array(kotlinclib_int_size() * this.size)
|
this.dataRawPtr = malloc_array(kotlinclib_int_size() * this.size)
|
||||||
var index = 0
|
var index = 0
|
||||||
while (index < this.size) {
|
while (index < this.size) {
|
||||||
set(index, 0)
|
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. */
|
/** Returns the array element at the given [index]. This method can be called using the index operator. */
|
||||||
operator fun get(index: Int): Int {
|
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. */
|
/** 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) {
|
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) {
|
class LongArray(var size: Int) {
|
||||||
val data: Int
|
val dataRawPtr: Int
|
||||||
|
|
||||||
/** Returns the number of elements in the array. */
|
/** Returns the number of elements in the array. */
|
||||||
//size: Int
|
//size: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.data = malloc_array(kotlinclib_long_size() * this.size)
|
this.dataRawPtr = malloc_array(kotlinclib_long_size() * this.size)
|
||||||
var index = 0
|
var index = 0
|
||||||
while (index < this.size) {
|
while (index < this.size) {
|
||||||
set(index, 0)
|
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. */
|
/** Returns the array element at the given [index]. This method can be called using the index operator. */
|
||||||
operator fun get(index: Int): Long {
|
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. */
|
/** 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) {
|
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) {
|
class ShortArray(var size: Int) {
|
||||||
val data: Int
|
val dataRawPtr: Int
|
||||||
|
|
||||||
/** Returns the number of elements in the array. */
|
/** Returns the number of elements in the array. */
|
||||||
//size: Int
|
//size: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.data = malloc_array(kotlinclib_short_size() * this.size)
|
this.dataRawPtr = malloc_array(kotlinclib_short_size() * this.size)
|
||||||
var index = 0
|
var index = 0
|
||||||
while (index < this.size) {
|
while (index < this.size) {
|
||||||
set(index, 0)
|
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. */
|
/** Returns the array element at the given [index]. This method can be called using the index operator. */
|
||||||
operator fun get(index: Int): Short {
|
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. */
|
/** 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) {
|
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(
|
val output = optionalParameter(
|
||||||
name = "output",
|
name = "output",
|
||||||
description = "output file",
|
description = "output file path",
|
||||||
shortNames = listOf('o')
|
shortNames = listOf('o')
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ class DefaultArguments(raw: RawArguments) : Arguments(raw, name = "default") {
|
|||||||
shortNames = listOf('M')
|
shortNames = listOf('M')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//[TODO] files with [] or another marking
|
||||||
val sources = positionalArguments(
|
val sources = positionalArguments(
|
||||||
name = "sources",
|
name = "sources",
|
||||||
description = "source files",
|
description = "source files",
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.jshmrsn.karg.parseArguments
|
import com.jshmrsn.karg.parseArguments
|
||||||
import org.kotlinnative.translator.ProjectTranslator
|
import org.kotlinnative.translator.ProjectTranslator
|
||||||
import org.kotlinnative.translator.parseAndAnalyze
|
import org.kotlinnative.translator.TranslationState
|
||||||
import java.io.*
|
import java.io.*
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
|
// TODO make good help message (ex. is rm --help)
|
||||||
val arguments = parseArguments(args, ::DefaultArguments)
|
val arguments = parseArguments(args, ::DefaultArguments)
|
||||||
val disposer = Disposer.newDisposable()
|
val disposer = Disposer.newDisposable()
|
||||||
val analyzedFiles = arguments.sources.toMutableList()
|
val analyzedFiles = arguments.sources.toMutableList()
|
||||||
@@ -14,9 +15,11 @@ fun main(args: Array<String>) {
|
|||||||
analyzedFiles.addAll(libraryFiles)
|
analyzedFiles.addAll(libraryFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm)
|
val translationState = TranslationState.createTranslationState(analyzedFiles, disposer, arguments.mainClass, arguments.arm)
|
||||||
val files = state.environment.getSourceFiles()
|
val code:String = ProjectTranslator(
|
||||||
val code = ProjectTranslator(files, state).generateCode()
|
translationState.environment.getSourceFiles(),
|
||||||
|
translationState
|
||||||
|
).generateCode()
|
||||||
|
|
||||||
if (arguments.output == null) {
|
if (arguments.output == null) {
|
||||||
println(code)
|
println(code)
|
||||||
|
|||||||
@@ -23,18 +23,26 @@ import java.rmi.UnexpectedException
|
|||||||
import kotlin.comparisons.compareBy
|
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
|
val topLevelScopeDepth = 2
|
||||||
var returnType: LLVMVariable? = null
|
var returnType: LLVMVariable? = null
|
||||||
var wasReturnOnTopLevel = false
|
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)
|
codeBuilder.markWithLabel(startLabel)
|
||||||
if (isBlock) {
|
if (isBlock) {
|
||||||
expressionWalker(expr, breakLabel, scopeDepth)
|
expressionWalker(expr, breakLabel, scopeDepth)
|
||||||
} else {
|
} 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) {
|
when (result) {
|
||||||
is LLVMVariable -> {
|
is LLVMVariable -> {
|
||||||
if (result.type is LLVMReferenceType) {
|
if (result.type is LLVMReferenceType) {
|
||||||
@@ -52,7 +60,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
codeBuilder.addUnconditionalJump(nextIterationLabel ?: return)
|
codeBuilder.addUnconditionalJump(nextIterationLabel ?: return)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? =
|
fun evaluateExpression(expr: PsiElement?,
|
||||||
|
scopeDepth: Int): LLVMSingleValue? =
|
||||||
when (expr) {
|
when (expr) {
|
||||||
is KtBlockExpression -> {
|
is KtBlockExpression -> {
|
||||||
expressionWalker(expr.lBrace, breakLabel = null, scopeDepth = scopeDepth + 1)
|
expressionWalker(expr.lBrace, breakLabel = null, scopeDepth = scopeDepth + 1)
|
||||||
@@ -78,26 +87,41 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
else -> throw UnsupportedOperationException()
|
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 targetCall = state.bindingContext.get(BindingContext.CALL, expr)
|
||||||
val names = parseValueArguments(targetCall!!.valueArguments, scopeDepth)
|
val names = parseValueArguments(targetCall!!.valueArguments, scopeDepth)
|
||||||
val args = codeBuilder.loadArgsIfRequired(names, constructorArguments)
|
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 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]
|
val field = clazz.fieldsIndex[selectorName]
|
||||||
|
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
return evaluateClassField(receiver, field)
|
return evaluateClassField(receiver, field)
|
||||||
} else {
|
} 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 firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
|
||||||
val secondNativeOp = codeBuilder.receiveNativeValue(secondOp)
|
val secondNativeOp = codeBuilder.receiveNativeValue(secondOp)
|
||||||
|
|
||||||
@@ -159,7 +183,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return codeBuilder.saveExpression(llvmExpression)
|
return codeBuilder.saveExpression(llvmExpression)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun expressionWalker(expr: PsiElement?, breakLabel: LLVMLabel?, scopeDepth: Int) {
|
private fun expressionWalker(expr: PsiElement?,
|
||||||
|
breakLabel: LLVMLabel?,
|
||||||
|
scopeDepth: Int) {
|
||||||
when (expr) {
|
when (expr) {
|
||||||
is KtBlockExpression -> expressionWalker(expr.lBrace, breakLabel, scopeDepth + 1)
|
is KtBlockExpression -> expressionWalker(expr.lBrace, breakLabel, scopeDepth + 1)
|
||||||
is KtProperty -> evaluateValExpression(expr, scopeDepth)
|
is KtProperty -> evaluateValExpression(expr, scopeDepth)
|
||||||
@@ -193,7 +219,11 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? {
|
fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? {
|
||||||
val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr) as TypedCompileTimeConstant
|
val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr) as TypedCompileTimeConstant
|
||||||
val value = receiveValue.getValue(receiveValue.type) ?: return null
|
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())
|
codeBuilder.addStringConstant(variable, value.toString())
|
||||||
return variable
|
return variable
|
||||||
@@ -202,10 +232,15 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? {
|
private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? {
|
||||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||||
val result = LLVMInstanceOfStandardType(expr.callableReference.text, kotlinType, LLVMVariableScope(), state)
|
val result = LLVMInstanceOfStandardType(expr.callableReference.text, kotlinType, LLVMVariableScope(), state)
|
||||||
return LLVMVariable("${result.label}${(result.type as LLVMFunctionType).mangleArgs()}", result.type, result.kotlinName, result.scope, result.pointer)
|
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 receiver = expr.receiverExpression
|
||||||
val selector = expr.selectorExpression
|
val selector = expr.selectorExpression
|
||||||
|
|
||||||
@@ -239,14 +274,17 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateDotExpression(expr: KtDotQualifiedExpression, scopeDepth: Int): LLVMSingleValue? {
|
private fun evaluateDotExpression(expr: KtDotQualifiedExpression,
|
||||||
|
scopeDepth: Int): LLVMSingleValue? {
|
||||||
val receiverExpr = expr.receiverExpression
|
val receiverExpr = expr.receiverExpression
|
||||||
val selectorExpr = expr.selectorExpression!!
|
val selectorExpr = expr.selectorExpression!!
|
||||||
|
|
||||||
return evaluateDotBody(receiverExpr, selectorExpr, scopeDepth)
|
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 receiverName = receiverExpr.text
|
||||||
var receiver = when (receiverExpr) {
|
var receiver = when (receiverExpr) {
|
||||||
is KtCallExpression,
|
is KtCallExpression,
|
||||||
@@ -271,14 +309,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
else -> variableManager[receiverName]
|
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) {
|
if (isExtension) {
|
||||||
return evaluateExtensionExpression(receiverExpr, receiver, selectorExpr as KtCallExpression, scopeDepth)
|
return evaluateExtensionExpression(receiverExpr, receiver, selectorExpr as KtCallExpression, scopeDepth)
|
||||||
}
|
}
|
||||||
|
|
||||||
val selectorName = when (selectorExpr) {
|
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
|
else -> selectorExpr.text
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +338,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth, receiver)
|
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 kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)!!.type!!
|
||||||
val receiverType = LLVMMapStandardType(kotlinType, state)
|
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)
|
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) {
|
when (selector) {
|
||||||
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz, caller = receiver)
|
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz, caller = receiver)
|
||||||
is KtReferenceExpression -> evaluateReferenceExpression(selector, scopeDepth, clazz)
|
is KtReferenceExpression -> evaluateReferenceExpression(selector, scopeDepth, clazz)
|
||||||
else -> throw UnsupportedOperationException()
|
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)
|
val result = codeBuilder.getNewVariable(field.type, pointer = field.pointer + 1)
|
||||||
codeBuilder.loadClassField(result, receiver, field.offset)
|
codeBuilder.loadClassField(result, receiver, field.offset)
|
||||||
return result
|
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 resolvedCall = call.getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext)
|
||||||
val functionDescriptor = resolvedCall.candidateDescriptor
|
val functionDescriptor = resolvedCall.candidateDescriptor
|
||||||
val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) }
|
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)
|
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
|
val arrayNameVariable = evaluateExpression(expr.arrayExpression, scope) as LLVMVariable
|
||||||
return when (arrayNameVariable.type) {
|
return when (arrayNameVariable.type) {
|
||||||
is LLVMReferenceType -> {
|
is LLVMReferenceType -> {
|
||||||
@@ -404,7 +455,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
|
|
||||||
val names = parseValueArguments(callMaker.valueArguments, scope)
|
val names = parseValueArguments(callMaker.valueArguments, scope)
|
||||||
val methodName = "$targetClassName.$arrayActionType${LLVMType.mangleFunctionArguments(names)}"
|
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 method = clazz.methods[methodName] ?: throw UnexpectedException(expr.text)
|
||||||
val returnType = method.returnType!!.type
|
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()
|
val targetName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)?.fqNameSafe?.convertToNativeName()
|
||||||
return when {
|
return when {
|
||||||
expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
|
expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
|
||||||
isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope)
|
isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope)
|
||||||
(targetName != null) && variableManager.contains(targetName) -> variableManager[targetName]
|
(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 -> {
|
else -> {
|
||||||
val clazz = classScope ?: resolveCodegen(expr)
|
val clazz = classScope ?: resolveCodegen(expr)
|
||||||
val receiver = if (clazz != null) variableManager[clazz.structName] ?: variableManager["this"] else variableManager["this"]
|
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 companionObject = classScope.companionObjectCodegen!!
|
||||||
val field = companionObject.fieldsIndex[fieldName] ?: return null
|
val field = companionObject.fieldsIndex[fieldName] ?: return null
|
||||||
val receiver = variableManager[companionObject.structName]!!
|
val receiver = variableManager[companionObject.structName]!!
|
||||||
@@ -455,10 +511,12 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveEnumClassField(expr: KtReferenceExpression, classScope: StructCodegen?): LLVMSingleValue =
|
private fun resolveEnumClassField(expr: KtReferenceExpression,
|
||||||
|
classScope: StructCodegen?): LLVMSingleValue =
|
||||||
(classScope ?: resolveCodegen(expr))!!.enumFields[expr.text]!!
|
(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
|
(classScope ?: resolveCodegen(expr))?.enumFields?.containsKey(expr.text) ?: false
|
||||||
|
|
||||||
private fun resolveCodegen(expr: KtExpression): StructCodegen? {
|
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? =
|
private fun resolveCodegenByName(name: String): StructCodegen? =
|
||||||
resolveClassOrObjectLocation(LLVMReferenceType(name, prefix = "class"))
|
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)
|
var names = parseArgList(expr, scopeDepth)
|
||||||
val targetFunction = state.bindingContext.get(BindingContext.CALL, expr.calleeExpression)
|
val targetFunction = state.bindingContext.get(BindingContext.CALL, expr.calleeExpression)
|
||||||
var resolvedCall = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction)
|
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)
|
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
|
val returnType = function.type
|
||||||
when (returnType) {
|
when (returnType) {
|
||||||
is LLVMVoidType -> {
|
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)
|
val store = codeBuilder.getNewVariable(function.type, pointer = 1)
|
||||||
codeBuilder.allocStaticVar(store, pointer = true)
|
codeBuilder.allocStaticVar(store, pointer = true)
|
||||||
|
|
||||||
@@ -589,7 +652,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseArgList(expr: KtCallExpression, scopeDepth: Int): List<LLVMSingleValue> =
|
private fun parseArgList(expr: KtCallExpression,
|
||||||
|
scopeDepth: Int): List<LLVMSingleValue> =
|
||||||
parseValueArguments(expr.getValueArgumentsInParentheses(), scopeDepth)
|
parseValueArguments(expr.getValueArgumentsInParentheses(), scopeDepth)
|
||||||
|
|
||||||
private fun parseValueArguments(args: List<ValueArgument>, scopeDepth: Int): List<LLVMSingleValue> =
|
private fun parseValueArguments(args: List<ValueArgument>, scopeDepth: Int): List<LLVMSingleValue> =
|
||||||
@@ -604,7 +668,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
}
|
}
|
||||||
}).toList()
|
}).toList()
|
||||||
|
|
||||||
private fun evaluateBinaryExpression(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable? {
|
private fun evaluateBinaryExpression(expr: KtBinaryExpression,
|
||||||
|
scopeDepth: Int): LLVMVariable? {
|
||||||
val operator = expr.operationToken
|
val operator = expr.operationToken
|
||||||
|
|
||||||
if (operator == KtTokens.ELVIS) {
|
if (operator == KtTokens.ELVIS) {
|
||||||
@@ -626,21 +691,24 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return addPrimitiveBinaryOperation(operator, left, right, expr.operationReference)
|
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 operator = expr.operationToken
|
||||||
val left = evaluateExpression(expr.baseExpression, scopeDepth)
|
val left = evaluateExpression(expr.baseExpression, scopeDepth)
|
||||||
?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}")
|
?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}")
|
||||||
return addPrimitivePostfixOperation(operator, left as LLVMVariable)
|
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 operator = expr.operationToken
|
||||||
val left = evaluateExpression(expr.baseExpression, scopeDepth)
|
val left = evaluateExpression(expr.baseExpression, scopeDepth)
|
||||||
?: throw UnsupportedOperationException("Wrong binary expression")
|
?: throw UnsupportedOperationException("Wrong binary expression")
|
||||||
return addPrimitivePrefixOperation(operator, left)
|
return addPrimitivePrefixOperation(operator, left)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addPrimitivePostfixOperation(operator: IElementType?, firstOp: LLVMVariable): LLVMSingleValue? =
|
private fun addPrimitivePostfixOperation(operator: IElementType?,
|
||||||
|
firstOp: LLVMVariable): LLVMSingleValue? =
|
||||||
when (operator) {
|
when (operator) {
|
||||||
KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> {
|
KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> {
|
||||||
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
|
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) {
|
when (operator) {
|
||||||
KtTokens.MINUS,
|
KtTokens.MINUS,
|
||||||
KtTokens.PLUS -> addPrimitiveBinaryOperation(operator!!, LLVMConstant("0", firstOp.type), firstOp)
|
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)
|
val left = evaluateExpression(expr.left, scopeDepth)
|
||||||
?: throw UnsupportedOperationException("Wrong binary expression")
|
?: throw UnsupportedOperationException("Wrong binary expression")
|
||||||
val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable)
|
val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable)
|
||||||
@@ -717,7 +787,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return left
|
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)
|
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
|
||||||
|
|
||||||
return when (operator) {
|
return when (operator) {
|
||||||
@@ -768,7 +840,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return LLVMConstant(expressionValue?.toString().orEmpty(), type, pointer = 0)
|
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) {
|
when (element) {
|
||||||
is LeafPsiElement -> evaluateLeafPsiElement(element, scopeDepth)
|
is LeafPsiElement -> evaluateLeafPsiElement(element, scopeDepth)
|
||||||
is KtConstantExpression -> evaluateConstantExpression(element)
|
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) {
|
return when (element.elementType) {
|
||||||
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth)
|
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element, scopeDepth)
|
||||||
KtTokens.IF_KEYWORD -> evaluateIfOperator(element.context as KtIfExpression, scopeDepth, isExpression = false)
|
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 range = evaluateExpression(expr.loopRange, scopeDepth + 1)!!
|
||||||
val conditionLabel = codeBuilder.getNewLabel(prefix = "for_condition")
|
val conditionLabel = codeBuilder.getNewLabel(prefix = "for_condition")
|
||||||
val bodyLabel = codeBuilder.getNewLabel(prefix = "for_body")
|
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)
|
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)
|
codeBuilder.markWithLabel(exitLabel)
|
||||||
|
|
||||||
return null
|
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")
|
val successConditionsLabel = codeBuilder.getNewLabel(prefix = "when_condition_success")
|
||||||
var nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
|
var nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
|
||||||
|
|
||||||
@@ -836,7 +917,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
codeBuilder.markWithLabel(nextLabel)
|
codeBuilder.markWithLabel(nextLabel)
|
||||||
nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
|
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)
|
val conditionResult = addPrimitiveBinaryOperation(KtTokens.EQEQ, target, currentConditionExpression)
|
||||||
|
|
||||||
codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel)
|
codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel)
|
||||||
@@ -856,7 +938,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
codeBuilder.addUnconditionalJump(endLabel)
|
codeBuilder.addUnconditionalJump(endLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateWhenExpression(expr: KtWhenExpression, scopeDepth: Int): LLVMVariable? {
|
private fun evaluateWhenExpression(expr: KtWhenExpression,
|
||||||
|
scopeDepth: Int): LLVMVariable? {
|
||||||
codeBuilder.addComment("start when expression")
|
codeBuilder.addComment("start when expression")
|
||||||
val whenExpression = expr.subjectExpression
|
val whenExpression = expr.subjectExpression
|
||||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
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
|
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)
|
executeWhileBlock(expr.condition!!, expr.body!!, scopeDepth, checkConditionBeforeExecute = true)
|
||||||
|
|
||||||
private fun executeWhileBlock(condition: KtExpression, bodyExpression: PsiElement, scopeDepth: Int, checkConditionBeforeExecute: Boolean): LLVMVariable? {
|
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)
|
conditionResult = codeBuilder.receivePointedArgument(conditionResult, requirePointer = 0)
|
||||||
|
|
||||||
codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel)
|
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)
|
codeBuilder.markWithLabel(exitLabel)
|
||||||
|
|
||||||
return null
|
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 conditionResult = evaluateExpression(element.condition, scopeDepth)!!
|
||||||
val conditionNativeResult = codeBuilder.receivePointedArgument(conditionResult, requirePointer = 0)
|
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)
|
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 kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, ifExpression)!!.type!!
|
||||||
val expressionType = LLVMInstanceOfStandardType("type", kotlinType, LLVMVariableScope(), state).type
|
val expressionType = LLVMInstanceOfStandardType("type", kotlinType, LLVMVariableScope(), state).type
|
||||||
val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1)
|
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)
|
is LLVMReferenceType -> codeBuilder.allocStaticVar(resultVariable, asValue = true)
|
||||||
else -> codeBuilder.allocStackVar(resultVariable, asValue = true)
|
else -> codeBuilder.allocStackVar(resultVariable, asValue = true)
|
||||||
}
|
}
|
||||||
val thenLabel = codeBuilder.getNewLabel(prefix = "if")
|
val thenLabel = codeBuilder.getNewLabel(prefix = "if_then")
|
||||||
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
|
val elseLabel = codeBuilder.getNewLabel(prefix = "if_else")
|
||||||
val endLabel = codeBuilder.getNewLabel(prefix = "if")
|
val endLabel = codeBuilder.getNewLabel(prefix = "if_end")
|
||||||
|
|
||||||
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
|
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
|
||||||
codeBuilder.markWithLabel(thenLabel)
|
codeBuilder.markWithLabel(thenLabel)
|
||||||
@@ -947,23 +1037,27 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return resultVariable
|
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 thenLabel = codeBuilder.getNewLabel(prefix = "if")
|
||||||
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
|
val elseLabel = codeBuilder.getNewLabel(prefix = "if")
|
||||||
val endLabel = codeBuilder.getNewLabel(prefix = "if")
|
val endLabel = codeBuilder.getNewLabel(prefix = "if")
|
||||||
|
|
||||||
codeBuilder.addCondition(conditionResult, thenLabel, if (elseExpression != null) elseLabel else endLabel)
|
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) {
|
if (elseExpression != null) {
|
||||||
evaluateCodeBlock(elseExpression, elseLabel, endLabel, endLabel, scopeDepth + 1)
|
evaluateCodeBlock(elseExpression, startLabel = elseLabel, nextIterationLabel = endLabel, breakLabel = endLabel, scopeDepth = scopeDepth + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
codeBuilder.markWithLabel(endLabel)
|
codeBuilder.markWithLabel(endLabel)
|
||||||
return null
|
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 variable = state.bindingContext.get(BindingContext.VARIABLE, element)!!
|
||||||
val identifier = variable.fqNameSafe.convertToNativeName()
|
val identifier = variable.fqNameSafe.convertToNativeName()
|
||||||
|
|
||||||
@@ -986,7 +1080,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateReturnInstruction(element: PsiElement, scopeDepth: Int): LLVMVariable? {
|
private fun evaluateReturnInstruction(element: PsiElement,
|
||||||
|
scopeDepth: Int): LLVMVariable? {
|
||||||
val next = element.getNextSiblingIgnoringWhitespaceAndComments()
|
val next = element.getNextSiblingIgnoringWhitespaceAndComments()
|
||||||
var retVar = evaluateExpression(next, scopeDepth)
|
var retVar = evaluateExpression(next, scopeDepth)
|
||||||
val type = retVar?.type ?: LLVMVoidType()
|
val type = retVar?.type ?: LLVMVoidType()
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ package org.kotlinnative.translator
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
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
|
private var codeBuilder = state.codeBuilder
|
||||||
|
|
||||||
fun generateCode(): String {
|
fun generateCode(): String {
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ import org.kotlinnative.translator.llvm.LLVMVariable
|
|||||||
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
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() {
|
fun generate() {
|
||||||
val varInfo = state.bindingContext.get(BindingContext.VARIABLE, property)?.compileTimeInitializer ?: return
|
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 org.kotlinnative.translator.llvm.types.LLVMVoidType
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO make high level description of code generation process
|
||||||
|
* and structure of generated code.
|
||||||
|
*/
|
||||||
abstract class StructCodegen(val state: TranslationState,
|
abstract class StructCodegen(val state: TranslationState,
|
||||||
val variableManager: VariableManager,
|
val variableManager: VariableManager,
|
||||||
val classOrObject: KtClassOrObject,
|
val classOrObject: KtClassOrObject,
|
||||||
val codeBuilder: LLVMBuilder,
|
val codeBuilder: LLVMBuilder,
|
||||||
val parentCodegen: StructCodegen? = null) {
|
val parentCodegen: StructCodegen? = null) {
|
||||||
|
|
||||||
val fields = ArrayList<LLVMVariable>()
|
val fields = ArrayList<LLVMClassVariable>()
|
||||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||||
val nestedClasses = HashMap<String, ClassCodegen>()
|
val nestedClasses = HashMap<String, ClassCodegen>()
|
||||||
val enumFields = HashMap<String, LLVMVariable>()
|
val enumFields = HashMap<String, LLVMVariable>()
|
||||||
@@ -208,8 +212,8 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
private fun generateReturn(src: LLVMVariable) {
|
private fun generateReturn(src: LLVMVariable) {
|
||||||
val dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
|
val dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||||
|
|
||||||
val castedDst = codeBuilder.bitcast(dst, LLVMVariable("", LLVMCharType(), pointer = 1))
|
val castedDst = codeBuilder.bitcast(dst, LLVMCharType(), pointer = 1)
|
||||||
val castedSrc = codeBuilder.bitcast(src, LLVMVariable("", LLVMCharType(), pointer = 1))
|
val castedSrc = codeBuilder.bitcast(src, LLVMCharType(), pointer = 1)
|
||||||
|
|
||||||
codeBuilder.memcpy(castedDst, castedSrc, size)
|
codeBuilder.memcpy(castedDst, castedSrc, size)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,17 +25,14 @@ import org.kotlinnative.translator.llvm.LLVMBuilder
|
|||||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||||
import java.util.*
|
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 externalFunctions = HashMap<String, FunctionCodegen>()
|
||||||
var functions = HashMap<String, FunctionCodegen>()
|
var functions = HashMap<String, FunctionCodegen>()
|
||||||
val globalVariableCollection = HashMap<String, LLVMVariable>()
|
val globalVariableCollection = HashMap<String, LLVMVariable>()
|
||||||
@@ -45,60 +42,71 @@ class TranslationState(val environment: KotlinCoreEnvironment, val bindingContex
|
|||||||
val codeBuilder = LLVMBuilder(arm)
|
val codeBuilder = LLVMBuilder(arm)
|
||||||
val extensionFunctions = HashMap<String, HashMap<String, FunctionCodegen>>()
|
val extensionFunctions = HashMap<String, HashMap<String, FunctionCodegen>>()
|
||||||
|
|
||||||
}
|
init {
|
||||||
|
POINTER_ALIGN = if (arm) 4 else 8
|
||||||
fun parseAndAnalyze(sources: List<String>, disposer: Disposable, mainFunction: String, arm: Boolean = false): TranslationState {
|
POINTER_SIZE = if (arm) 4 else 8
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
companion object {
|
||||||
configuration.put(JVMConfigurationKeys.MODULE_NAME, JvmAbi.DEFAULT_MODULE_NAME)
|
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 configuration = CompilerConfiguration()
|
||||||
val bindingContext = analyze(environment)?.bindingContext ?: throw TranslationException("Can't initialize binding context for project")
|
val messageCollector = object : MessageCollector {
|
||||||
|
private var hasError = false
|
||||||
|
|
||||||
return TranslationState(environment, bindingContext, mainFunction, arm)
|
override fun hasErrors(): Boolean = hasError
|
||||||
}
|
|
||||||
|
|
||||||
fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? {
|
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
|
||||||
val collector = environment.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
if (severity.isError) {
|
||||||
|
System.err.println("[${severity.toString()}]${location.path} ${location.line}:${location.column} $message")
|
||||||
|
hasError = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val analyzer = AnalyzerWithCompilerReport(collector)
|
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||||
analyzer.analyzeAndReport(environment.getSourceFiles(), object : AnalyzerWithCompilerReport.Analyzer {
|
configuration.put(JVMConfigurationKeys.MODULE_NAME, JvmAbi.DEFAULT_MODULE_NAME)
|
||||||
override fun analyze(): AnalysisResult {
|
|
||||||
val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
|
||||||
val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project, environment.getModuleName())
|
|
||||||
|
|
||||||
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
|
configuration.addKotlinSourceRoots(sources)
|
||||||
moduleContext,
|
|
||||||
environment.getSourceFiles(),
|
val environment = KotlinCoreEnvironment.createForProduction(disposer, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||||
sharedTrace,
|
val bindingContext = analyze(environment)?.bindingContext ?: throw TranslationException("Can't initialize binding context for project")
|
||||||
environment.configuration.get(JVMConfigurationKeys.MODULES),
|
|
||||||
environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS),
|
return TranslationState(environment, bindingContext, mainFunction, arm)
|
||||||
JvmPackagePartProvider(environment))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reportEnvironmentErrors() {
|
private fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? {
|
||||||
val files = environment.configuration.jvmClasspathRoots
|
val collector = environment.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||||
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)
|
val analyzer = AnalyzerWithCompilerReport(collector)
|
||||||
System.err.println(runtimes.joinToString { it.toString() })
|
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 "*")
|
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 { ${
|
val code = "$target = internal global $classType { ${
|
||||||
fields.map { it.pointedType + " " + if (initializers.containsKey(it)) initializers[it] else "0" }.joinToString()
|
fields.map { it.pointedType + " " + if (initializers.containsKey(it)) initializers[it] else "0" }.joinToString()
|
||||||
} }, align ${classType.align}"
|
} }, align ${classType.align}"
|
||||||
addLLVMCodeToGlobalPlace(code)
|
addLLVMCodeToGlobalPlace(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable {
|
fun bitcast(src: LLVMVariable, llvmType: LLVMType, pointer: Int): LLVMVariable {
|
||||||
val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer)
|
val empty = getNewVariable(llvmType, pointer = pointer)
|
||||||
addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.pointedType}")
|
addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.toString() + "*".repeat(pointer)}")
|
||||||
return empty
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package org.kotlinnative.translator.llvm
|
|||||||
|
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
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()}" }})"
|
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
|
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.*
|
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(${
|
"${if (declare) "declare" else "define weak"} $returnType @$name(${
|
||||||
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
|
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
|
||||||
"${s.pointedType} ${if (s.type is LLVMReferenceType && !s.type.byRef) "byval" else ""} %${s.label}"
|
"${s.pointedType} ${if (s.type is LLVMReferenceType && !s.type.byRef) "byval" else ""} %${s.label}"
|
||||||
}?.joinToString()}) #0"
|
}?.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 typeName = type.toString().dropLastWhile { it == '?' }
|
||||||
val pointerMark = if (type.isMarkedNullable) 1 else 0
|
val pointerMark = if (type.isMarkedNullable) 1 else 0
|
||||||
return when {
|
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
|
LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type
|
||||||
|
|
||||||
fun String.addBeforeIfNotEmpty(add: String): String =
|
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.LLVMExpression
|
||||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||||
|
|
||||||
abstract class LLVMType() : Cloneable {
|
abstract class LLVMType() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun mangleFunctionArguments(names: List<LLVMSingleValue>) =
|
fun mangleFunctionArguments(names: List<LLVMSingleValue>) =
|
||||||
|
|||||||
Reference in New Issue
Block a user