translator: add class methods, fix empty class argument list

This commit is contained in:
Alexey Stepanov
2016-07-18 14:38:09 +03:00
parent 314dbcbcd0
commit e8ceffc79d
10 changed files with 58 additions and 34 deletions
@@ -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 {
@@ -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"