translator: add object declarations
This commit is contained in:
@@ -3,24 +3,27 @@ package org.kotlinnative.translator
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.exceptions.TranslationException
|
||||
import org.kotlinnative.translator.llvm.*
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
import java.util.*
|
||||
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(val state: TranslationState, val variableManager: VariableManager, val clazz: KtClass, val codeBuilder: LLVMBuilder) {
|
||||
class ClassCodegen(override val state: TranslationState, override val variableManager: VariableManager, val clazz: KtClass, override val codeBuilder: LLVMBuilder) :
|
||||
StructCodegen(state, variableManager, state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException(), codeBuilder) {
|
||||
|
||||
val annotation: Boolean
|
||||
val fields = ArrayList<LLVMVariable>()
|
||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||
val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
|
||||
val size: Int
|
||||
var methods = HashMap<String, FunctionCodegen>()
|
||||
|
||||
override val size: Int
|
||||
override val structName: String
|
||||
override val type: LLVMType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
|
||||
|
||||
|
||||
init {
|
||||
structName = clazz.name.toString()
|
||||
val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException()
|
||||
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
|
||||
|
||||
@@ -66,22 +69,7 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
||||
return
|
||||
}
|
||||
|
||||
generateStruct()
|
||||
generatePrimaryConstructor()
|
||||
|
||||
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)
|
||||
}
|
||||
generate(clazz.declarations)
|
||||
}
|
||||
|
||||
private fun generateStruct() {
|
||||
@@ -89,105 +77,4 @@ class ClassCodegen(val state: TranslationState, val variableManager: VariableMan
|
||||
|
||||
codeBuilder.createClass(name, fields)
|
||||
}
|
||||
|
||||
private fun generatePrimaryConstructor() {
|
||||
val classData = state.bindingContext.get(BindingContext.CLASS, clazz)
|
||||
val classKind = classData?.kind
|
||||
//if (classKind == ClassKind.ENUM_CLASS)
|
||||
val argFields = ArrayList<LLVMVariable>()
|
||||
val refType = type.makeClone() as LLVMReferenceType
|
||||
refType.addParam("sret")
|
||||
refType.byRef = true
|
||||
|
||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||
variableManager.addVariable("this", classVal, 0)
|
||||
|
||||
argFields.add(classVal)
|
||||
argFields.addAll(fields)
|
||||
|
||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(clazz.name!!, argFields, LLVMVoidType(), arm = state.arm))
|
||||
|
||||
codeBuilder.addStartExpression()
|
||||
generateLoadArguments(classVal)
|
||||
generateAssignments()
|
||||
generateReturn()
|
||||
codeBuilder.addAnyReturn(LLVMVoidType())
|
||||
codeBuilder.addEndExpression()
|
||||
}
|
||||
|
||||
private fun generateLoadArguments(thisField: LLVMVariable) {
|
||||
|
||||
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
|
||||
codeBuilder.loadArgument(thisVariable, false)
|
||||
|
||||
fields.forEach {
|
||||
if (it.type !is LLVMReferenceType) {
|
||||
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
|
||||
codeBuilder.loadArgument(loadVariable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateAssignments() {
|
||||
fields.forEach {
|
||||
when (it.type) {
|
||||
is LLVMReferenceType -> {
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = it.pointer + 1)
|
||||
codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
|
||||
codeBuilder.storeVariable(classField, it)
|
||||
}
|
||||
else -> {
|
||||
val argument = codeBuilder.getNewVariable(it.type, it.pointer)
|
||||
codeBuilder.loadVariable(argument, LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = it.pointer + 1))
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = 1)
|
||||
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("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||
val src = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||
|
||||
val castedDst = codeBuilder.bitcast(dst, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||
val castedSrc = codeBuilder.bitcast(src, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||
|
||||
codeBuilder.memcpy(castedDst, castedSrc, size)
|
||||
}
|
||||
|
||||
private fun resolveType(field: KtParameter): LLVMClassVariable {
|
||||
val annotations = parseFieldAnnotations(field)
|
||||
|
||||
val ktType = state.bindingContext.get(BindingContext.TYPE, field.typeReference)!!
|
||||
val result = LLVMMapStandardType(field.name!!, ktType, LLVMRegisterScope())
|
||||
|
||||
if (result.type is LLVMReferenceType) {
|
||||
val type = result.type as LLVMReferenceType
|
||||
type.prefix = "class"
|
||||
type.byRef = true
|
||||
}
|
||||
|
||||
if (annotations.contains("Plain")) {
|
||||
result.pointer = 0
|
||||
}
|
||||
|
||||
return LLVMClassVariable(result.label, result.type, result.pointer)
|
||||
}
|
||||
|
||||
private fun parseFieldAnnotations(field: KtParameter): Set<String> {
|
||||
val result = HashSet<String>()
|
||||
|
||||
for (annotation in field.annotationEntries) {
|
||||
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
|
||||
val type = annotationDescriptor?.type.toString()
|
||||
|
||||
result.add(type)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
|
||||
class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||
@@ -31,6 +28,10 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +39,10 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||
property.generate()
|
||||
}
|
||||
|
||||
for (objectDeclaration in state.objects.values) {
|
||||
objectDeclaration.generate()
|
||||
}
|
||||
|
||||
for (clazz in state.classes.values) {
|
||||
clazz.generate()
|
||||
}
|
||||
@@ -45,8 +50,6 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||
for (function in state.functions.values) {
|
||||
function.generate()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -184,14 +184,14 @@ class FunctionCodegen(val state: TranslationState, val variableManager: Variable
|
||||
|
||||
val receiver = variableManager.getLLVMvalue(receiverName)!!
|
||||
|
||||
val clazz = state.classes[(receiver.type as LLVMReferenceType).type]!!
|
||||
val clazz = state.classes[(receiver.type as LLVMReferenceType).type] ?: state.objects[(receiver.type as LLVMReferenceType).type]!!
|
||||
val field = clazz.fieldsIndex[selectorName]
|
||||
if (field != null) {
|
||||
val result = codeBuilder.getNewVariable(field.type, pointer = 1)
|
||||
codeBuilder.loadClassField(result, receiver, field.offset)
|
||||
return result
|
||||
} else {
|
||||
val methodName = clazz.clazz.name.toString() + '.' + selectorName.substringBefore('(')
|
||||
val methodName = clazz.structName + '.' + selectorName.substringBefore('(')
|
||||
val method = clazz.methods[methodName]!!
|
||||
val returnType = clazz.methods[methodName]!!.returnType.type
|
||||
val methodArgs = mutableListOf<LLVMSingleValue>(receiver)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.exceptions.TranslationException
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
class ObjectCodegen(override val state: TranslationState, override val variableManager: VariableManager, val objectDeclaration: KtObjectDeclaration, override val codeBuilder: LLVMBuilder) :
|
||||
StructCodegen(state, variableManager, state.bindingContext.get(BindingContext.CLASS, objectDeclaration) ?: throw TranslationException(), codeBuilder) {
|
||||
override val size: Int = 0
|
||||
override val structName: String
|
||||
override val type: LLVMType = LLVMReferenceType(objectDeclaration.name.toString(), "class", byRef = true)
|
||||
|
||||
init {
|
||||
structName = objectDeclaration.name!!
|
||||
}
|
||||
|
||||
fun generate() {
|
||||
generate(objectDeclaration.declarations)
|
||||
val classInstance = LLVMVariable("object.instance.${structName}", type, objectDeclaration.name, LLVMVariableScope())
|
||||
codeBuilder.addGlobalIntialize(classInstance, type);
|
||||
variableManager.addGlobalVariable(structName, classInstance)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.llvm.*
|
||||
import org.kotlinnative.translator.llvm.types.LLVMCharType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||
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 classDescriptor: ClassDescriptor, open val codeBuilder: LLVMBuilder) {
|
||||
|
||||
val plain: Boolean = false // TODO
|
||||
val fields = ArrayList<LLVMVariable>()
|
||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||
abstract val type: LLVMType
|
||||
abstract val size: Int
|
||||
var methods = HashMap<String, FunctionCodegen>()
|
||||
abstract val structName: String
|
||||
|
||||
|
||||
fun generate(declarationList: List<KtDeclaration>) {
|
||||
generateStruct()
|
||||
generatePrimaryConstructor()
|
||||
|
||||
for (declaration in declarationList) {
|
||||
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() {
|
||||
val name = classDescriptor.name.identifier
|
||||
|
||||
codeBuilder.createClass(name, fields)
|
||||
}
|
||||
|
||||
private fun generatePrimaryConstructor() {
|
||||
val argFields = ArrayList<LLVMVariable>()
|
||||
val refType = type.makeClone() as LLVMReferenceType
|
||||
refType.addParam("sret")
|
||||
refType.byRef = true
|
||||
|
||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||
variableManager.addVariable("this", classVal, 0)
|
||||
|
||||
argFields.add(classVal)
|
||||
argFields.addAll(fields)
|
||||
|
||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(classDescriptor.name.identifier, argFields, LLVMVoidType(), arm = state.arm))
|
||||
|
||||
codeBuilder.addStartExpression()
|
||||
generateLoadArguments(classVal)
|
||||
generateAssignments()
|
||||
generateReturn()
|
||||
codeBuilder.addAnyReturn(LLVMVoidType())
|
||||
codeBuilder.addEndExpression()
|
||||
}
|
||||
|
||||
private fun generateLoadArguments(thisField: LLVMVariable) {
|
||||
|
||||
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
|
||||
codeBuilder.loadArgument(thisVariable, false)
|
||||
|
||||
fields.forEach {
|
||||
if (it.type !is LLVMReferenceType) {
|
||||
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
|
||||
codeBuilder.loadArgument(loadVariable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateAssignments() {
|
||||
fields.forEach {
|
||||
when (it.type) {
|
||||
is LLVMReferenceType -> {
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = it.pointer + 1)
|
||||
codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
|
||||
codeBuilder.storeVariable(classField, it)
|
||||
}
|
||||
else -> {
|
||||
val argument = codeBuilder.getNewVariable(it.type, it.pointer)
|
||||
codeBuilder.loadVariable(argument, LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = it.pointer + 1))
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = 1)
|
||||
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("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||
val src = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||
|
||||
val castedDst = codeBuilder.bitcast(dst, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||
val castedSrc = codeBuilder.bitcast(src, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||
|
||||
codeBuilder.memcpy(castedDst, castedSrc, size)
|
||||
}
|
||||
|
||||
protected fun resolveType(field: KtParameter): LLVMClassVariable {
|
||||
val annotations = parseFieldAnnotations(field)
|
||||
|
||||
val ktType = state.bindingContext.get(BindingContext.TYPE, field.typeReference)!!
|
||||
val result = LLVMMapStandardType(field.name!!, ktType, LLVMRegisterScope())
|
||||
|
||||
if (result.type is LLVMReferenceType) {
|
||||
val type = result.type as LLVMReferenceType
|
||||
type.prefix = "class"
|
||||
type.byRef = true
|
||||
}
|
||||
|
||||
if (annotations.contains("Plain")) {
|
||||
result.pointer = 0
|
||||
}
|
||||
|
||||
return LLVMClassVariable(result.label, result.type, result.pointer)
|
||||
}
|
||||
|
||||
private fun parseFieldAnnotations(field: KtParameter): Set<String> {
|
||||
val result = HashSet<String>()
|
||||
|
||||
for (annotation in field.annotationEntries) {
|
||||
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
|
||||
val type = annotationDescriptor?.type.toString()
|
||||
|
||||
result.add(type)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ class TranslationState(val environment: KotlinCoreEnvironment, val bindingContex
|
||||
var functions = HashMap<String, FunctionCodegen>()
|
||||
val globalVariableCollection = HashMap<String, LLVMVariable>()
|
||||
var classes = HashMap<String, ClassCodegen>()
|
||||
var objects = HashMap<String, ObjectCodegen>()
|
||||
var properties = HashMap<String, PropertyCodegen>()
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,11 @@ class LLVMBuilder(val arm: Boolean) {
|
||||
globalCode.appendln("$variable = private unnamed_addr constant ${type.fullType()} c\"$value\\00\", align 1")
|
||||
}
|
||||
|
||||
fun addGlobalIntialize(target: LLVMVariable, classType: LLVMType) {
|
||||
val code = "$target = internal global $classType zeroinitializer, align ${classType.align}"
|
||||
globalCode.appendln(code)
|
||||
}
|
||||
|
||||
fun storeString(target: LLVMVariable, source: LLVMVariable, offset: Int) {
|
||||
val stringType = source.type as LLVMStringType
|
||||
val code = "store ${target.type} getelementptr inbounds (${stringType.fullType()}, " +
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Singleton.create(5) == 40
|
||||
@@ -0,0 +1,6 @@
|
||||
object Singleton {
|
||||
fun create(x : Int): Int {
|
||||
return x * 8
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user