translator: fix class class arguments, fix computing class size

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