translator: rewrite companions usage, tests fixes, pointer loading fixes, name resolve fixes

This commit is contained in:
e5l
2016-08-11 15:40:37 +03:00
parent 71ad20ddab
commit 1397ead8aa
11 changed files with 85 additions and 72 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ object WireFormat {
val FIXED_64_BYTE_SIZE: Int = 8
fun getTagWireType(tag: Int): WireType {
return WireType.from ( (tag and TAG_TYPE_MASK).toByte())
return WireType.from((tag and TAG_TYPE_MASK).toByte())
}
fun getTagFieldNumber(tag: Int): Int {
+2 -2
View File
@@ -15,7 +15,7 @@ enum class WireType(val id: Int) {
UNDEFINED(6); // indicates error when parsing from Int
companion object {
fun from (value: Byte): WireType {
fun from(value: Byte): WireType {
return when (value) {
0.toByte() -> VARINT
1.toByte() -> FIX_64
@@ -27,4 +27,4 @@ enum class WireType(val id: Int) {
}
}
}
}
}
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
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.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.kotlinnative.translator.llvm.*
import org.kotlinnative.translator.llvm.types.*
@@ -206,27 +207,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
}
val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiverExpr)?.type
?: receiverExpr.getType(state.bindingContext)
?: receiverExpr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext)
val path = type?.getSubtypesPredicate()?.toString()?.split(".")
val classReference = LLVMReferenceType(path?.last() ?: receiverName, "class")
if (path != null) {
classReference.location.addAll(path.dropLast(1))
}
val clazz = resolveClassOrObjectLocation(classReference) ?: return evaluateExtensionExpression(receiverExpr, selectorExpr as KtCallExpression, scopeDepth)
return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth)
val clazz = resolveCodegen(receiverExpr) ?: return evaluateExtensionExpression(receiverExpr, selectorExpr as KtCallExpression, scopeDepth)
return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth, receiver)
}
private fun evaluateExtensionExpression(receiver: KtExpression, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)
val standardType = LLVMMapStandardType(receiverType!!.type!!)
// if (standardType is LLVMReferenceType) {
// standardType.location.addAll(receiverType.type!!.getSubtypesPredicate().toString().split(".").dropLast(1))
// }
val function = selector.firstChild.firstChild.text
val names = parseArgList(selector, scopeDepth)
@@ -244,23 +231,12 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args)
}
private fun evaluateClassScopedDotExpression(clazz: StructCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) {
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz)
private fun evaluateClassScopedDotExpression(clazz: StructCodegen, selector: KtExpression, scopeDepth: Int, receiver: LLVMVariable? = null): LLVMSingleValue? = when (selector) {
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz, caller = receiver)
is KtReferenceExpression -> evaluateReferenceExpression(selector, scopeDepth, clazz)
else -> throw UnsupportedOperationException()
}
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: StructCodegen): 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[companionObject!!.fullName]!!
val result = codeBuilder.getNewVariable(field!!.type, pointer = 1)
codeBuilder.loadClassField(result, receiver, field.offset)
return result
}
fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? {
val type = receiver.type as LLVMReferenceType
val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString())
@@ -272,7 +248,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return result
}
val names = parseArgList(call!! as KtCallExpression, scopeDepth)
(call as? KtCallExpression) ?: throw UnexpectedException("$receiver:$selectorName")
val names = parseArgList(call as KtCallExpression, scopeDepth)
val typePath = type.location.joinToString(".")
val types = if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""
val methodName = "${if (typePath.length > 0) "$typePath." else ""}${clazz.structName}.${selectorName.substringBefore('(').trim()}$types"
@@ -353,23 +330,42 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: StructCodegen? = null): LLVMSingleValue? = when {
expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
isEnumClassField(expr) -> resolveEnumClassField(expr)
isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope)
resolveContainingClass(expr) != null -> {
val clazz = resolveContainingClass(expr)
val receiver = if (clazz != null) variableManager[clazz.fullName] ?: variableManager["this"] else variableManager["this"]
evaluateMemberMethodOrField(receiver!!, expr.firstChild.text, topLevel)
}
(expr is KtNameReferenceExpression) && (classScope != null) -> evaluateNameReferenceExpression(expr, classScope.parentCodegen!!)
resolveContainingClass(expr) != null -> evaluateMemberMethodOrField(variableManager["this"]!!, expr.firstChild.text, topLevel)
else -> variableManager[expr.firstChild.text]
}
private fun resolveEnumClassField(expr: KtReferenceExpression): LLVMSingleValue {
return resolveCodegen(expr)!!.enumFields[expr.text]!!
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: StructCodegen): LLVMSingleValue? {
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
val companionObject = (classScope as ClassCodegen).companionObjectCodegen ?: throw UnexpectedException(expr.text)
val field = companionObject.fieldsIndex[fieldName]
val receiver = variableManager[companionObject.fullName]!!
val result = codeBuilder.getNewVariable(field!!.type, pointer = 1)
codeBuilder.loadClassField(result, receiver, field.offset)
return result
}
private fun isEnumClassField(expr: KtReferenceExpression): Boolean {
val clazz = resolveCodegen(expr) ?: return false
return clazz.enumFields.containsKey(expr.text)
}
private fun resolveEnumClassField(expr: KtReferenceExpression, classScope: StructCodegen?): LLVMSingleValue =
(classScope ?: resolveCodegen(expr))!!.enumFields[expr.text]!!
private fun isEnumClassField(expr: KtReferenceExpression, classScope: StructCodegen?): Boolean =
(classScope ?: resolveCodegen(expr))?.enumFields?.containsKey(expr.text) ?: false
private fun resolveCodegen(expr: KtExpression): StructCodegen? {
val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)?.type
?: expr.getType(state.bindingContext)
?: expr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext)
val location = type?.getSubtypesPredicate()?.toString()?.split(".")
?: state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr as KtReferenceExpression)?.fqNameSafe?.toString()?.split(".")
?: return null
private fun resolveCodegen(expr: KtReferenceExpression): StructCodegen? {
val location = expr.getType(state.bindingContext)?.getSubtypesPredicate()?.toString()?.split(".") ?: return null
val name = location.last()
val classType = LLVMReferenceType(name, prefix = "class")
@@ -378,7 +374,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return resolveClassOrObjectLocation(classType)
}
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null): LLVMSingleValue? {
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? {
val names = parseArgList(expr, scopeDepth)
val name = expr.firstChild.firstChild.text
val external = state.externalFunctions.containsKey(name)
@@ -391,10 +387,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return evaluateFunctionCallExpression(LLVMVariable(function, descriptor.returnType!!.type, scope = LLVMVariableScope()), args)
}
if (state.classes.containsKey(name)) {
val descriptor = state.classes[name] ?: return null
if (state.classes.containsKey(name) || classScope?.structName == name) {
val descriptor = state.classes[name] ?: classScope ?: return null
val args = loadArgsIfRequired(names, descriptor.constructorFields)
return evaluateConstructorCallExpression(LLVMVariable(name, descriptor.type, scope = LLVMVariableScope()), args)
return evaluateConstructorCallExpression(LLVMVariable(descriptor.fullName, descriptor.type, scope = LLVMVariableScope()), args)
}
val localFunction = variableManager[name]
@@ -405,10 +401,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
if (classScope != null) {
val classDescriptor = classScope.parentCodegen
val methodShortName = classDescriptor?.structName + "." + function
if (classDescriptor != null && classDescriptor.companionMethods.containsKey(methodShortName)) {
val descriptor = classDescriptor.companionMethods[methodShortName] ?: return null
val methodShortName = classScope.structName + "." + function
if (classScope != null && classScope.methods.containsKey(methodShortName)) {
val descriptor = classScope.methods[methodShortName] ?: return null
val parentDescriptor = descriptor.parentCodegen!!
val receiver = variableManager[parentDescriptor.fullName]!!
val methodFullName = descriptor.name
@@ -433,7 +428,17 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
if (containingClass != null) {
val name = "${containingClass.fullName}.$function"
val method = containingClass.methods[name]!!
val args = mutableListOf<LLVMSingleValue>(variableManager["this"]!!)
val args = mutableListOf<LLVMSingleValue>()
val leftName = (expr.context as? KtDotQualifiedExpression)?.receiverExpression?.text
if (caller != null) {
args.add(caller)
} else if (variableManager[containingClass.fullName] != null) {
args.add(variableManager[containingClass.fullName]!!)
} else {
args.add(variableManager["this"]!!)
}
args.addAll(loadArgsIfRequired(names, method.args))
return evaluateFunctionCallExpression(LLVMVariable(method.fullName, method.returnType?.type ?: LLVMVoidType(), scope = LLVMVariableScope()), args)
@@ -860,7 +865,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.addUnconditionalJump(if (checkConditionBeforeExecute) conditionLabel else bodyLabel)
codeBuilder.markWithLabel(conditionLabel)
val conditionResult = evaluateExpression(condition, scopeDepth + 1)!!
var conditionResult = evaluateExpression(condition, scopeDepth + 1)!!
while (conditionResult.pointer > 0) {
conditionResult = codeBuilder.loadAndGetVariable(conditionResult as LLVMVariable)
}
codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel)
evaluateCodeBlock(bodyExpression, bodyLabel, conditionLabel, scopeDepth + 1)
@@ -84,19 +84,7 @@ class ClassCodegen(state: TranslationState,
nestedClasses.forEach { x, classCodegen -> classCodegen.generate() }
if (companionObjectCodegen != null) {
val companionObject = clazz.getCompanionObjects().first()
val companionObjectName = structName + "." + companionObject.name
companionObjectCodegen!!.generate()
for ((key, value) in companionObjectCodegen!!.methods) {
val methodName = key.removePrefix(companionObjectName + ".")
companionMethods.put(structName + "." + methodName, value)
}
companionFields.addAll(companionObjectCodegen!!.fields)
for (field in companionObjectCodegen!!.fields) {
companionFieldsSource.put(field.label, companionObjectCodegen!!)
}
companionFieldsIndex.putAll(companionObjectCodegen!!.fieldsIndex)
}
}
@@ -37,6 +37,7 @@ class FunctionCodegen(state: TranslationState,
returnType = LLVMInstanceOfStandardType("instance", descriptor.returnType!!)
if (returnType!!.type is LLVMReferenceType) {
(returnType!!.type as LLVMReferenceType).location.addAll(descriptor.returnType!!.getSubtypesPredicate().toString().split(".").dropLast(1))
returnType!!.pointer = 2
}
external = isExternal()
name = "${function.fqName}${if (args.size > 0 && !external) "_${args.joinToString(separator = "_", transform = { it.type.mangle() })}" else ""}"
@@ -23,10 +23,6 @@ abstract class StructCodegen(val state: TranslationState,
val fields = ArrayList<LLVMVariable>()
val fieldsIndex = HashMap<String, LLVMClassVariable>()
val nestedClasses = HashMap<String, ClassCodegen>()
val companionMethods = HashMap<String, FunctionCodegen>()
val companionFields = ArrayList<LLVMVariable>()
val companionFieldsIndex = HashMap<String, LLVMClassVariable>()
val companionFieldsSource = HashMap<String, ObjectCodegen>()
val enumFields = HashMap<String, LLVMVariable>()
val constructorFields = ArrayList<LLVMVariable>()
@@ -3,7 +3,6 @@ package org.kotlinnative.translator.llvm.types
import org.kotlinnative.translator.exceptions.UnimplementedException
import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.LLVMVariable
abstract class LLVMType() : Cloneable {
@@ -0,0 +1 @@
enum_complex_test1() == 0
@@ -1,5 +1,5 @@
class companion_object_1 {
companion object Factory {
companion object {
val fieldCompanion: Int = 5790
fun create(): Int {
@@ -1,5 +1,5 @@
class companion_object_2 {
companion object Factory {
companion object {
var fieldCompanion: Int = 5790
fun create(): Int {
@@ -0,0 +1,20 @@
class Holder() {
enum class nested(val id: Int) {
FIRST(0),
SECOND(1),
THIRD(3);
companion object {
fun functor(ord: Int): Int {
return nested.FIRST.id
}
}
}
}
fun enum_complex_test1(): Int {
val h = Holder()
return 0
}