translator: functions and members overload
This commit is contained in:
@@ -23,81 +23,119 @@ store i32 %var8, i32* %var9, align 4
|
||||
store i32 %var11, i32* %var5, align 4
|
||||
ret void
|
||||
}
|
||||
define i8 @ByteArray.get(%class.ByteArray* %classvariable.this, i32 %index)
|
||||
{
|
||||
%index.addr = alloca i32, align 4
|
||||
store i32 %index, i32* %index.addr, align 4
|
||||
%var12 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1
|
||||
%var13 = load i32* %var12, align 4
|
||||
%var14 = load i32* %index.addr, align 4
|
||||
%var15 = call i8 @kotlinclib_get_byte(i32 %var13, i32 %var14)
|
||||
%var16 = alloca i8, align 1
|
||||
store i8 %var15, i8* %var16, align 1
|
||||
%var17 = load i8* %var16, align 1
|
||||
ret i8 %var17
|
||||
}
|
||||
define void @ByteArray.clone(%class.ByteArray** %instance, %class.ByteArray* %classvariable.this)
|
||||
{
|
||||
%var18 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0
|
||||
%var19 = load i32* %var18, align 4
|
||||
%var21 = call i8* @malloc(i32 8)
|
||||
%var20 = bitcast i8* %var21 to %class.ByteArray*
|
||||
call void @ByteArray(%class.ByteArray* %var20, i32 %var19)
|
||||
%var12 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0
|
||||
%var13 = load i32* %var12, align 4
|
||||
%var15 = call i8* @malloc(i32 8)
|
||||
%var14 = bitcast i8* %var15 to %class.ByteArray*
|
||||
%var17 = call i8* @malloc(i32 4)
|
||||
%var16 = bitcast i8* %var17 to %class.ByteArray**
|
||||
store %class.ByteArray* %var14, %class.ByteArray** %var16, align 4
|
||||
call void @ByteArray(%class.ByteArray* %var14, i32 %var13)
|
||||
%managed.index.1 = alloca i32, align 4
|
||||
store i32 0, i32* %managed.index.1, align 4
|
||||
br label %label.while.1
|
||||
label.while.1:
|
||||
%var22 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0
|
||||
%var23 = load i32* %managed.index.1, align 4
|
||||
%var24 = load i32* %var22, align 4
|
||||
%var25 = icmp slt i32 %var23, %var24
|
||||
br i1 %var25, label %label.while.2, label %label.while.3
|
||||
%var18 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 0
|
||||
%var19 = load i32* %managed.index.1, align 4
|
||||
%var20 = load i32* %var18, align 4
|
||||
%var21 = icmp slt i32 %var19, %var20
|
||||
br i1 %var21, label %label.while.2, label %label.while.3
|
||||
label.while.2:
|
||||
%var22 = load i32* %managed.index.1, align 4
|
||||
%var23 = call i8 @ByteArray.get_Int(%class.ByteArray* %classvariable.this, i32 %var22)
|
||||
%var24 = alloca i8, align 1
|
||||
store i8 %var23, i8* %var24, align 1
|
||||
%var25 = load %class.ByteArray** %var16, align 4
|
||||
%var26 = load i32* %managed.index.1, align 4
|
||||
%var27 = call i8 @ByteArray.get(%class.ByteArray* %classvariable.this, i32 %var26)
|
||||
%var28 = alloca i8, align 1
|
||||
store i8 %var27, i8* %var28, align 1
|
||||
%var29 = load i32* %managed.index.1, align 4
|
||||
%var30 = load i8* %var28, align 1
|
||||
call void @ByteArray.set(%class.ByteArray* %var20, i32 %var29, i8 %var30)
|
||||
%var31 = load i32* %managed.index.1, align 4
|
||||
%var32 = add nsw i32 %var31, 1
|
||||
%var33 = load i32* %managed.index.1, align 4
|
||||
store i32 %var32, i32* %managed.index.1, align 4
|
||||
%var27 = load i8* %var24, align 1
|
||||
call void @ByteArray.set_Int_Byte(%class.ByteArray* %var25, i32 %var26, i8 %var27)
|
||||
%var28 = load i32* %managed.index.1, align 4
|
||||
%var29 = add nsw i32 %var28, 1
|
||||
%var30 = load i32* %managed.index.1, align 4
|
||||
store i32 %var29, i32* %managed.index.1, align 4
|
||||
br label %label.while.1
|
||||
label.while.3:
|
||||
store %class.ByteArray* %var20, %class.ByteArray** %instance, align 4
|
||||
%var31 = load %class.ByteArray** %var16, align 4
|
||||
store %class.ByteArray* %var31, %class.ByteArray** %instance, align 4
|
||||
ret void
|
||||
}
|
||||
define void @ByteArray.set(%class.ByteArray* %classvariable.this, i32 %index, i8 %value)
|
||||
define i8 @ByteArray.get_Int(%class.ByteArray* %classvariable.this, i32 %index)
|
||||
{
|
||||
%index.addr = alloca i32, align 4
|
||||
store i32 %index, i32* %index.addr, align 4
|
||||
%var32 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1
|
||||
%var33 = load i32* %var32, align 4
|
||||
%var34 = load i32* %index.addr, align 4
|
||||
%var35 = call i8 @kotlinclib_get_byte(i32 %var33, i32 %var34)
|
||||
%var36 = alloca i8, align 1
|
||||
store i8 %var35, i8* %var36, align 1
|
||||
%var37 = load i8* %var36, align 1
|
||||
ret i8 %var37
|
||||
}
|
||||
define void @ByteArray.set_Int_Byte(%class.ByteArray* %classvariable.this, i32 %index, i8 %value)
|
||||
{
|
||||
%index.addr = alloca i32, align 4
|
||||
store i32 %index, i32* %index.addr, align 4
|
||||
%value.addr = alloca i8, align 1
|
||||
store i8 %value, i8* %value.addr, align 1
|
||||
%var34 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1
|
||||
%var35 = load i32* %var34, align 4
|
||||
%var36 = load i32* %index.addr, align 4
|
||||
%var37 = load i8* %value.addr, align 1
|
||||
call void @kotlinclib_set_byte(i32 %var35, i32 %var36, i8 %var37)
|
||||
%var38 = getelementptr inbounds %class.ByteArray* %classvariable.this, i32 0, i32 1
|
||||
%var39 = load i32* %var38, align 4
|
||||
%var40 = load i32* %index.addr, align 4
|
||||
%var41 = load i8* %value.addr, align 1
|
||||
call void @kotlinclib_set_byte(i32 %var39, i32 %var40, i8 %var41)
|
||||
ret void
|
||||
}
|
||||
declare i8 @kotlinclib_get_byte(i32 %src, i32 %index)
|
||||
define i8 @bytearray_1(i8 %x)
|
||||
%class.WithFields = type { i32, i32 }
|
||||
define void @WithFields(%class.WithFields* %classvariable.this, i32 %i)
|
||||
{
|
||||
%x.addr = alloca i8, align 1
|
||||
store i8 %x, i8* %x.addr, align 1
|
||||
%var39 = call i8* @malloc(i32 8)
|
||||
%var38 = bitcast i8* %var39 to %class.ByteArray*
|
||||
call void @ByteArray(%class.ByteArray* %var38, i32 10)
|
||||
%var40 = load i8* %x.addr, align 1
|
||||
call void @ByteArray.set(%class.ByteArray* %var38, i32 1, i8 %var40)
|
||||
%var41 = call i8 @ByteArray.get(%class.ByteArray* %var38, i32 1)
|
||||
%var42 = alloca i8, align 1
|
||||
store i8 %var41, i8* %var42, align 1
|
||||
%var43 = load i8* %var42, align 1
|
||||
ret i8 %var43
|
||||
%classvariable.this.addr = alloca %class.WithFields, align 4
|
||||
%i.addr = alloca i32, align 4
|
||||
store i32 %i, i32* %i.addr, align 4
|
||||
%var42 = load i32* %i.addr, align 4
|
||||
%var43 = getelementptr inbounds %class.WithFields* %classvariable.this.addr, i32 0, i32 0
|
||||
store i32 %var42, i32* %var43, align 4
|
||||
%var44 = bitcast %class.WithFields* %classvariable.this to i8*
|
||||
%var45 = bitcast %class.WithFields* %classvariable.this.addr to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var44, i8* %var45, i64 8, i32 4, i1 false)
|
||||
%var46 = getelementptr inbounds %class.WithFields* %classvariable.this, i32 0, i32 1
|
||||
%var47 = getelementptr inbounds %class.WithFields* %classvariable.this, i32 0, i32 0
|
||||
%var48 = load i32* %var46, align 4
|
||||
%var49 = load i32* %var47, align 4
|
||||
store i32 %var49, i32* %var46, align 4
|
||||
ret void
|
||||
}
|
||||
define i32 @test_field_assignment_Int(i32 %i)
|
||||
{
|
||||
%i.addr = alloca i32, align 4
|
||||
store i32 %i, i32* %i.addr, align 4
|
||||
%var50 = load i32* %i.addr, align 4
|
||||
%var52 = call i8* @malloc(i32 8)
|
||||
%var51 = bitcast i8* %var52 to %class.WithFields*
|
||||
%var54 = call i8* @malloc(i32 4)
|
||||
%var53 = bitcast i8* %var54 to %class.WithFields**
|
||||
store %class.WithFields* %var51, %class.WithFields** %var53, align 4
|
||||
call void @WithFields(%class.WithFields* %var51, i32 %var50)
|
||||
%var55 = load %class.WithFields** %var53, align 4
|
||||
%var56 = getelementptr inbounds %class.WithFields* %var55, i32 0, i32 1
|
||||
%var57 = load i32* %var56, align 4
|
||||
ret i32 %var57
|
||||
}
|
||||
define i32 @test_simple_field()
|
||||
{
|
||||
%var59 = call i8* @malloc(i32 8)
|
||||
%var58 = bitcast i8* %var59 to %class.WithFields*
|
||||
%var61 = call i8* @malloc(i32 4)
|
||||
%var60 = bitcast i8* %var61 to %class.WithFields**
|
||||
store %class.WithFields* %var58, %class.WithFields** %var60, align 4
|
||||
call void @WithFields(%class.WithFields* %var58, i32 1)
|
||||
%var62 = load %class.WithFields** %var60, align 4
|
||||
%var63 = getelementptr inbounds %class.WithFields* %var62, i32 0, i32 1
|
||||
%var64 = load i32* %var63, align 4
|
||||
ret i32 %var64
|
||||
}
|
||||
declare i8 @kotlinclib_get_byte(i32 %src, i32 %index)
|
||||
declare i32 @malloc_array(i32 %size)
|
||||
declare void @kotlinclib_set_byte(i32 %src, i32 %index, i8 %value)
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import org.kotlinnative.translator.FileTranslator
|
||||
import org.kotlinnative.translator.ProjectTranslator
|
||||
import org.kotlinnative.translator.parseAndAnalyze
|
||||
import java.io.File
|
||||
@@ -15,8 +14,8 @@ fun main(args: Array<String>) {
|
||||
val analyzedFiles = ArrayList<String>()
|
||||
|
||||
val kotlib = File("build/resources/main/kotlib/kotlin").listFiles()
|
||||
for (resourse in kotlib) {
|
||||
analyzedFiles.add(resourse.absolutePath)
|
||||
for (resource in kotlib) {
|
||||
analyzedFiles.add(resource.absolutePath)
|
||||
}
|
||||
|
||||
analyzedFiles.addAll(args.toList())
|
||||
@@ -30,11 +29,6 @@ fun main(args: Array<String>) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
files.forEach {
|
||||
FileTranslator(state, it).addDeclarations()
|
||||
}
|
||||
|
||||
println(ProjectTranslator(state).generateCode())
|
||||
println(ProjectTranslator(files, state).generateCode())
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
is KtIfExpression -> evaluateIfOperator(expr.firstChild as LeafPsiElement, scopeDepth + 1, expr)
|
||||
is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr)
|
||||
is KtReturnExpression -> evaluateReturnInstruction(expr.firstChild, scopeDepth)
|
||||
is KtThisExpression -> evaluateThisExpression(expr, scopeDepth)
|
||||
is KtThisExpression -> evaluateThisExpression()
|
||||
is PsiWhiteSpace -> null
|
||||
is PsiElement -> evaluatePsiElement(expr, scopeDepth)
|
||||
null -> null
|
||||
@@ -76,7 +76,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateThisExpression(expr: KtThisExpression, scopeDepth: Int): LLVMSingleValue? {
|
||||
private fun evaluateThisExpression(): LLVMSingleValue? {
|
||||
return variableManager.getLLVMvalue("this")
|
||||
}
|
||||
|
||||
@@ -92,7 +92,8 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
|
||||
private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? {
|
||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||
return LLVMInstanceOfStandardType(expr.text.substring(2), kotlinType, LLVMVariableScope())
|
||||
val result = LLVMInstanceOfStandardType(expr.text.substring(2), kotlinType, LLVMVariableScope())
|
||||
return LLVMVariable("${result.label}${(result.type as LLVMFunctionType).mangleArgs()}", result.type, result.kotlinName, result.scope, result.pointer)
|
||||
}
|
||||
|
||||
private fun evaluateDotExpression(expr: KtDotQualifiedExpression, scopeDepth: Int): LLVMSingleValue? {
|
||||
@@ -118,18 +119,19 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
|
||||
private fun evaluateExtensionExpression(receiver: KtExpression, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
|
||||
val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)
|
||||
val standartType = LLVMMapStandardType(receiverType!!.type!!)
|
||||
val standardType = LLVMMapStandardType(receiverType!!.type!!)
|
||||
val function = selector.firstChild.firstChild.text
|
||||
val names = parseArgList(selector, scopeDepth)
|
||||
val extensionCodegen = state.extensionFunctions[standartType.toString()]!![function]!!
|
||||
val type = if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""
|
||||
val extensionCodegen = state.extensionFunctions[standardType.toString()]!!["$function$type"]!!
|
||||
val receiverExpression = evaluateExpression(receiver, scopeDepth + 1)!!
|
||||
|
||||
val typeThisArgument = when (standartType) {
|
||||
is LLVMReferenceType -> LLVMVariable("type", standartType, pointer = 1)
|
||||
else -> LLVMVariable("type", standartType, pointer = 0)
|
||||
val typeThisArgument = when (standardType) {
|
||||
is LLVMReferenceType -> LLVMVariable("type", standardType, pointer = 1)
|
||||
else -> LLVMVariable("type", standardType, pointer = 0)
|
||||
}
|
||||
|
||||
val args = mutableListOf<LLVMSingleValue>(loadArgumentIfRequired(receiverExpression, typeThisArgument))
|
||||
val args = mutableListOf(loadArgumentIfRequired(receiverExpression, typeThisArgument))
|
||||
|
||||
args.addAll(loadArgsIfRequired(names, extensionCodegen.args))
|
||||
|
||||
@@ -143,7 +145,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
else -> throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? {
|
||||
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: ClassCodegen? = null): LLVMSingleValue? {
|
||||
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
|
||||
val field = classScope!!.companionFieldsIndex[fieldName]
|
||||
|
||||
@@ -167,13 +169,14 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
return result
|
||||
}
|
||||
|
||||
val names = parseArgList(call as KtCallExpression, scopeDepth)
|
||||
val typePath = type.location.joinToString(".")
|
||||
val methodName = "${if (typePath.length > 0) "$typePath." else ""}${clazz.structName}.${selectorName.substringBefore('(')}"
|
||||
val types = if (names.size > 0) "_${names.joinToString(separator = "_", transform ={ it.type!!.mangle() })}" else ""
|
||||
val methodName = "${if (typePath.length > 0) "$typePath." else ""}${clazz.structName}.${selectorName.substringBefore('(')}$types"
|
||||
|
||||
val method = clazz.methods[methodName]!!
|
||||
val returnType = clazz.methods[methodName]!!.returnType!!.type
|
||||
|
||||
val names = parseArgList(call as KtCallExpression, scopeDepth)
|
||||
val loadedArgs = loadArgsIfRequired(names, method.args)
|
||||
val callArgs = mutableListOf<LLVMSingleValue>(receiver)
|
||||
callArgs.addAll(loadedArgs)
|
||||
@@ -208,31 +211,35 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
|
||||
private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when (expr) {
|
||||
is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
|
||||
else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluateNameReferenceExpression(expr, scopeDepth + 1, classScope)
|
||||
else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluateNameReferenceExpression(expr, classScope)
|
||||
else variableManager.getLLVMvalue(expr.firstChild.text)
|
||||
}
|
||||
|
||||
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? {
|
||||
val function = expr.firstChild.firstChild.text
|
||||
val names = parseArgList(expr, scopeDepth)
|
||||
val name = expr.firstChild.firstChild.text
|
||||
val external = state.externalFunctions.containsKey(name)
|
||||
|
||||
if (state.functions.containsKey(function)) {
|
||||
val descriptor = state.functions[function] ?: return null
|
||||
val function = "$name${if (names.size > 0 && !external) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""}"
|
||||
|
||||
if (state.functions.containsKey(function) || state.externalFunctions.containsKey(function)) {
|
||||
val descriptor = state.functions[function] ?: state.externalFunctions[function] ?: return null
|
||||
val args = loadArgsIfRequired(names, descriptor.args)
|
||||
return evaluateFunctionCallExpression(LLVMVariable(function, descriptor.returnType!!.type, scope = LLVMVariableScope()), args)
|
||||
}
|
||||
|
||||
if (state.classes.containsKey(function)) {
|
||||
val descriptor = state.classes[function] ?: return null
|
||||
|
||||
if (state.classes.containsKey(name)) {
|
||||
val descriptor = state.classes[name] ?: return null
|
||||
val args = loadArgsIfRequired(names, descriptor.constructorFields)
|
||||
return evaluateConstructorCallExpression(LLVMVariable(function, descriptor.type, scope = LLVMVariableScope()), args)
|
||||
return evaluateConstructorCallExpression(LLVMVariable(name, descriptor.type, scope = LLVMVariableScope()), args)
|
||||
}
|
||||
|
||||
val localFunction = variableManager.getLLVMvalue(function)
|
||||
val localFunction = variableManager.getLLVMvalue(name)
|
||||
if (localFunction != null) {
|
||||
val type = localFunction.type as LLVMFunctionType
|
||||
val args = loadArgsIfRequired(names, type.arguments)
|
||||
return evaluateFunctionCallExpression(LLVMVariable(function, type.returnType.type, scope = LLVMRegisterScope()), args)
|
||||
return evaluateFunctionCallExpression(LLVMVariable(name, type.returnType.type, scope = LLVMRegisterScope()), args)
|
||||
}
|
||||
|
||||
if (state.classes.containsKey(classScope?.structName)) {
|
||||
@@ -358,10 +365,10 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
val left = evaluateExpression(expr.firstChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||
val right = evaluateExpression(expr.lastChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||
|
||||
return executeBinaryExpression(operator, expr.operationReference, left, right, scopeDepth)
|
||||
return executeBinaryExpression(operator, expr.operationReference, left, right)
|
||||
}
|
||||
|
||||
private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue, scopeDepth: Int)
|
||||
private fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue)
|
||||
= addPrimitiveBinaryOperation(operator, referenceName, left, right)
|
||||
|
||||
private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable {
|
||||
@@ -474,7 +481,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
|
||||
|
||||
val currentConditionExpression = evaluateExpression(condition.firstChild, scopeDepth + 1)!!
|
||||
val conditionResult = executeBinaryExpression(KtTokens.EQEQ, null, target, currentConditionExpression, scopeDepth)
|
||||
val conditionResult = executeBinaryExpression(KtTokens.EQEQ, null, target, currentConditionExpression)
|
||||
|
||||
codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel)
|
||||
}
|
||||
|
||||
@@ -86,9 +86,9 @@ class ClassCodegen(override val state: TranslationState,
|
||||
val companionObjectName = structName + "." + companionObject.name
|
||||
property.generate()
|
||||
|
||||
for (method in property.methods) {
|
||||
val methodName = method.key.removePrefix(companionObjectName + ".")
|
||||
companionMethods.put(structName + "." + methodName, method.value)
|
||||
for ((key, value) in property.methods) {
|
||||
val methodName = key.removePrefix(companionObjectName + ".")
|
||||
companionMethods.put(structName + "." + methodName, value)
|
||||
}
|
||||
companionFields.addAll(property.fields)
|
||||
for (field in property.fields) {
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.kotlinnative.translator.debug.printFile
|
||||
|
||||
class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||
|
||||
private var codeBuilder = state.codeBuilder
|
||||
|
||||
fun addDeclarations() {
|
||||
for (declaration in file.declarations) {
|
||||
when (declaration) {
|
||||
is KtNamedFunction -> {
|
||||
val function = FunctionCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder)
|
||||
state.functions.put(function.name, function)
|
||||
}
|
||||
is KtClass -> {
|
||||
val codegen = ClassCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder)
|
||||
state.classes.put(declaration.name!!, codegen)
|
||||
}
|
||||
is KtProperty -> {
|
||||
val property = PropertyCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder)
|
||||
state.properties.put(declaration.name!!, property)
|
||||
}
|
||||
is KtObjectDeclaration -> {
|
||||
val property = ObjectCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder)
|
||||
state.objects.put(declaration.name!!, property)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,13 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
val parentCodegen: StructCodegen? = null) :
|
||||
BlockCodegen(state, variableManager, codeBuilder) {
|
||||
|
||||
var name = function.fqName.toString()
|
||||
var name: String
|
||||
var args = LinkedList<LLVMVariable>()
|
||||
val isExtensionDeclaration = function.isExtensionDeclaration()
|
||||
var functionNamePrefix = ""
|
||||
val fullName: String
|
||||
get() = functionNamePrefix + name
|
||||
val external: Boolean
|
||||
|
||||
init {
|
||||
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
|
||||
@@ -33,6 +34,9 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
})
|
||||
|
||||
returnType = LLVMInstanceOfStandardType("instance", descriptor.returnType!!)
|
||||
external = isExternal()
|
||||
name = "${function.fqName}${if (args.size > 0 && !external) "_${args.joinToString(separator = "_", transform = { it.type.mangle() })}" else ""}"
|
||||
|
||||
val retType = returnType!!.type
|
||||
when (retType) {
|
||||
is LLVMReferenceType -> {
|
||||
@@ -50,7 +54,9 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
}
|
||||
|
||||
fun generate(this_type: LLVMVariable? = null) {
|
||||
if (generateDeclaration(this_type)) {
|
||||
generateDeclaration(this_type)
|
||||
|
||||
if (external) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -64,9 +70,7 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
codeBuilder.addEndExpression()
|
||||
}
|
||||
|
||||
private fun generateDeclaration(this_type: LLVMVariable? = null): Boolean {
|
||||
var external = false
|
||||
|
||||
private fun generateDeclaration(this_type: LLVMVariable? = null) {
|
||||
args.forEach {
|
||||
val type = it.type
|
||||
if (type is LLVMReferenceType && state.classes.containsKey(type.type)) {
|
||||
@@ -74,16 +78,6 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
}
|
||||
}
|
||||
|
||||
var keyword = function.firstChild
|
||||
while (keyword != null) {
|
||||
if (keyword.text == "external") {
|
||||
external = true
|
||||
break
|
||||
}
|
||||
|
||||
keyword = keyword.getNextSiblingIgnoringWhitespaceAndComments()
|
||||
}
|
||||
|
||||
var actualReturnType: LLVMType = returnType!!.type
|
||||
val actualArgs = ArrayList<LLVMVariable>()
|
||||
|
||||
@@ -114,7 +108,6 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
actualArgs.addAll(args)
|
||||
|
||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName, actualArgs, actualReturnType, external, state.arm))
|
||||
return external
|
||||
}
|
||||
|
||||
private fun generateLoadArguments() {
|
||||
@@ -133,4 +126,17 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun isExternal(): Boolean {
|
||||
var keyword = function.firstChild
|
||||
while (keyword != null) {
|
||||
if (keyword.text == "external") {
|
||||
return true
|
||||
}
|
||||
|
||||
keyword = keyword.getNextSiblingIgnoringWhitespaceAndComments()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,52 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
class ProjectTranslator(val state: TranslationState) {
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class ProjectTranslator(val files: List<KtFile>, val state: TranslationState) {
|
||||
private var codeBuilder = state.codeBuilder
|
||||
|
||||
fun generateCode(): String {
|
||||
codeBuilder.clean()
|
||||
files.map { addDeclarations(it) }
|
||||
generateProjectBody()
|
||||
return codeBuilder.toString()
|
||||
}
|
||||
|
||||
fun addDeclarations(file: KtFile) {
|
||||
for (declaration in file.declarations) {
|
||||
when (declaration) {
|
||||
is KtNamedFunction -> {
|
||||
val function = FunctionCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder)
|
||||
if (function.external) {
|
||||
state.externalFunctions.put(function.name, function)
|
||||
} else {
|
||||
state.functions.put(function.name, function)
|
||||
}
|
||||
}
|
||||
is KtClass -> {
|
||||
val codegen = ClassCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder)
|
||||
state.classes.put(declaration.name!!, codegen)
|
||||
}
|
||||
is KtProperty -> {
|
||||
val property = PropertyCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder)
|
||||
state.properties.put(declaration.name!!, property)
|
||||
}
|
||||
is KtObjectDeclaration -> {
|
||||
val property = ObjectCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder)
|
||||
state.objects.put(declaration.name!!, property)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateProjectBody() {
|
||||
for (property in state.properties.values) {
|
||||
property.generate()
|
||||
}
|
||||
|
||||
for (objectCodegen in state.objects.values) {
|
||||
objectCodegen.generate()
|
||||
}
|
||||
|
||||
for (clazz in state.classes.values) {
|
||||
clazz.generate()
|
||||
}
|
||||
|
||||
for (function in state.functions.values.filter { it.isExtensionDeclaration }) {
|
||||
function.generate()
|
||||
}
|
||||
|
||||
for (function in state.functions.values.filter { !it.isExtensionDeclaration }) {
|
||||
function.generate()
|
||||
with (state) {
|
||||
properties.values.map { it.generate() }
|
||||
objects.values.map { it.generate() }
|
||||
classes.values.map { it.generate() }
|
||||
functions.values.filter { it.isExtensionDeclaration }.map { it.generate() }
|
||||
functions.values.filter { !it.isExtensionDeclaration }.map { it.generate() }
|
||||
externalFunctions.values.map { it.generate() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.*
|
||||
|
||||
class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val arm: Boolean) {
|
||||
|
||||
var externalFunctions = HashMap<String, FunctionCodegen>()
|
||||
var functions = HashMap<String, FunctionCodegen>()
|
||||
val globalVariableCollection = HashMap<String, LLVMVariable>()
|
||||
var classes = HashMap<String, ClassCodegen>()
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ class LLVMBooleanType() : LLVMType() {
|
||||
else -> throw IllegalArgumentException("Failed to parse boolean type")
|
||||
}
|
||||
|
||||
override fun mangle() = "Boolean"
|
||||
|
||||
override val align = 4
|
||||
override var size: Int = 1
|
||||
override val defaultValue = "0"
|
||||
|
||||
@@ -22,6 +22,8 @@ class LLVMByteType() : LLVMType() {
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i8 $firstOp, $secondOp")
|
||||
|
||||
override fun mangle() = "Byte"
|
||||
|
||||
override val align = 1
|
||||
override var size: Int = 1
|
||||
override fun toString(): String = "i8"
|
||||
|
||||
@@ -22,6 +22,8 @@ class LLVMCharType() : LLVMType() {
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i8 $firstOp, $secondOp")
|
||||
|
||||
override fun mangle() = "Char"
|
||||
|
||||
override val align = 1
|
||||
override var size: Int = 1
|
||||
override fun toString(): String = "i8"
|
||||
|
||||
@@ -18,6 +18,8 @@ class LLVMDoubleType() : LLVMType() {
|
||||
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
|
||||
LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp")
|
||||
|
||||
override fun mangle() = "Double"
|
||||
|
||||
override val align = 8
|
||||
override var size: Int = 8
|
||||
override fun toString() = "double"
|
||||
|
||||
@@ -7,5 +7,7 @@ class LLVMEnumItemType() : LLVMType() {
|
||||
override var size: Int = 4
|
||||
override val defaultValue = "0"
|
||||
|
||||
override fun mangle() = "Enum"
|
||||
|
||||
override fun toString() = "i32"
|
||||
}
|
||||
@@ -20,6 +20,8 @@ class LLVMFloatType() : LLVMType() {
|
||||
|
||||
override val align = 4
|
||||
override var size: Int = 4
|
||||
|
||||
override fun mangle() = "Float"
|
||||
override fun toString() = "float"
|
||||
override val defaultValue = "0.0"
|
||||
override fun isPrimitive() = true
|
||||
|
||||
@@ -19,6 +19,13 @@ class LLVMFunctionType(type: KotlinType) : LLVMType() {
|
||||
arguments = types.dropLast(1)
|
||||
}
|
||||
|
||||
override fun mangle() =
|
||||
"F.${arguments.joinToString(separator = "_", transform = { it.type.mangle() })}.EF"
|
||||
|
||||
fun mangleArgs(): String =
|
||||
if (arguments.size > 0) "_${arguments.joinToString(separator = "_", transform = { it.type.mangle() })}" else ""
|
||||
|
||||
override fun toString(): String =
|
||||
"${returnType.type} (${arguments.map { it.getType() }.joinToString()})"
|
||||
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ class LLVMIntType() : LLVMType() {
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i32 $firstOp, $secondOp")
|
||||
|
||||
override fun mangle() = "Int"
|
||||
|
||||
override val align = 4
|
||||
override var size: Int = 4
|
||||
override val defaultValue = "0"
|
||||
|
||||
@@ -59,6 +59,7 @@ class LLVMLongType() : LLVMType() {
|
||||
override var size: Int = 8
|
||||
override val defaultValue = "0"
|
||||
|
||||
override fun mangle() = "Long"
|
||||
override fun toString() = "i64"
|
||||
override fun isPrimitive() = true
|
||||
}
|
||||
@@ -4,4 +4,6 @@ class LLVMNullType() : LLVMType() {
|
||||
override val align: Int = 0
|
||||
override var size: Int = 0
|
||||
override val defaultValue: String = "0"
|
||||
|
||||
override fun mangle() = ""
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ class LLVMReferenceType(val type: String, var prefix: String = "", override val
|
||||
|
||||
val location = ArrayList<String>()
|
||||
|
||||
override fun mangle() = "Ref_$type"
|
||||
|
||||
fun addParam(param: String) {
|
||||
params.add(param)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ class LLVMShortType() : LLVMType() {
|
||||
override val align = 2
|
||||
override val defaultValue = "0"
|
||||
|
||||
override fun mangle() = "Short"
|
||||
override fun toString(): String = "i16"
|
||||
override fun isPrimitive() = true
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ class LLVMStringType(override val length: Int) : LLVMArray, LLVMType() {
|
||||
override val align = 8
|
||||
override val defaultValue = ""
|
||||
|
||||
override fun mangle() = "String"
|
||||
|
||||
override fun basicType() = LLVMCharType()
|
||||
override fun toString(): String = "i8*"
|
||||
override fun fullType() = "[${length + 1} x i8]"
|
||||
|
||||
@@ -25,6 +25,8 @@ abstract class LLVMType() : Cloneable {
|
||||
|
||||
fun makeClone() = clone()
|
||||
|
||||
abstract fun mangle(): String
|
||||
|
||||
abstract val align: Int
|
||||
abstract var size: Int
|
||||
abstract val defaultValue: String
|
||||
|
||||
@@ -6,5 +6,6 @@ class LLVMVoidType() : LLVMType() {
|
||||
override var size: Int = 0
|
||||
override val defaultValue = ""
|
||||
|
||||
override fun mangle() = ""
|
||||
override fun toString(): String = "void"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
bytearray_1(123) == 123
|
||||
bytearray_1_Byte(123) == 123
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
compact_test(1) == 2
|
||||
compact_test(3) == 4
|
||||
external_test(3) == 2
|
||||
external_test(4) == 3
|
||||
mixed_test(1) == 4
|
||||
mixed_test(9) == 12
|
||||
compact_test_Int(1) == 2
|
||||
compact_test_Int(3) == 4
|
||||
external_test_Int(3) == 2
|
||||
external_test_Int(4) == 3
|
||||
mixed_test_Int(1) == 4
|
||||
mixed_test_Int(9) == 12
|
||||
|
||||
@@ -1 +1 @@
|
||||
class_init_section_1(523) == 12868
|
||||
class_init_section_1_Int(523) == 12868
|
||||
|
||||
@@ -1 +1 @@
|
||||
class_methods_1(55) == 60
|
||||
class_methods_1_Int(55) == 60
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
test_simple_field() == 1
|
||||
test_field_assignment(10) == 10
|
||||
test_field_assignment_Int(10) == 10
|
||||
|
||||
@@ -1 +1 @@
|
||||
companion_object_2_test(5) == 244
|
||||
companion_object_2_test_Int(5) == 244
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
do_while_test_1(5) == 6
|
||||
do_while_test_1(57) == 58
|
||||
do_while_test_1_Int(5) == 6
|
||||
do_while_test_1_Int(57) == 58
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
elvis_test_1(0) == 0
|
||||
elvis_test_1(2) == 1
|
||||
elvis_test_1_Int(0) == 0
|
||||
elvis_test_1_Int(2) == 1
|
||||
|
||||
@@ -1 +1 @@
|
||||
function_extensions_1(118) == 291
|
||||
function_extensions_1_Int(118) == 291
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if_test_1(11) == 10
|
||||
if_test_1(0) == 0
|
||||
if_test_null(0) == 1
|
||||
if_test_null_2(0) == 0
|
||||
if_test_1_Int(11) == 10
|
||||
if_test_1_Int(0) == 0
|
||||
if_test_null_Int(0) == 1
|
||||
if_test_null_2_Int(0) == 0
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
if_without_else_2(5) == 1256
|
||||
if_without_else_2(55) == 1320
|
||||
if_without_else_2_Int(5) == 1256
|
||||
if_without_else_2_Int(55) == 1320
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
if_expression_1(56) == 2323
|
||||
if_expression_1(-58) == 678934
|
||||
if_expression_1_Int(56) == 2323
|
||||
if_expression_1_Int(-58) == 678934
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
nested_test_1(1) == 1
|
||||
nested_test_2(1) == 5
|
||||
nested_test_1_Int(1) == 1
|
||||
nested_test_2_Int(1) == 5
|
||||
@@ -1,2 +1,2 @@
|
||||
nullable_test(1) == 1
|
||||
nullable_test_2(4) == 5
|
||||
nullable_test_Int(1) == 1
|
||||
nullable_test_2_Int(4) == 5
|
||||
|
||||
@@ -1 +1 @@
|
||||
singleton_test(5) == 40
|
||||
singleton_test_Int(5) == 40
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
testCastToInt(32) == 0
|
||||
testCastToInt(34) == 1
|
||||
testCastToByte(32) == 0
|
||||
testCastToByte(34) == 1
|
||||
testCastToInt_Int(32) == 0
|
||||
testCastToInt_Int(34) == 1
|
||||
testCastToByte_Byte(32) == 0
|
||||
testCastToByte_Byte(34) == 1
|
||||
|
||||
@@ -1 +1 @@
|
||||
reassigment_0(5) == 6
|
||||
reassigment_0_Int(5) == 6
|
||||
|
||||
@@ -1 +1 @@
|
||||
reassigment_1(5) == 8
|
||||
reassigment_1_Int(5) == 8
|
||||
|
||||
@@ -1 +1 @@
|
||||
return_test_1(101) == 101
|
||||
return_test_1_Int(101) == 101
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
change(0) == 1
|
||||
change(1) == 2
|
||||
testGen(10) == 10
|
||||
change_Int(0) == 1
|
||||
change_Int(1) == 2
|
||||
testGen_Int(10) == 10
|
||||
|
||||
@@ -1 +1 @@
|
||||
simply_class_1(6789) == 6794
|
||||
simply_class_1_Int(6789) == 6794
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
when_expression_1(21234) == 20
|
||||
when_expression_1(55555) == 50
|
||||
when_expression_1(345626) == 100
|
||||
when_expression_1(756754) == 100
|
||||
when_expression_1_Int(21234) == 20
|
||||
when_expression_1_Int(55555) == 50
|
||||
when_expression_1_Int(345626) == 100
|
||||
when_expression_1_Int(756754) == 100
|
||||
|
||||
@@ -1 +1 @@
|
||||
while_test_1(6) == 10
|
||||
while_test_1_Int(6) == 10
|
||||
|
||||
@@ -1 +1 @@
|
||||
while_test_2(77) == 78
|
||||
while_test_2_Int(77) == 78
|
||||
|
||||
Reference in New Issue
Block a user