translator: add class methods, fix empty class argument list
This commit is contained in:
@@ -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<LLVMVariable>()
|
||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||
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<String, FunctionCodegen>()
|
||||
|
||||
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<LLVMVariable>()
|
||||
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())
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<LLVMVariable>()
|
||||
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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<String, FunctionCodegen>()
|
||||
val variableManager = VariableManager()
|
||||
val globalVariableCollection = HashMap<String, LLVMVariable>()
|
||||
var classes = HashMap<String, ClassCodegen>()
|
||||
var properties = HashMap<String, PropertyCodegen>()
|
||||
}
|
||||
|
||||
@@ -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<String, LLVMVariable>) {
|
||||
|
||||
private var fileVariableCollectionTree = HashMap<String, Stack<Pair<LLVMVariable, Int>>>()
|
||||
private var globalVariableCollection = HashMap<String, LLVMVariable>()
|
||||
private var variableVersion = HashMap<String, Int>()
|
||||
|
||||
fun getLLVMvalue(variableName: String): LLVMVariable? {
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.kotlinnative.translator.llvm.types.*
|
||||
fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, 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 {
|
||||
|
||||
+1
-2
@@ -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"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user