translator: enums

This commit is contained in:
e5l
2016-08-08 16:57:53 +03:00
parent a230fadd0d
commit d83215e3ec
8 changed files with 71 additions and 54 deletions
-1
View File
@@ -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"
}