translator: enums
This commit is contained in:
-1
@@ -10,7 +10,6 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="ast-kotlin_main" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.1" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-compiler:1.0.3" level="project" />
|
||||
<orderEntry type="library" name="Gradle: junit:junit:4.11" level="project" />
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getType
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
|
||||
import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant
|
||||
import org.kotlinnative.translator.llvm.*
|
||||
@@ -100,7 +101,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
}
|
||||
|
||||
private fun evaluateThisExpression(): LLVMSingleValue? {
|
||||
return variableManager.getLLVMvalue("this")
|
||||
return variableManager.get("this")
|
||||
}
|
||||
|
||||
fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? {
|
||||
@@ -172,7 +173,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
var receiver = when (receiverExpr) {
|
||||
is KtCallExpression,
|
||||
is KtBinaryExpression -> evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
|
||||
else -> variableManager.getLLVMvalue(receiverName)
|
||||
else -> variableManager.get(receiverName)
|
||||
}
|
||||
|
||||
if (receiver != null) {
|
||||
@@ -212,7 +213,6 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
}
|
||||
|
||||
private fun evaluateClassScopedDotExpression(clazz: ClassCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) {
|
||||
|
||||
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz)
|
||||
is KtReferenceExpression -> evaluateReferenceExpression(selector, scopeDepth, clazz)
|
||||
else -> throw UnsupportedOperationException()
|
||||
@@ -221,12 +221,10 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: ClassCodegen? = null): LLVMSingleValue? {
|
||||
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
|
||||
val field = classScope!!.companionFieldsIndex[fieldName]
|
||||
|
||||
val companionObject = classScope.companionFieldsSource[fieldName]
|
||||
|
||||
val receiver = variableManager.getLLVMvalue(companionObject!!.fullName)!!
|
||||
|
||||
val receiver = variableManager.get(companionObject!!.fullName)!!
|
||||
val result = codeBuilder.getNewVariable(field!!.type, pointer = 1)
|
||||
|
||||
codeBuilder.loadClassField(result, receiver, field.offset)
|
||||
return result
|
||||
}
|
||||
@@ -282,10 +280,22 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
return indexVariable
|
||||
}
|
||||
|
||||
private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when (expr) {
|
||||
is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
|
||||
else -> if ((expr is KtNameReferenceExpression) && (classScope != null)) evaluateNameReferenceExpression(expr, classScope)
|
||||
else variableManager.getLLVMvalue(expr.firstChild.text)
|
||||
private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when {
|
||||
expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
|
||||
isEnumClassField(expr) -> resolveEnumClassField(expr)
|
||||
(expr is KtNameReferenceExpression) && (classScope != null) -> evaluateNameReferenceExpression(expr, classScope)
|
||||
else -> variableManager.get(expr.firstChild.text)
|
||||
}
|
||||
|
||||
private fun resolveEnumClassField(expr: KtReferenceExpression): LLVMSingleValue {
|
||||
val field = state.classes[expr.getType(state.bindingContext).toString()]!!.enumFields[expr.text]!!
|
||||
return codeBuilder.loadAndGetVariable(codeBuilder.loadAndGetVariable(field))
|
||||
}
|
||||
|
||||
private fun isEnumClassField(expr: KtReferenceExpression): Boolean {
|
||||
val name = expr.getType(state.bindingContext)?.toString() ?: return false
|
||||
val clazz = state.classes[name] ?: return false
|
||||
return clazz.enumFields.containsKey(expr.text)
|
||||
}
|
||||
|
||||
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? {
|
||||
@@ -308,7 +318,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
return evaluateConstructorCallExpression(LLVMVariable(name, descriptor.type, scope = LLVMVariableScope()), args)
|
||||
}
|
||||
|
||||
val localFunction = variableManager.getLLVMvalue(name)
|
||||
val localFunction = variableManager.get(name)
|
||||
if (localFunction != null) {
|
||||
val type = localFunction.type as LLVMFunctionType
|
||||
val args = loadArgsIfRequired(names, type.arguments)
|
||||
@@ -321,7 +331,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
if (classDescriptor.companionMethods.containsKey(methodShortName)) {
|
||||
val descriptor = classDescriptor.companionMethods[methodShortName] ?: return null
|
||||
val parentDescriptor = descriptor.parentCodegen!!
|
||||
val receiver = variableManager.getLLVMvalue(parentDescriptor.fullName)!!
|
||||
val receiver = variableManager.get(parentDescriptor.fullName)!!
|
||||
val methodFullName = descriptor.name
|
||||
|
||||
val returnType = descriptor.returnType!!.type
|
||||
@@ -613,7 +623,9 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
private fun evaluateWhenItem(item: KtWhenEntry, target: LLVMSingleValue, resultVariable: LLVMVariable, elseLabel: LLVMLabel, endLabel: LLVMLabel, isElse: Boolean, scopeDepth: Int) {
|
||||
val successConditionsLabel = codeBuilder.getNewLabel(prefix = "when_condition_success")
|
||||
var nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
|
||||
|
||||
codeBuilder.addUnconditionalJump(nextLabel)
|
||||
|
||||
for (condition in item.conditions) {
|
||||
codeBuilder.markWithLabel(nextLabel)
|
||||
nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
|
||||
@@ -623,10 +635,12 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
|
||||
codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel)
|
||||
}
|
||||
|
||||
codeBuilder.markWithLabel(nextLabel)
|
||||
codeBuilder.addComment("last condition item")
|
||||
codeBuilder.addUnconditionalJump(if (isElse) successConditionsLabel else elseLabel)
|
||||
codeBuilder.markWithLabel(successConditionsLabel)
|
||||
|
||||
val successExpression = evaluateExpression(item.expression, scopeDepth + 1)
|
||||
codeBuilder.storeVariable(resultVariable, successExpression ?: return)
|
||||
codeBuilder.addUnconditionalJump(endLabel)
|
||||
@@ -638,9 +652,11 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
val whenExpression = expr.subjectExpression
|
||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||
val expressionType = LLVMMapStandardType(kotlinType)
|
||||
if (state.classes.containsKey(kotlinType.toString())) {
|
||||
(expressionType as LLVMReferenceType).prefix = "class"
|
||||
}
|
||||
|
||||
val targetExpression = evaluateExpression(whenExpression, scopeDepth + 1)!!
|
||||
|
||||
val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1)
|
||||
codeBuilder.allocStackPointedVarAsValue(resultVariable)
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
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.KtParameter
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.exceptions.TranslationException
|
||||
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
|
||||
|
||||
class ClassCodegen(override val state: TranslationState,
|
||||
@@ -20,6 +17,7 @@ class ClassCodegen(override val state: TranslationState,
|
||||
StructCodegen(state, variableManager, clazz, state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException(), codeBuilder, parentCodegen) {
|
||||
|
||||
val annotation: Boolean
|
||||
val enum: Boolean
|
||||
|
||||
override var size: Int = 0
|
||||
override val structName: String = clazz.name!!
|
||||
@@ -31,7 +29,9 @@ class ClassCodegen(override val state: TranslationState,
|
||||
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
|
||||
|
||||
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
|
||||
indexFields(descriptor, parameterList)
|
||||
enum = descriptor.kind == ClassKind.ENUM_CLASS
|
||||
|
||||
indexFields(parameterList)
|
||||
generateInnerFields(clazz.declarations)
|
||||
|
||||
if (parentCodegen != null) {
|
||||
@@ -42,7 +42,7 @@ class ClassCodegen(override val state: TranslationState,
|
||||
type.size = size
|
||||
}
|
||||
|
||||
private fun indexFields(descriptor: ClassDescriptor, parameters: MutableList<KtParameter>) {
|
||||
private fun indexFields(parameters: MutableList<KtParameter>) {
|
||||
if (annotation) {
|
||||
return
|
||||
}
|
||||
@@ -56,18 +56,6 @@ class ClassCodegen(override val state: TranslationState,
|
||||
fieldsIndex[item.label] = item
|
||||
size += type.size
|
||||
}
|
||||
|
||||
when (descriptor.kind) {
|
||||
ClassKind.ENUM_CLASS -> {
|
||||
val item = LLVMClassVariable("enum_item", LLVMEnumItemType())
|
||||
item.offset = fields.size
|
||||
fields.add(item)
|
||||
fieldsIndex["enum_item"] = item
|
||||
size += type.size
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generate() {
|
||||
|
||||
@@ -20,7 +20,7 @@ class PropertyCodegen(val state: TranslationState, val variableManager: Variable
|
||||
val variableType = LLVMInstanceOfStandardType(property.name ?: return, kotlinType).type
|
||||
val variable = LLVMVariable(property.name.toString(), variableType, property.name.toString(), LLVMVariableScope(), pointer = 1)
|
||||
variableManager.addGlobalVariable(property.name.toString(), variable)
|
||||
codeBuilder.declareGlobalVariable(variable, variableType.parseArg(value.toString()))
|
||||
codeBuilder.defineGlobalVariable(variable, variableType.parseArg(value.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ abstract class StructCodegen(open val state: TranslationState,
|
||||
val companionFields = ArrayList<LLVMVariable>()
|
||||
val companionFieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||
val companionFieldsSource = HashMap<String, ObjectCodegen>()
|
||||
val enumFields = HashMap<String, LLVMVariable>()
|
||||
|
||||
val constructorFields = ArrayList<LLVMVariable>()
|
||||
|
||||
@@ -35,9 +36,9 @@ abstract class StructCodegen(open val state: TranslationState,
|
||||
val fullName: String
|
||||
get() = "${if (type.location.size > 0) "${type.location.joinToString(".")}." else ""}$structName"
|
||||
|
||||
|
||||
fun generate(declarations: List<KtDeclaration>) {
|
||||
generateStruct()
|
||||
generateEnumFields()
|
||||
generatePrimaryConstructor()
|
||||
|
||||
for (declaration in declarations) {
|
||||
@@ -72,6 +73,11 @@ abstract class StructCodegen(open val state: TranslationState,
|
||||
fieldsIndex[field.label] = field
|
||||
size += field.type.size
|
||||
}
|
||||
is KtEnumEntry -> {
|
||||
val name = declaration.name!!
|
||||
val field = LLVMVariable("class.$fullName.$name", type, scope = LLVMVariableScope(), pointer = 2)
|
||||
enumFields.put(name, field)
|
||||
}
|
||||
is KtClass -> {
|
||||
nestedClasses.put(declaration.name!!,
|
||||
ClassCodegen(state,
|
||||
@@ -83,6 +89,22 @@ abstract class StructCodegen(open val state: TranslationState,
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateEnumFields() {
|
||||
val enumEntries = classOrObject.declarations.filter { it is KtEnumEntry }
|
||||
|
||||
for (declaration in enumEntries) {
|
||||
val name = declaration.name!!
|
||||
val initializer = (declaration as KtEnumEntry).initializerList!!.initializers[0]
|
||||
val arguments = (initializer as KtSuperTypeCallEntry).valueArguments.map { it.getArgumentExpression()!!.text }
|
||||
|
||||
val field = codeBuilder.getNewVariable(type, scope = LLVMVariableScope())
|
||||
val enumField = enumFields[name]!!
|
||||
|
||||
codeBuilder.defineGlobalVariable(field, codeBuilder.makeStructInitializer(constructorFields, arguments))
|
||||
codeBuilder.defineGlobalVariable(LLVMVariable(enumField.label, enumField.type, enumField.kotlinName, enumField.scope, enumField.pointer - 1), "$field")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateStruct() {
|
||||
codeBuilder.createClass(fullName, fields)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class VariableManager(val globalVariableCollection: HashMap<String, LLVMVariable
|
||||
private var fileVariableCollectionTree = HashMap<String, Stack<Pair<LLVMVariable, Int>>>()
|
||||
private var variableVersion = HashMap<String, Int>()
|
||||
|
||||
fun getLLVMvalue(variableName: String): LLVMVariable? {
|
||||
fun get(variableName: String): LLVMVariable? {
|
||||
return fileVariableCollectionTree[variableName]?.peek()?.first ?: globalVariableCollection[variableName]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
import org.kotlinnative.translator.llvm.types.LLVMCharType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMIntType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMStringType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
class LLVMBuilder(val arm: Boolean) {
|
||||
private val POINTER_SIZE = 4
|
||||
@@ -28,9 +30,9 @@ class LLVMBuilder(val arm: Boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
fun getNewVariable(type: LLVMType, pointer: Int = 0, kotlinName: String? = null): LLVMVariable {
|
||||
fun getNewVariable(type: LLVMType, pointer: Int = 0, kotlinName: String? = null, scope: LLVMScope = LLVMRegisterScope()): LLVMVariable {
|
||||
variableCount++
|
||||
return LLVMVariable("var$variableCount", type, kotlinName, LLVMRegisterScope(), pointer)
|
||||
return LLVMVariable("var$variableCount", type, kotlinName, scope, pointer)
|
||||
}
|
||||
|
||||
fun getNewLabel(scope: LLVMScope = LLVMRegisterScope(), prefix: String): LLVMLabel {
|
||||
@@ -181,10 +183,13 @@ class LLVMBuilder(val arm: Boolean) {
|
||||
localCode.appendln("store ${allocVariable.type} $constantValue, ${allocVariable.getType()} $allocVariable, align ${allocVariable.type.align}")
|
||||
}
|
||||
|
||||
fun declareGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) {
|
||||
localCode.appendln("$variable = global ${variable.type} $defaultValue, align ${variable.type.align}")
|
||||
fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) {
|
||||
localCode.appendln("$variable = global ${variable.getType()} $defaultValue, align ${variable.type.align}")
|
||||
}
|
||||
|
||||
fun makeStructInitializer(args: List<LLVMVariable>, values: List<String>)
|
||||
= "{ ${ args.mapIndexed { i: Int, variable: LLVMVariable -> "${variable.type} ${values[i]}" }.joinToString() } }"
|
||||
|
||||
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
|
||||
assert(source.pointer > 0)
|
||||
val target = getNewVariable(source.type, source.pointer - 1, source.kotlinName)
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
|
||||
class LLVMEnumItemType() : LLVMType() {
|
||||
|
||||
override val align = 4
|
||||
override var size: Int = 4
|
||||
override val defaultValue = "0"
|
||||
|
||||
override fun mangle() = "Enum"
|
||||
|
||||
override fun toString() = "i32"
|
||||
}
|
||||
Reference in New Issue
Block a user