diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt index 8a606bf114a..aceb38f017b 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/ClassCodegen.kt @@ -3,6 +3,7 @@ package org.kotlinnative.translator import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtUserType import org.jetbrains.kotlin.resolve.BindingContext @@ -12,18 +13,19 @@ import org.kotlinnative.translator.llvm.* import org.kotlinnative.translator.llvm.types.* import java.util.* -class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuilder: LLVMBuilder) { +class ClassCodegen(val state: TranslationState, val variableManager: VariableManager, val clazz: KtClass, val codeBuilder: LLVMBuilder) { val annotation: Boolean val native: Boolean val fields = ArrayList() val fieldsIndex = HashMap() - val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class") + val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", align = 8, byRef = true, uncopyable = true) val size: Int + var methods = HashMap() init { val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException() - val parameterList = clazz.getPrimaryConstructorParameterList()!!.parameters + val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf() var offset = 0 var currentSize = 0 @@ -53,6 +55,21 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil generateStruct() generateDefaultConstructor() + + for (declaration in clazz.declarations) { + when (declaration) { + is KtNamedFunction -> { + val function = FunctionCodegen(state, variableManager, declaration, codeBuilder) + methods.put(function.name, function) + } + } + } + val classVal = LLVMVariable("classvariable.this", type, pointer = 1) + variableManager.addVariable("this", classVal, 0); + for (function in methods.values) { + + function.generate(classVal) + } } private fun generateStruct() { @@ -65,17 +82,18 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil val argFields = ArrayList() val refType = type.makeClone() as LLVMReferenceType refType.addParam("sret") - refType.isReturn = true + refType.byRef = true - val thisField = LLVMVariable("instance", refType, clazz.name, pointer = 1) + val classVal = LLVMVariable("classvariable.this", type, pointer = 1) + variableManager.addVariable("this", classVal, 0); - argFields.add(thisField) + argFields.add(classVal) argFields.addAll(fields) codeBuilder.addLLVMCode(LLVMFunctionDescriptor(clazz.name!!, argFields, LLVMVoidType(), arm = state.arm)) codeBuilder.addStartExpression() - generateLoadArguments(thisField) + generateLoadArguments(classVal) generateAssignments() generateReturn() codeBuilder.addAnyReturn(LLVMVoidType()) @@ -84,7 +102,7 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil private fun generateLoadArguments(thisField: LLVMVariable) { - val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 1) + val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0) codeBuilder.loadArgument(thisVariable, false) fields.forEach { @@ -98,14 +116,14 @@ class ClassCodegen(val state: TranslationState, val clazz: KtClass, val codeBuil val argument = codeBuilder.getNewVariable(it.type) codeBuilder.loadVariable(argument, LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = 1)) val classField = codeBuilder.getNewVariable(it.type, pointer = 1) - codeBuilder.loadClassField(classField, LLVMVariable("instance.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset) + codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset) codeBuilder.storeVariable(classField, argument) } } private fun generateReturn() { - val dst = LLVMVariable("instance", type, scope = LLVMRegisterScope(), pointer = 1) - val src = LLVMVariable("instance.addr", type, scope = LLVMRegisterScope(), pointer = 1) + val dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1) + val src = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1) val castedDst = codeBuilder.bitcast(dst, LLVMCharType()) val castedSrc = codeBuilder.bitcast(src, LLVMCharType()) diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt index 6a9c12f531b..6a39fd060fb 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt @@ -20,15 +20,15 @@ class FileTranslator(val state: TranslationState, val file: KtFile) { for (declaration in file.declarations) { when (declaration) { is KtNamedFunction -> { - val function = FunctionCodegen(state, declaration, codeBuilder) + val function = FunctionCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder) state.functions.put(function.name, function) } is KtClass -> { - val codegen = ClassCodegen(state, declaration, codeBuilder) + val codegen = ClassCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder) state.classes.put(declaration.name!!, codegen) } is KtProperty -> { - val property = PropertyCodegen(state, declaration, codeBuilder) + val property = PropertyCodegen(state, VariableManager(state.globalVariableCollection), declaration, codeBuilder) state.properties.put(declaration.name!!, property) } } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index 52be6c583db..8107f8cf822 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -16,12 +16,11 @@ import org.kotlinnative.translator.llvm.types.* import java.util.* -class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) { +class FunctionCodegen(val state: TranslationState, val variableManager : VariableManager, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) { var name = function.fqName.toString() var returnType: LLVMVariable var args = ArrayList() - val variableManager = state.variableManager val topLevel = 2 var wasReturnOnTopLevel = false @@ -39,7 +38,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction retType.prefix = "class" } - retType.isReturn = true + retType.byRef = true } } if (retType is LLVMReferenceType && state.classes.containsKey(retType.type)) { @@ -47,8 +46,8 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction } } - fun generate() { - if (generateDeclaration()) { + fun generate(this_type: LLVMVariable? = null) { + if (generateDeclaration(this_type)) { return } @@ -62,9 +61,12 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction codeBuilder.addEndExpression() } - private fun generateDeclaration(): Boolean { + private fun generateDeclaration(this_type: LLVMVariable? = null): Boolean { var external = false + if (this_type != null) { + args.add(this_type) + } args.forEach { val type = it.type if (type is LLVMReferenceType && state.classes.containsKey(type.type)) { @@ -98,13 +100,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction private fun generateLoadArguments() { args.forEach(fun(it: LLVMVariable) { - if (it.type is LLVMFunctionType) { + if (it.type is LLVMFunctionType || (it.type is LLVMReferenceType && (it.type as LLVMReferenceType).uncopyable)) { variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 1), topLevel) return } - if (it.type !is LLVMReferenceType || (it.type as LLVMReferenceType).isReturn) { - val loadVariable = LLVMVariable("${it.label}", it.type, it.label, LLVMRegisterScope(), pointer = 0) + if (it.type !is LLVMReferenceType || (it.type as LLVMReferenceType).byRef) { + val loadVariable = LLVMVariable("${it.label}", it.type, it.label, LLVMRegisterScope(), pointer = it.pointer) val allocVar = codeBuilder.loadArgument(loadVariable) variableManager.addVariable(it.label, allocVar, topLevel) } else { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt index f72effb09d9..358b2df2e1d 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/PropertyCodegen.kt @@ -4,13 +4,12 @@ import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.resolve.BindingContext import org.kotlinnative.translator.llvm.LLVMBuilder -import org.kotlinnative.translator.llvm.LLVMVariableScope import org.kotlinnative.translator.llvm.LLVMMapStandardType import org.kotlinnative.translator.llvm.LLVMVariable +import org.kotlinnative.translator.llvm.LLVMVariableScope -class PropertyCodegen(val state: TranslationState, val property: KtProperty, val codeBuilder: LLVMBuilder) { - private val variableManager = state.variableManager +class PropertyCodegen(val state: TranslationState, val variableManager: VariableManager, val property: KtProperty, val codeBuilder: LLVMBuilder) { fun generate() { val varInfo = state.bindingContext.get(BindingContext.VARIABLE, property)?.compileTimeInitializer ?: return diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt index 8a4575f8104..ea687fdf771 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt @@ -18,12 +18,13 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.utils.PathUtil import org.kotlinnative.translator.exceptions.TranslationException +import org.kotlinnative.translator.llvm.LLVMVariable import java.util.* class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val arm: Boolean) { var functions = HashMap() - val variableManager = VariableManager() + val globalVariableCollection = HashMap() var classes = HashMap() var properties = HashMap() } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt b/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt index fdd92fa5ec2..d0cddefd095 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/VariableManager.kt @@ -5,10 +5,9 @@ import org.kotlinnative.translator.llvm.LLVMVariable import org.kotlinnative.translator.llvm.types.LLVMType import java.util.* -class VariableManager { +class VariableManager(val globalVariableCollection: HashMap) { private var fileVariableCollectionTree = HashMap>>() - private var globalVariableCollection = HashMap() private var variableVersion = HashMap() fun getLLVMvalue(variableName: String): LLVMVariable? { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/debug/debug.kt b/translator/src/main/kotlin/org/kotlinnative/translator/debug/debug.kt index 55f35bddc21..345a7416faa 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/debug/debug.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/debug/debug.kt @@ -3,6 +3,7 @@ package org.kotlinnative.translator.debug import com.intellij.psi.PsiElement import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.impl.source.tree.CompositeElement +import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction @@ -41,12 +42,17 @@ fun printFunction(function: KtNamedFunction) { debugPrintNode(function.node) } +fun printClass(function: KtClass) { + debugPrintNode(function.node) +} + fun printFile(file: KtFile) { for (declaration in file.declarations) { when (declaration) { is KtNamedFunction -> printFunction(declaration) + is KtClass -> printClass(declaration) else -> println(declaration.toString()) } } diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt index 1e76b3b0856..f84bc2084cc 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -143,7 +143,7 @@ class LLVMBuilder(val arm: Boolean) { } fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable { - val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = 1) + val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = llvmVariable.pointer + 1) addVariableByRef(allocVar, llvmVariable, store) return allocVar } @@ -158,7 +158,7 @@ class LLVMBuilder(val arm: Boolean) { } fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) { - llvmLocalCode.appendln("$targetVariable = alloca ${sourceVariable.type}, align ${sourceVariable.type.align}") + llvmLocalCode.appendln("$targetVariable = alloca ${sourceVariable.type}${"*".repeat(sourceVariable.pointer)}, align ${sourceVariable.type.align}") if (store) { llvmLocalCode.appendln("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type.align}") diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt index 768276e4787..c567649f3d6 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/generators.kt @@ -9,7 +9,7 @@ import org.kotlinnative.translator.llvm.types.* fun LLVMFunctionDescriptor(name: String, argTypes: List?, returnType: LLVMType, declare: Boolean = false, arm: Boolean = false) = "${if (declare) "declare" else "define"} $returnType @$name(${ argTypes?.mapIndexed { i: Int, s: LLVMVariable -> - "${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).isReturn) "byval" else ""} %${s.label}" + "${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).byRef) "byval" else ""} %${s.label}" }?.joinToString()}) ${if (arm) "#0" else ""}" fun LLVMMapStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope()): LLVMVariable = when { diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt index ffa1014611d..8395ed177b3 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMReferenceType.kt @@ -2,11 +2,10 @@ package org.kotlinnative.translator.llvm.types import java.util.* -class LLVMReferenceType(val type: String, var prefix: String = "", var isReturn: Boolean = false) : LLVMType() { +class LLVMReferenceType(val type: String, var prefix: String = "", override val align: Int = 4, var byRef: Boolean = false, val uncopyable: Boolean = false) : LLVMType() { override val defaultValue: String = "" - override val align = 4 override val size: Byte = 4 override fun toString() = "%$prefix${if (prefix.length > 0) "." else ""}$type"