translator: fix class class arguments, fix computing class size
This commit is contained in:
@@ -121,7 +121,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
|
||||
private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? {
|
||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||
val result = LLVMInstanceOfStandardType(expr.text.substring(2), kotlinType, LLVMVariableScope())
|
||||
val result = LLVMInstanceOfStandardType(expr.text.substring(2), kotlinType, LLVMVariableScope(), state)
|
||||
return LLVMVariable("${result.label}${(result.type as LLVMFunctionType).mangleArgs()}", result.type, result.kotlinName, result.scope, result.pointer)
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
|
||||
val left = evaluateExpression(receiver, scopeDepth)!!
|
||||
val loadedLeft = codeBuilder.receiveNativeValue(left)
|
||||
val expectedType = LLVMMapStandardType(state.bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expr)!!) as LLVMReferenceType
|
||||
val expectedType = LLVMMapStandardType(state.bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expr)!!, state) as LLVMReferenceType
|
||||
|
||||
if (state.classes.containsKey(expectedType.type)) {
|
||||
expectedType.prefix = "class"
|
||||
@@ -223,7 +223,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
|
||||
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!!)
|
||||
val standardType = LLVMMapStandardType(receiverType!!.type!!, state)
|
||||
|
||||
val function = selector.firstChild.firstChild.text
|
||||
val names = parseArgList(selector, scopeDepth)
|
||||
@@ -809,7 +809,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant {
|
||||
val expressionKotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||
val expressionValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)?.getValue(expressionKotlinType)
|
||||
val type = LLVMMapStandardType(expressionKotlinType)
|
||||
val type = LLVMMapStandardType(expressionKotlinType, state)
|
||||
return LLVMConstant(expressionValue?.toString() ?: "", type, pointer = 0)
|
||||
}
|
||||
|
||||
@@ -866,7 +866,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
codeBuilder.addComment("start when expression")
|
||||
val whenExpression = expr.subjectExpression
|
||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||
val expressionType = LLVMMapStandardType(kotlinType)
|
||||
val expressionType = LLVMMapStandardType(kotlinType, state)
|
||||
|
||||
val targetExpression = evaluateExpression(whenExpression, scopeDepth + 1)!!
|
||||
val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1)
|
||||
@@ -925,7 +925,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
|
||||
private fun executeIfExpression(conditionResult: LLVMSingleValue, thenExpression: KtExpression, elseExpression: PsiElement?, ifExpression: KtIfExpression, scopeDepth: Int): LLVMVariable? {
|
||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, ifExpression)!!.type!!
|
||||
val expressionType = LLVMInstanceOfStandardType("type", kotlinType, LLVMVariableScope()).type
|
||||
val expressionType = LLVMInstanceOfStandardType("type", kotlinType, LLVMVariableScope(), state).type
|
||||
val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1)
|
||||
codeBuilder.allocStackPointedVarAsValue(resultVariable)
|
||||
val thenLabel = codeBuilder.getNewLabel(prefix = "if")
|
||||
@@ -988,7 +988,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
}
|
||||
is LLVMConstant -> {
|
||||
if (assignExpression.type is LLVMNullType) {
|
||||
val reference = LLVMInstanceOfStandardType(identifier, variable.type)
|
||||
val reference = LLVMInstanceOfStandardType(identifier, variable.type, state = state)
|
||||
if (state.classes.containsKey(variable.type.toString().dropLast(1))) {
|
||||
(reference.type as LLVMReferenceType).prefix = "class"
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ class ClassCodegen(state: TranslationState,
|
||||
override val type: LLVMReferenceType
|
||||
|
||||
init {
|
||||
type = LLVMReferenceType(structName, "class", byRef = true)
|
||||
type = LLVMReferenceType(structName, "class", align = state.pointerAllign, size = state.pointerSize, byRef = true)
|
||||
if (parentCodegen != null) {
|
||||
type.location.addAll(parentCodegen.type.location)
|
||||
type.location.add(parentCodegen.structName)
|
||||
@@ -41,7 +41,9 @@ class ClassCodegen(state: TranslationState,
|
||||
indexFields(parameterList)
|
||||
generateInnerFields(clazz.declarations)
|
||||
|
||||
calculateTypeSize()
|
||||
type.size = size
|
||||
type.align = state.pointerAllign
|
||||
}
|
||||
|
||||
private fun indexFields(parameters: MutableList<KtParameter>) {
|
||||
@@ -49,8 +51,6 @@ class ClassCodegen(state: TranslationState,
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (field in parameters) {
|
||||
val item = resolveType(field, state.bindingContext.get(BindingContext.TYPE, field.typeReference)!!)
|
||||
item.offset = fields.size
|
||||
@@ -59,18 +59,6 @@ class ClassCodegen(state: TranslationState,
|
||||
fields.add(item)
|
||||
fieldsIndex[item.label] = item
|
||||
}
|
||||
val classAlignment = fields.map { it.type.size }.max()?.toInt() ?: 0
|
||||
var alignmentRemainder = 0
|
||||
|
||||
for (item in fields) {
|
||||
alignmentRemainder = alignmentRemainder - (alignmentRemainder % item.type.size)
|
||||
if (alignmentRemainder < item.type.size) {
|
||||
size += classAlignment
|
||||
alignmentRemainder = classAlignment - item.type.size
|
||||
} else {
|
||||
alignmentRemainder -= item.type.size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun prepareForGenerate() {
|
||||
|
||||
@@ -30,10 +30,10 @@ class FunctionCodegen(state: TranslationState,
|
||||
init {
|
||||
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
|
||||
args.addAll(descriptor.valueParameters.map {
|
||||
LLVMInstanceOfStandardType(it.name.toString(), it.type)
|
||||
LLVMInstanceOfStandardType(it.name.toString(), it.type, state = state)
|
||||
})
|
||||
|
||||
returnType = LLVMInstanceOfStandardType("instance", descriptor.returnType!!)
|
||||
returnType = LLVMInstanceOfStandardType("instance", descriptor.returnType!!, state = state)
|
||||
if (returnType!!.type is LLVMReferenceType) {
|
||||
returnType!!.pointer = 2
|
||||
}
|
||||
@@ -42,7 +42,7 @@ class FunctionCodegen(state: TranslationState,
|
||||
|
||||
if (isExtensionDeclaration) {
|
||||
val receiverType = descriptor.extensionReceiverParameter!!.type
|
||||
val translatorType = LLVMMapStandardType(receiverType)
|
||||
val translatorType = LLVMMapStandardType(receiverType, state)
|
||||
functionNamePrefix += translatorType.typename + "."
|
||||
|
||||
val extensionFunctionsOfThisType = state.extensionFunctions.getOrDefault(translatorType.toString(), HashMap())
|
||||
@@ -95,7 +95,7 @@ class FunctionCodegen(state: TranslationState,
|
||||
if (isExtensionDeclaration) {
|
||||
val receiverParameter = state.bindingContext.get(BindingContext.FUNCTION, function)!!.extensionReceiverParameter!!
|
||||
val receiverType = receiverParameter.type
|
||||
val translatorType = LLVMMapStandardType(receiverType)
|
||||
val translatorType = LLVMMapStandardType(receiverType, state)
|
||||
|
||||
val classVal = when (translatorType) {
|
||||
is LLVMReferenceType -> LLVMVariable("classvariable.this", translatorType, pointer = 1)
|
||||
|
||||
@@ -20,12 +20,16 @@ class ObjectCodegen(state: TranslationState,
|
||||
override val type: LLVMReferenceType
|
||||
|
||||
init {
|
||||
type = LLVMReferenceType(structName, "class", byRef = true)
|
||||
type = LLVMReferenceType(structName, "class", align = state.pointerAllign, size = state.pointerSize, byRef = true)
|
||||
if (parentCodegen != null) {
|
||||
type.location.addAll(parentCodegen.type.location)
|
||||
type.location.add(parentCodegen.structName)
|
||||
}
|
||||
generateInnerFields(objectDeclaration.declarations)
|
||||
|
||||
calculateTypeSize()
|
||||
type.size = size
|
||||
type.align = state.pointerAllign
|
||||
}
|
||||
|
||||
override fun prepareForGenerate() {
|
||||
@@ -35,7 +39,7 @@ class ObjectCodegen(state: TranslationState,
|
||||
codeBuilder.addGlobalInitialize(classInstance, fields, initializedFields.map {
|
||||
val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, it.value)!!.type!!
|
||||
Pair(it.key, state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, it.value)!!.getValue(type).toString())
|
||||
}.toMap() , type)
|
||||
}.toMap(), type)
|
||||
variableManager.addGlobalVariable(fullName, classInstance)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class PropertyCodegen(val state: TranslationState, val variableManager: Variable
|
||||
val kotlinType = varInfo.type
|
||||
val value = varInfo.value
|
||||
if (kotlinType.nameIfStandardType != null) {
|
||||
val variableType = LLVMInstanceOfStandardType(property.name ?: return, kotlinType).type
|
||||
val variableType = LLVMInstanceOfStandardType(property.name ?: return, kotlinType, state = state).type
|
||||
val variable = LLVMVariable(property.name.toString(), variableType, property.name.toString(), LLVMVariableScope())
|
||||
variableManager.addGlobalVariable(property.name.toString(), variable)
|
||||
codeBuilder.defineGlobalVariable(variable, variableType.parseArg(value.toString()))
|
||||
|
||||
@@ -47,6 +47,23 @@ abstract class StructCodegen(val state: TranslationState,
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateTypeSize() {
|
||||
val classAlignment = fields.map { it.type.align }.max()?.toInt() ?: 0
|
||||
var alignmentRemainder = 0
|
||||
size = 0
|
||||
|
||||
for (item in fields) {
|
||||
val currentFieldType = if (item.pointer > 0) state.pointerSize else item.type.size
|
||||
alignmentRemainder -= (alignmentRemainder % currentFieldType)
|
||||
if (alignmentRemainder < currentFieldType) {
|
||||
size += classAlignment
|
||||
alignmentRemainder = classAlignment - currentFieldType
|
||||
} else {
|
||||
alignmentRemainder -= currentFieldType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun generate() {
|
||||
generateEnumFields()
|
||||
generatePrimaryConstructor()
|
||||
@@ -76,7 +93,6 @@ abstract class StructCodegen(val state: TranslationState,
|
||||
}
|
||||
fields.add(field)
|
||||
fieldsIndex[field.label] = field
|
||||
size += field.type.size
|
||||
}
|
||||
is KtEnumEntry -> {
|
||||
val name = declaration.name!!
|
||||
@@ -192,7 +208,7 @@ abstract class StructCodegen(val state: TranslationState,
|
||||
protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType): LLVMClassVariable {
|
||||
val annotations = parseFieldAnnotations(field)
|
||||
|
||||
val result = LLVMInstanceOfStandardType(field.name!!, ktType, LLVMRegisterScope())
|
||||
val result = LLVMInstanceOfStandardType(field.name!!, ktType, LLVMRegisterScope(), state = state)
|
||||
|
||||
if (result.type is LLVMReferenceType) {
|
||||
val type = result.type as LLVMReferenceType
|
||||
@@ -200,6 +216,11 @@ abstract class StructCodegen(val state: TranslationState,
|
||||
type.byRef = true
|
||||
}
|
||||
|
||||
if (state.classes.containsKey(field.name!!)) {
|
||||
return LLVMClassVariable(result.label, state.classes[field.name!!]!!.type, result.pointer)
|
||||
}
|
||||
|
||||
|
||||
if (annotations.contains("Plain")) {
|
||||
result.pointer = 0
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ class TranslationState(val environment: KotlinCoreEnvironment, val bindingContex
|
||||
var objects = HashMap<String, ObjectCodegen>()
|
||||
var properties = HashMap<String, PropertyCodegen>()
|
||||
val codeBuilder = LLVMBuilder(arm)
|
||||
val pointerAllign = if (arm) 4 else 8
|
||||
val pointerSize = if (arm) 4 else 8
|
||||
val extensionFunctions = HashMap<String, HashMap<String, FunctionCodegen>>()
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.getSubtypesPredicate
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
|
||||
|
||||
@@ -14,8 +15,8 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnTy
|
||||
"${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).byRef) "byval" else ""} %${s.label}"
|
||||
}?.joinToString()}) #0"
|
||||
|
||||
fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope()): LLVMVariable = when {
|
||||
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type), name, scope, pointer = 1)
|
||||
fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable = when {
|
||||
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1)
|
||||
type.toString() == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope)
|
||||
type.toString() == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope)
|
||||
type.toString() == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope)
|
||||
@@ -29,12 +30,12 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope
|
||||
type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope)
|
||||
type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(type.toString().dropLast(1), prefix = "class"), name, scope, pointer = 1)
|
||||
else -> {
|
||||
val refType = LLVMReferenceType(type.toString(), prefix = "class")
|
||||
val refType = state.classes[type.toString()]!!.type
|
||||
val result = LLVMVariable(name, refType, name, scope, pointer = 1)
|
||||
refType.location.addAll(type.getSubtypesPredicate().toString().split(".").dropLast(1))
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fun LLVMMapStandardType(type: KotlinType): LLVMType =
|
||||
LLVMInstanceOfStandardType("type", type, LLVMRegisterScope()).type
|
||||
fun LLVMMapStandardType(type: KotlinType, state: TranslationState): LLVMType =
|
||||
LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type
|
||||
|
||||
+3
-2
@@ -1,10 +1,11 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.llvm.LLVMInstanceOfStandardType
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
|
||||
class LLVMFunctionType(type: KotlinType) : LLVMType() {
|
||||
class LLVMFunctionType(type: KotlinType, state: TranslationState) : LLVMType() {
|
||||
|
||||
override val defaultValue = ""
|
||||
override val align: Int = 4
|
||||
@@ -14,7 +15,7 @@ class LLVMFunctionType(type: KotlinType) : LLVMType() {
|
||||
val returnType: LLVMVariable
|
||||
|
||||
init {
|
||||
val types = type.arguments.map { LLVMInstanceOfStandardType("", it.type) }.toList()
|
||||
val types = type.arguments.map { LLVMInstanceOfStandardType("", it.type, state = state) }.toList()
|
||||
returnType = types.last()
|
||||
arguments = types.dropLast(1)
|
||||
}
|
||||
|
||||
+1
-2
@@ -4,11 +4,10 @@ import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
import java.util.*
|
||||
|
||||
class LLVMReferenceType(val type: String, var prefix: String = "", override val align: Int = 4, var byRef: Boolean = true) : LLVMType() {
|
||||
class LLVMReferenceType(val type: String, var prefix: String = "", override var align: Int = 4, override var size: Int = 4, var byRef: Boolean = true) : LLVMType() {
|
||||
|
||||
override val defaultValue: String = ""
|
||||
|
||||
override var size: Int = 4
|
||||
override val typename: String
|
||||
get() = "$prefix${if (prefix.length > 0) "." else ""}${
|
||||
if (location.size > 0) "${location.joinToString(".")}." else ""
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
class_class_argument_1() == 99999
|
||||
@@ -0,0 +1,12 @@
|
||||
class class_class_argument_1_slave
|
||||
|
||||
class class_class_argument_1_master(val buffer: class_class_argument_1_slave) {
|
||||
var pos = 99999
|
||||
}
|
||||
|
||||
|
||||
fun class_class_argument_1(): Int {
|
||||
val buffer = class_class_argument_1_slave()
|
||||
val output = class_class_argument_1_master(buffer)
|
||||
return output.pos
|
||||
}
|
||||
Reference in New Issue
Block a user