translator: functions and members overload

This commit is contained in:
e5l
2016-07-22 11:52:40 +03:00
parent 4e30698756
commit 8a1d6a8e99
48 changed files with 268 additions and 207 deletions
+92 -54
View File
@@ -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)
+3 -9
View File
@@ -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