diff --git a/car_llvmkot/kotlib/kotlin_main.ll b/car_llvmkot/kotlib/kotlin_main.ll index 6cf6b53a217..1b4f5a24a08 100644 --- a/car_llvmkot/kotlib/kotlin_main.ll +++ b/car_llvmkot/kotlib/kotlin_main.ll @@ -1,40 +1,39 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) declare i8* @malloc(i32) -%class.MyAwesomeClass = type { i32 } -define void @MyAwesomeClass(%class.MyAwesomeClass* %classvariable.this, i32 %i) +%class.Outer = type { } +define void @Outer(%class.Outer* %classvariable.this) { -%classvariable.this.addr = alloca %class.MyAwesomeClass, align 4 -%i.addr = alloca i32, align 4 -store i32 %i, i32* %i.addr, align 4 -%var1 = load i32* %i.addr, align 4 -%var2 = getelementptr inbounds %class.MyAwesomeClass* %classvariable.this.addr, i32 0, i32 0 -store i32 %var1, i32* %var2, align 4 -%var3 = bitcast %class.MyAwesomeClass* %classvariable.this to i8* -%var4 = bitcast %class.MyAwesomeClass* %classvariable.this.addr to i8* -call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var3, i8* %var4, i64 4, i32 4, i1 false) +%classvariable.this.addr = alloca %class.Outer, align 4 +%var1 = bitcast %class.Outer* %classvariable.this to i8* +%var2 = bitcast %class.Outer* %classvariable.this.addr to i8* +call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var1, i8* %var2, i64 0, i32 4, i1 false) ret void } -define i32 @nullable_test(i32 %i) +define void @Outer.main(%class.Outer* %instance, %class.Outer* %classvariable.this) { -%i.addr = alloca i32, align 4 -store i32 %i, i32* %i.addr, align 4 -%var6 = call i8* @malloc(i32 4) -%var5 = bitcast i8* %var6 to %class.MyAwesomeClass* -call void @MyAwesomeClass(%class.MyAwesomeClass* %var5, i32 1) -%var8 = call i8* @malloc(i32 4) -%var7 = bitcast i8* %var8 to %class.MyAwesomeClass* -call void @MyAwesomeClass(%class.MyAwesomeClass* %var7, i32 2) -%var9 = load %class.MyAwesomeClass* %var5, align 4 -%var10 = load %class.MyAwesomeClass* %var7, align 4 -%var11 = getelementptr inbounds %class.MyAwesomeClass* %var7, i32 0, i32 0 -%var12 = load i32* %var11, align 4 -ret i32 %var12 +%var4 = call i8* @malloc(i32 0) +%var3 = bitcast i8* %var4 to %class.Outer* +call void @Outer(%class.Outer* %var3) +%var5 = bitcast %class.Outer* %var3 to i8* +%var6 = bitcast %class.Outer* %instance to i8* +call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var6, i8* %var5, i64 0, i32 4, i1 false) +ret void } -define void @main() +%class.Outer_Nested = type { i32 } +define void @Outer_Nested(%class_Outer.Nested* %classvariable.this) +{ +%classvariable.this.addr = alloca %class_Outer.Nested, align 4 +%var7 = bitcast %class_Outer.Nested* %classvariable.this to i8* +%var8 = bitcast %class_Outer.Nested* %classvariable.this.addr to i8* +call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var7, i8* %var8, i64 4, i32 4, i1 false) +ret void +} +define void @Outer.Nested.main(%class_Outer.Nested* %classvariable.this) +{ +ret void +} +define void @test() { -%var13 = call i32 @nullable_test(i32 0) -%var14 = alloca i32, align 4 -store i32 %var13, i32* %var14, align 4 ret void } diff --git a/translator/run_tests.sh b/translator/run_tests.sh index f88f4b25362..6fbb3352676 100755 --- a/translator/run_tests.sh +++ b/translator/run_tests.sh @@ -30,7 +30,7 @@ for i in $( ls "$DIRECTORY/input"); do clang-3.6 -S -emit-llvm $DIRECTORY/linked/main.c -o $DIRECTORY/linked/main.ll -Wno-implicit-function-declaration rm -f $DIRECTORY/linked/main.c - cp /home/user/Kotlin/carkot/translator/src/main/resources/kotllib/* $DIRECTORY/linked/ + cp ./src/main/resources/kotllib/* $DIRECTORY/linked/ if [ -f "$DIRECTORY/c/$TEST.c" ] then diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt index cd46a075994..57ca7ef31b3 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/BlockCodegen.kt @@ -89,10 +89,22 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM private fun evaluateDotExpression(expr: KtDotQualifiedExpression, scopeDepth: Int): LLVMSingleValue? { val receiverName = expr.receiverExpression.text - val selectorName = expr.selectorExpression!!.text + val selectorName = expr.selectorExpression!!.text!! - val receiver = variableManager.getLLVMvalue(receiverName)!! + val receiver = variableManager.getLLVMvalue(receiverName) + if (receiver != null) { + return evaluateMemberMethodOrField(receiver, selectorName, scopeDepth, expr.lastChild) + } + val clazz = state.classes.get(receiverName) ?: return null + return evaluateClassScopedDotExpression(clazz, selectorName, scopeDepth) + } + + private fun evaluateClassScopedDotExpression(clazz: ClassCodegen, selectorName: String, scopeDepth: Int): LLVMSingleValue? { + return null + } + + private fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement): LLVMSingleValue? { val clazz = state.classes[(receiver.type as LLVMReferenceType).type] ?: state.objects[(receiver.type as LLVMReferenceType).type]!! val field = clazz.fieldsIndex[selectorName] if (field != null) { @@ -104,7 +116,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM val method = clazz.methods[methodName]!! val returnType = clazz.methods[methodName]!!.returnType!!.type - val names = parseArgList(expr.lastChild as KtCallExpression, scopeDepth) + val names = parseArgList(call as KtCallExpression, scopeDepth) val loadedArgs = loadArgsIfRequired(names, method.args) val callArgs = mutableListOf(receiver) callArgs.addAll(loadedArgs) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt index c4289cf7bd4..fa4292e09e2 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -10,25 +10,33 @@ import org.kotlinnative.translator.llvm.LLVMBuilder import org.kotlinnative.translator.llvm.LLVMClassVariable import org.kotlinnative.translator.llvm.types.LLVMEnumItemType import org.kotlinnative.translator.llvm.types.LLVMReferenceType -import org.kotlinnative.translator.llvm.types.LLVMType -class ClassCodegen(override val state: TranslationState, override val variableManager: VariableManager, val clazz: KtClass, override val codeBuilder: LLVMBuilder) : - StructCodegen(state, variableManager, clazz, state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException(), codeBuilder) { +class ClassCodegen(override val state: TranslationState, + override val variableManager: VariableManager, + val clazz: KtClass, + override val codeBuilder: LLVMBuilder, + prefix: String = "") : + + StructCodegen(state, variableManager, clazz, state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException(), codeBuilder, prefix) { val annotation: Boolean override var size: Int = 0 override val structName: String - override val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true) + override val type: LLVMReferenceType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true) init { - structName = clazz.name.toString() + structName = clazz.name!! val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException() val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf() annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS indexFields(descriptor, parameterList) generateInnerFields(clazz.declarations) + + if (prefix.length > 0) { + type.prefix = "${type.prefix}_$prefix" + } type.size = size } @@ -64,6 +72,7 @@ class ClassCodegen(override val state: TranslationState, override val variableMa } generate(clazz.declarations) + nestedClasses.forEach { x, classCodegen -> classCodegen.generate() } } } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt index 7a158a8069e..147bc6430e1 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt @@ -39,8 +39,8 @@ class FileTranslator(val state: TranslationState, val file: KtFile) { property.generate() } - for (objectDeclaration in state.objects.values) { - objectDeclaration.generate() + for (objectCodegen in state.objects.values) { + objectCodegen.generate() } for (clazz in state.classes.values) { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt index d395e1e1c86..77623d2b454 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ObjectCodegen.kt @@ -14,7 +14,7 @@ class ObjectCodegen(override val state: TranslationState, override val variableM codeBuilder) { override var size: Int = 0 override val structName: String - override val type: LLVMType = LLVMReferenceType(objectDeclaration.name.toString(), "class", byRef = true) + override val type: LLVMReferenceType = LLVMReferenceType(objectDeclaration.name.toString(), "class", byRef = true) init { structName = objectDeclaration.name!! diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt index 321763dae90..da989552e90 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/StructCodegen.kt @@ -12,19 +12,26 @@ import org.kotlinnative.translator.llvm.types.LLVMType import org.kotlinnative.translator.llvm.types.LLVMVoidType import java.util.* -abstract class StructCodegen(open val state: TranslationState, open val variableManager: VariableManager, open val classOrObject: KtClassOrObject, +abstract class StructCodegen(open val state: TranslationState, + open val variableManager: VariableManager, + open val classOrObject: KtClassOrObject, val classDescriptor: ClassDescriptor, - open val codeBuilder: LLVMBuilder) { + open val codeBuilder: LLVMBuilder, + val prefix: String = "") { val fields = ArrayList() val fieldsIndex = HashMap() + val nestedClasses = HashMap() val constructorFields = ArrayList() - abstract val type: LLVMType + abstract val type: LLVMReferenceType abstract var size: Int var methods = HashMap() abstract val structName: String + val fullName: String + get() = "${if (prefix.length > 0) "${prefix}_" else ""}$structName" + fun generate(declarations: List) { generateStruct() @@ -60,14 +67,19 @@ abstract class StructCodegen(open val state: TranslationState, open val variable fieldsIndex[field.label] = field size += field.type.size } + is KtClass -> { + nestedClasses.put(declaration.name!!, + ClassCodegen(state, + VariableManager(state.globalVariableCollection), + declaration, codeBuilder, + fullName)) + } } } } private fun generateStruct() { - val name = classDescriptor.name.identifier - - codeBuilder.createClass(name, fields) + codeBuilder.createClass(fullName, fields) } private fun generatePrimaryConstructor() { @@ -82,7 +94,7 @@ abstract class StructCodegen(open val state: TranslationState, open val variable argFields.add(classVal) argFields.addAll(constructorFields) - codeBuilder.addLLVMCode(LLVMFunctionDescriptor(classDescriptor.name.identifier, argFields, LLVMVoidType(), arm = state.arm)) + codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName, argFields, LLVMVoidType(), arm = state.arm)) codeBuilder.addStartExpression() generateLoadArguments(classVal)