translator: fix conflict name of struct, refactor StructCodegen
This commit is contained in:
@@ -35,7 +35,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
if (isBlock) {
|
if (isBlock) {
|
||||||
expressionWalker(expr, breakLabel, scopeDepth)
|
expressionWalker(expr, breakLabel, scopeDepth)
|
||||||
} else {
|
} else {
|
||||||
var result = evaluateExpression(expr, scopeDepth) ?: throw UnexpectedException(expr!!.text)
|
var result = evaluateExpression(expr, scopeDepth) ?: throw UnexpectedException("Can't evaluate expression " + expr!!.text)
|
||||||
when (result) {
|
when (result) {
|
||||||
is LLVMVariable -> {
|
is LLVMVariable -> {
|
||||||
if (result.pointer == 1 && result.type !is LLVMReferenceType) {
|
if (result.pointer == 1 && result.type !is LLVMReferenceType) {
|
||||||
@@ -57,12 +57,12 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
|
|
||||||
private fun expressionWalker(expr: PsiElement?, breakLabel: LLVMLabel?, scopeDepth: Int) {
|
private fun expressionWalker(expr: PsiElement?, breakLabel: LLVMLabel?, scopeDepth: Int) {
|
||||||
when (expr) {
|
when (expr) {
|
||||||
is KtBlockExpression -> expressionWalker(expr.firstChild, breakLabel, scopeDepth + 1)
|
is KtBlockExpression -> expressionWalker(expr.lBrace, breakLabel, scopeDepth + 1)
|
||||||
is KtProperty -> evaluateValExpression(expr, scopeDepth)
|
is KtProperty -> evaluateValExpression(expr, scopeDepth)
|
||||||
is KtPostfixExpression -> evaluatePostfixExpression(expr, scopeDepth)
|
is KtPostfixExpression -> evaluatePostfixExpression(expr, scopeDepth)
|
||||||
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
||||||
is KtCallExpression -> evaluateCallExpression(expr, scopeDepth)
|
is KtCallExpression -> evaluateCallExpression(expr, scopeDepth)
|
||||||
is KtDoWhileExpression -> evaluateDoWhileExpression(expr.firstChild, scopeDepth + 1)
|
is KtDoWhileExpression -> evaluateDoWhileExpression(expr, scopeDepth + 1)
|
||||||
is KtBreakExpression -> evaluateBreakExpression(breakLabel!!)
|
is KtBreakExpression -> evaluateBreakExpression(breakLabel!!)
|
||||||
is KtDotQualifiedExpression -> evaluateDotExpression(expr, scopeDepth)
|
is KtDotQualifiedExpression -> evaluateDotExpression(expr, scopeDepth)
|
||||||
is KtWhenExpression -> evaluateWhenExpression(expr, scopeDepth)
|
is KtWhenExpression -> evaluateWhenExpression(expr, scopeDepth)
|
||||||
@@ -77,19 +77,17 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
expressionWalker(expr.getNextSiblingIgnoringWhitespaceAndComments(), breakLabel, scopeDepth)
|
expressionWalker(expr.getNextSiblingIgnoringWhitespaceAndComments(), breakLabel, scopeDepth)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateBreakExpression(breakLabel: LLVMLabel) {
|
private fun evaluateBreakExpression(breakLabel: LLVMLabel) =
|
||||||
codeBuilder.addUnconditionalJump(breakLabel)
|
codeBuilder.addUnconditionalJump(breakLabel)
|
||||||
}
|
|
||||||
|
private fun evaluateDoWhileExpression(expr: KtDoWhileExpression, scopeDepth: Int) =
|
||||||
|
executeWhileBlock(expr.condition!!, expr.body!!, scopeDepth, checkConditionBeforeExecute = false)
|
||||||
|
|
||||||
private fun evaluateDoWhileExpression(element: PsiElement, scopeDepth: Int) {
|
|
||||||
val expr = element.context as KtDoWhileExpression
|
|
||||||
executeWhileBlock(expr.condition!!, expr.body!!, scopeDepth, checkConditionBeforeExecute = false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? {
|
fun evaluateExpression(expr: PsiElement?, scopeDepth: Int): LLVMSingleValue? {
|
||||||
return when (expr) {
|
return when (expr) {
|
||||||
is KtBlockExpression -> {
|
is KtBlockExpression -> {
|
||||||
expressionWalker(expr.firstChild, breakLabel = null, scopeDepth = scopeDepth + 1)
|
expressionWalker(expr.lBrace, breakLabel = null, scopeDepth = scopeDepth + 1)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
is KtBinaryExpression -> evaluateBinaryExpression(expr, scopeDepth)
|
||||||
@@ -118,7 +116,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
val targetCall = state.bindingContext.get(BindingContext.CALL, expr)
|
val targetCall = state.bindingContext.get(BindingContext.CALL, expr)
|
||||||
val names = parseValueArguments(targetCall!!.valueArguments, scopeDepth)
|
val names = parseValueArguments(targetCall!!.valueArguments, scopeDepth)
|
||||||
val args = codeBuilder.loadArgsIfRequired(names, constructorArguments)
|
val args = codeBuilder.loadArgsIfRequired(names, constructorArguments)
|
||||||
return evaluateConstructorCallExpression(LLVMVariable(structCodegen.fullName + LLVMType.mangleFunctionArguments(names), structCodegen.type, scope = LLVMVariableScope()), args)
|
return evaluateConstructorCallExpression(LLVMVariable(structCodegen.structName + LLVMType.mangleFunctionArguments(names), structCodegen.type, scope = LLVMVariableScope()), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateThisExpression(): LLVMSingleValue? =
|
private fun evaluateThisExpression(): LLVMSingleValue? =
|
||||||
@@ -169,8 +167,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
codeBuilder.addUnconditionalJump(endLabel)
|
codeBuilder.addUnconditionalJump(endLabel)
|
||||||
|
|
||||||
codeBuilder.markWithLabel(elseLabel)
|
codeBuilder.markWithLabel(elseLabel)
|
||||||
val right = evaluateDotBody(receiver, selector!!, scopeDepth)
|
val right = evaluateDotBody(receiver, selector!!, scopeDepth) as LLVMVariable
|
||||||
val rightLoaded = codeBuilder.loadAndGetVariable(right as LLVMVariable)
|
val rightLoaded = codeBuilder.loadAndGetVariable(right)
|
||||||
codeBuilder.storeVariable(result, rightLoaded)
|
codeBuilder.storeVariable(result, rightLoaded)
|
||||||
codeBuilder.addUnconditionalJump(endLabel)
|
codeBuilder.addUnconditionalJump(endLabel)
|
||||||
|
|
||||||
@@ -234,7 +232,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
|
|
||||||
val clazz = resolveCodegen(receiverExpr)
|
val clazz = resolveCodegen(receiverExpr)
|
||||||
?: return evaluateExtensionExpression(receiverExpr, receiver, selectorExpr as? KtCallExpression
|
?: return evaluateExtensionExpression(receiverExpr, receiver, selectorExpr as? KtCallExpression
|
||||||
?: throw UnexpectedException(selectorExpr.text), scopeDepth)
|
?: throw UnexpectedException("Failed evaluate dot expression: " + selectorExpr.text), scopeDepth)
|
||||||
return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth, receiver)
|
return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth, receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,11 +279,19 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
val field = clazz.fieldsIndex[selectorName]
|
val field = clazz.fieldsIndex[selectorName]
|
||||||
|
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
val result = codeBuilder.getNewVariable(field.type, pointer = field.pointer + 1)
|
return evaluateClassField(receiver, field)
|
||||||
codeBuilder.loadClassField(result, receiver, field.offset)
|
} else {
|
||||||
return result
|
return evaluateMemberMethod(receiver, selectorName, clazz, scopeDepth, call)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun evaluateClassField(receiver: LLVMVariable, field: LLVMClassVariable): LLVMVariable {
|
||||||
|
val result = codeBuilder.getNewVariable(field.type, pointer = field.pointer + 1)
|
||||||
|
codeBuilder.loadClassField(result, receiver, field.offset)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun evaluateMemberMethod(receiver: LLVMVariable, selectorName: String, clazz: StructCodegen, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? {
|
||||||
(call as? KtCallExpression) ?: throw UnexpectedException("$receiver:$selectorName")
|
(call as? KtCallExpression) ?: throw UnexpectedException("$receiver:$selectorName")
|
||||||
val resolvedCall = (call as KtCallExpression).getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext)
|
val resolvedCall = (call as KtCallExpression).getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext)
|
||||||
val functionDescriptor = resolvedCall.candidateDescriptor
|
val functionDescriptor = resolvedCall.candidateDescriptor
|
||||||
@@ -363,7 +369,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
|
|
||||||
return evaluateFunctionCallExpression(LLVMVariable(methodName, returnType, scope = LLVMVariableScope()), callArgs)
|
return evaluateFunctionCallExpression(LLVMVariable(methodName, returnType, scope = LLVMVariableScope()), callArgs)
|
||||||
}
|
}
|
||||||
else -> throw IllegalStateException("Unknown array access method")
|
else -> throw UnexpectedException("Unknown array access method")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@@ -386,7 +392,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(expr, classScope.parentCodegen!!)
|
((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(expr, classScope.parentCodegen!!)
|
||||||
else -> {
|
else -> {
|
||||||
val clazz = classScope ?: resolveCodegen(expr)
|
val clazz = classScope ?: resolveCodegen(expr)
|
||||||
val receiver = if (clazz != null) variableManager[clazz.fullName] ?: variableManager["this"] else variableManager["this"]
|
val receiver = if (clazz != null) variableManager[clazz.structName] ?: variableManager["this"] else variableManager["this"]
|
||||||
targetName ?: throw RuntimeException(expr.firstChild.text)
|
targetName ?: throw RuntimeException(expr.firstChild.text)
|
||||||
evaluateMemberMethodOrField(receiver ?: throw UnexpectedException(targetName), targetName, topLevel)
|
evaluateMemberMethodOrField(receiver ?: throw UnexpectedException(targetName), targetName, topLevel)
|
||||||
}
|
}
|
||||||
@@ -398,7 +404,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
|
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
|
||||||
val companionObject = (classScope as ClassCodegen).companionObjectCodegen ?: throw UnexpectedException(expr.text)
|
val companionObject = (classScope as ClassCodegen).companionObjectCodegen ?: throw UnexpectedException(expr.text)
|
||||||
val field = companionObject.fieldsIndex[fieldName] ?: return null
|
val field = companionObject.fieldsIndex[fieldName] ?: return null
|
||||||
val receiver = variableManager[companionObject.fullName]!!
|
val receiver = variableManager[companionObject.structName]!!
|
||||||
val result = codeBuilder.getNewVariable(field.type, pointer = 1)
|
val result = codeBuilder.getNewVariable(field.type, pointer = 1)
|
||||||
|
|
||||||
codeBuilder.loadClassField(result, receiver, field.offset)
|
codeBuilder.loadClassField(result, receiver, field.offset)
|
||||||
@@ -453,7 +459,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
val descriptor = state.classes[targetFunctionName] ?: classScope ?: return null
|
val descriptor = state.classes[targetFunctionName] ?: classScope ?: return null
|
||||||
val detectedConstructor = LLVMType.mangleFunctionTypes(functionArguments)
|
val detectedConstructor = LLVMType.mangleFunctionTypes(functionArguments)
|
||||||
val args = codeBuilder.loadArgsIfRequired(names, descriptor.constructorFields[detectedConstructor]!!)
|
val args = codeBuilder.loadArgsIfRequired(names, descriptor.constructorFields[detectedConstructor]!!)
|
||||||
return evaluateConstructorCallExpression(LLVMVariable(descriptor.fullName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), args)
|
return evaluateConstructorCallExpression(LLVMVariable(descriptor.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
val localFunction = variableManager[targetFunctionName]
|
val localFunction = variableManager[targetFunctionName]
|
||||||
@@ -464,11 +470,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (classScope != null) {
|
if (classScope != null) {
|
||||||
val methodShortName = function
|
if (classScope.methods.containsKey(function)) {
|
||||||
if (classScope.methods.containsKey(methodShortName)) {
|
val descriptor = classScope.methods[function]!!
|
||||||
val descriptor = classScope.methods[methodShortName]!!
|
|
||||||
val parentDescriptor = descriptor.parentCodegen!!
|
val parentDescriptor = descriptor.parentCodegen!!
|
||||||
val receiver = variableManager[parentDescriptor.fullName] ?: throw UnexpectedException(parentDescriptor.fullName)
|
val receiver = variableManager[parentDescriptor.structName] ?: throw UnexpectedException(parentDescriptor.structName)
|
||||||
val methodFullName = descriptor.name
|
val methodFullName = descriptor.name
|
||||||
val returnType = descriptor.returnType!!.type
|
val returnType = descriptor.returnType!!.type
|
||||||
val loadedArgs = codeBuilder.loadArgsIfRequired(names, descriptor.args)
|
val loadedArgs = codeBuilder.loadArgsIfRequired(names, descriptor.args)
|
||||||
@@ -482,7 +487,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text)
|
val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text)
|
||||||
if (nestedConstructor != null) {
|
if (nestedConstructor != null) {
|
||||||
val args = codeBuilder.loadArgsIfRequired(names, nestedConstructor.constructorFields[nestedConstructor.primaryConstructorIndex]!!)
|
val args = codeBuilder.loadArgsIfRequired(names, nestedConstructor.constructorFields[nestedConstructor.primaryConstructorIndex]!!)
|
||||||
return evaluateConstructorCallExpression(LLVMVariable(nestedConstructor.fullName, nestedConstructor.type, scope = LLVMVariableScope()), args)
|
return evaluateConstructorCallExpression(LLVMVariable(nestedConstructor.structName, nestedConstructor.type, scope = LLVMVariableScope()), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
val containingClass = resolveContainingClass(expr) ?: return null
|
val containingClass = resolveContainingClass(expr) ?: return null
|
||||||
@@ -491,8 +496,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
|
|
||||||
if (caller != null) {
|
if (caller != null) {
|
||||||
args.add(caller)
|
args.add(caller)
|
||||||
} else if (variableManager[containingClass.fullName] != null) {
|
} else if (variableManager[containingClass.structName] != null) {
|
||||||
args.add(variableManager[containingClass.fullName]!!)
|
args.add(variableManager[containingClass.structName]!!)
|
||||||
} else {
|
} else {
|
||||||
args.add(variableManager["this"]!!)
|
args.add(variableManager["this"]!!)
|
||||||
}
|
}
|
||||||
@@ -748,7 +753,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
val descriptor = state.classes["kotlin.ranges.IntRange"]
|
val descriptor = state.classes["kotlin.ranges.IntRange"]
|
||||||
val arguments = listOf(firstOp, secondNativeOp)
|
val arguments = listOf(firstOp, secondNativeOp)
|
||||||
val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type })
|
val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type })
|
||||||
val result = evaluateConstructorCallExpression(LLVMVariable(descriptor!!.fullName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), arguments)
|
val result = evaluateConstructorCallExpression(LLVMVariable(descriptor!!.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), arguments)
|
||||||
return LLVMExpression(result!!.type, "load ${descriptor.type}** $result, align ${descriptor.type.align}", pointer = 1)
|
return LLVMExpression(result!!.type, "load ${descriptor.type}** $result, align ${descriptor.type.align}", pointer = 1)
|
||||||
}
|
}
|
||||||
else -> throw UnsupportedOperationException("Unknown binary operator: $operator(${firstNativeOp.type}, ${secondNativeOp.type})")
|
else -> throw UnsupportedOperationException("Unknown binary operator: $operator(${firstNativeOp.type}, ${secondNativeOp.type})")
|
||||||
|
|||||||
@@ -7,10 +7,8 @@ import org.jetbrains.kotlin.psi.KtParameter
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.kotlinnative.translator.exceptions.TranslationException
|
import org.kotlinnative.translator.exceptions.TranslationException
|
||||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class ClassCodegen(state: TranslationState,
|
class ClassCodegen(state: TranslationState,
|
||||||
variableManager: VariableManager,
|
variableManager: VariableManager,
|
||||||
@@ -30,7 +28,6 @@ class ClassCodegen(state: TranslationState,
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
|
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
|
||||||
|
|
||||||
descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException("Can't receive descriptor of class " + clazz.name)
|
descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException("Can't receive descriptor of class " + clazz.name)
|
||||||
|
|
||||||
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
|
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
|
||||||
@@ -43,15 +40,10 @@ class ClassCodegen(state: TranslationState,
|
|||||||
if (annotation) {
|
if (annotation) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val currentConstructorFields = ArrayList<LLVMVariable>()
|
|
||||||
for (field in parameters) {
|
|
||||||
val item = resolveType(field, state.bindingContext.get(BindingContext.TYPE, field.typeReference)!!)
|
|
||||||
item.offset = fields.size
|
|
||||||
|
|
||||||
currentConstructorFields.add(item)
|
val currentConstructorFields = parameters.mapIndexed { i, it -> resolveType(it, state.bindingContext.get(BindingContext.TYPE, it.typeReference)!!, fields.size + i) }
|
||||||
fields.add(item)
|
fields.addAll(currentConstructorFields)
|
||||||
fieldsIndex[item.label] = item
|
fieldsIndex.putAll(currentConstructorFields.map { Pair(it.label, it) })
|
||||||
}
|
|
||||||
primaryConstructorIndex = LLVMType.mangleFunctionArguments(currentConstructorFields)
|
primaryConstructorIndex = LLVMType.mangleFunctionArguments(currentConstructorFields)
|
||||||
constructorFields.put(primaryConstructorIndex!!, currentConstructorFields)
|
constructorFields.put(primaryConstructorIndex!!, currentConstructorFields)
|
||||||
}
|
}
|
||||||
@@ -71,8 +63,7 @@ class ClassCodegen(state: TranslationState,
|
|||||||
super.prepareForGenerate()
|
super.prepareForGenerate()
|
||||||
nestedClasses.forEach { x, classCodegen -> classCodegen.prepareForGenerate() }
|
nestedClasses.forEach { x, classCodegen -> classCodegen.prepareForGenerate() }
|
||||||
|
|
||||||
val companionObjectDescriptor = descriptor.companionObjectDescriptor
|
if (descriptor.companionObjectDescriptor != null) {
|
||||||
if (companionObjectDescriptor != null) {
|
|
||||||
val companionObject = clazz.getCompanionObjects().first()
|
val companionObject = clazz.getCompanionObjects().first()
|
||||||
companionObjectCodegen = ObjectCodegen(state, variableManager, companionObject, codeBuilder, this)
|
companionObjectCodegen = ObjectCodegen(state, variableManager, companionObject, codeBuilder, this)
|
||||||
companionObjectCodegen!!.prepareForGenerate()
|
companionObjectCodegen!!.prepareForGenerate()
|
||||||
@@ -86,10 +77,7 @@ class ClassCodegen(state: TranslationState,
|
|||||||
|
|
||||||
super.generate()
|
super.generate()
|
||||||
nestedClasses.forEach { x, classCodegen -> classCodegen.generate() }
|
nestedClasses.forEach { x, classCodegen -> classCodegen.generate() }
|
||||||
|
companionObjectCodegen?.generate()
|
||||||
if (companionObjectCodegen != null) {
|
|
||||||
companionObjectCodegen!!.generate()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -14,13 +14,14 @@ class ObjectCodegen(state: TranslationState,
|
|||||||
codeBuilder: LLVMBuilder,
|
codeBuilder: LLVMBuilder,
|
||||||
parentCodegen: StructCodegen? = null) :
|
parentCodegen: StructCodegen? = null) :
|
||||||
StructCodegen(state, variableManager, objectDeclaration, codeBuilder, parentCodegen) {
|
StructCodegen(state, variableManager, objectDeclaration, codeBuilder, parentCodegen) {
|
||||||
|
|
||||||
override var size: Int = 0
|
override var size: Int = 0
|
||||||
override val structName: String = objectDeclaration.fqName?.asString()!!
|
override val structName: String = objectDeclaration.fqName?.asString()!!
|
||||||
override val type: LLVMReferenceType
|
override val type: LLVMReferenceType
|
||||||
|
|
||||||
init {
|
init {
|
||||||
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
|
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
|
||||||
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
|
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
|
||||||
constructorFields.put(primaryConstructorIndex!!, arrayListOf())
|
constructorFields.put(primaryConstructorIndex!!, arrayListOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,15 +33,12 @@ class ObjectCodegen(state: TranslationState,
|
|||||||
|
|
||||||
super.prepareForGenerate()
|
super.prepareForGenerate()
|
||||||
|
|
||||||
val classInstance = LLVMVariable("object.instance.$fullName", type, objectDeclaration.name, LLVMVariableScope(), pointer = 1)
|
val classInstance = LLVMVariable("object.instance.$structName", type, objectDeclaration.name, LLVMVariableScope(), pointer = 1)
|
||||||
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(structName, classInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generate() {
|
}
|
||||||
super.generate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.kotlinnative.translator
|
package org.kotlinnative.translator
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
@@ -23,17 +22,14 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||||
val nestedClasses = HashMap<String, ClassCodegen>()
|
val nestedClasses = HashMap<String, ClassCodegen>()
|
||||||
val enumFields = HashMap<String, LLVMVariable>()
|
val enumFields = HashMap<String, LLVMVariable>()
|
||||||
|
val constructorFields = HashMap<String, List<LLVMVariable>>()
|
||||||
val constructorFields = HashMap<String, ArrayList<LLVMVariable>>()
|
|
||||||
var primaryConstructorIndex: String? = null
|
var primaryConstructorIndex: String? = null
|
||||||
val initializedFields = HashMap<LLVMVariable, KtExpression>()
|
val initializedFields = HashMap<LLVMVariable, KtExpression>()
|
||||||
|
var methods = HashMap<String, FunctionCodegen>()
|
||||||
|
|
||||||
abstract val type: LLVMReferenceType
|
abstract val type: LLVMReferenceType
|
||||||
abstract var size: Int
|
abstract var size: Int
|
||||||
var methods = HashMap<String, FunctionCodegen>()
|
|
||||||
abstract val structName: String
|
abstract val structName: String
|
||||||
val fullName: String
|
|
||||||
get() = structName
|
|
||||||
|
|
||||||
open fun prepareForGenerate() {
|
open fun prepareForGenerate() {
|
||||||
generateStruct()
|
generateStruct()
|
||||||
@@ -50,13 +46,13 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
size = 0
|
size = 0
|
||||||
|
|
||||||
for (item in fields) {
|
for (item in fields) {
|
||||||
val currentFieldType = if (item.pointer > 0) TranslationState.pointerSize else item.type.size
|
val currentFieldSize = if (item.pointer > 0) TranslationState.pointerAlign else item.type.align
|
||||||
alignmentRemainder -= (alignmentRemainder % currentFieldType)
|
alignmentRemainder -= (alignmentRemainder % currentFieldSize)
|
||||||
if (alignmentRemainder < currentFieldType) {
|
if (alignmentRemainder < currentFieldSize) {
|
||||||
size += classAlignment
|
size += classAlignment
|
||||||
alignmentRemainder = classAlignment - currentFieldType
|
alignmentRemainder = classAlignment - currentFieldSize
|
||||||
} else {
|
} else {
|
||||||
alignmentRemainder -= currentFieldType
|
alignmentRemainder -= currentFieldSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,47 +60,39 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
open fun generate() {
|
open fun generate() {
|
||||||
generateEnumFields()
|
generateEnumFields()
|
||||||
generatePrimaryConstructor()
|
generatePrimaryConstructor()
|
||||||
for (secondaryConstructor in classOrObject.getSecondaryConstructors()) {
|
classOrObject.getSecondaryConstructors().map { generateSecondaryConstructor(it) }
|
||||||
generateSecondaryConstructor(secondaryConstructor)
|
|
||||||
}
|
|
||||||
|
|
||||||
val classVal = LLVMVariable("classvariable.this", type, pointer = if (type.isPrimitive) 0 else 1)
|
val classVal = LLVMVariable("classvariable.this", type, pointer = if (type.isPrimitive) 0 else 1)
|
||||||
variableManager.addVariable("this", classVal, 0)
|
variableManager.addVariable("this", classVal, 0)
|
||||||
|
|
||||||
for (function in methods.values) {
|
methods.values.map { it.generate(classVal) }
|
||||||
function.generate(classVal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateInnerFields(declarations: List<KtDeclaration>) {
|
fun generateInnerFields(declarations: List<KtDeclaration>) {
|
||||||
var offset = fields.size
|
|
||||||
|
|
||||||
for (declaration in declarations) {
|
for (declaration in declarations) {
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
is KtProperty -> {
|
is KtProperty -> {
|
||||||
val ktType = state.bindingContext.get(BindingContext.TYPE, declaration.typeReference)
|
val ktType = state.bindingContext.get(BindingContext.TYPE, declaration.typeReference)
|
||||||
?: state.bindingContext.get(BindingContext.VARIABLE, declaration)!!.type
|
?: state.bindingContext.get(BindingContext.VARIABLE, declaration)!!.type
|
||||||
val field = resolveType(declaration, ktType)
|
val field = resolveType(declaration, ktType, fields.size)
|
||||||
field.offset = offset
|
|
||||||
offset++
|
|
||||||
|
|
||||||
if (declaration.initializer != null) {
|
if (declaration.initializer != null) {
|
||||||
initializedFields.put(field, declaration.initializer!!)
|
initializedFields.put(field, declaration.initializer!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
fields.add(field)
|
fields.add(field)
|
||||||
fieldsIndex[field.label] = field
|
fieldsIndex[field.label] = field
|
||||||
}
|
}
|
||||||
is KtEnumEntry -> {
|
is KtEnumEntry -> {
|
||||||
val name = declaration.name!!
|
val name = declaration.name!!
|
||||||
val field = LLVMVariable("class.$fullName.$name", type, scope = LLVMVariableScope(), pointer = 2)
|
val field = LLVMVariable("class.$structName.$name", type, scope = LLVMVariableScope(), pointer = 2)
|
||||||
enumFields.put(name, field)
|
enumFields.put(name, field)
|
||||||
}
|
}
|
||||||
is KtClass -> {
|
is KtClass ->
|
||||||
nestedClasses.put(declaration.fqName!!.asString(),
|
nestedClasses.put(declaration.fqName!!.asString(),
|
||||||
ClassCodegen(state,
|
ClassCodegen(state,
|
||||||
VariableManager(state.globalVariableCollection),
|
VariableManager(state.globalVariableCollection),
|
||||||
declaration, codeBuilder, this))
|
declaration, codeBuilder, this))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,20 +110,17 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
val enumField = enumFields[name]!!
|
val enumField = enumFields[name]!!
|
||||||
|
|
||||||
codeBuilder.defineGlobalVariable(field, codeBuilder.makeStructInitializer(constructorFields[primaryConstructorIndex]!!, arguments))
|
codeBuilder.defineGlobalVariable(field, codeBuilder.makeStructInitializer(constructorFields[primaryConstructorIndex]!!, arguments))
|
||||||
codeBuilder.defineGlobalVariable(LLVMVariable(enumField.label, enumField.type, enumField.kotlinName, enumField.scope, enumField.pointer - 1), "$field")
|
codeBuilder.defineGlobalVariable(LLVMVariable(enumField.label, enumField.type, enumField.kotlinName, enumField.scope, enumField.pointer - 1), field.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateStruct() {
|
private fun generateStruct() =
|
||||||
codeBuilder.createClass(fullName, fields)
|
codeBuilder.createClass(structName, fields)
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateSecondaryConstructor(secondaryConstructor: KtSecondaryConstructor) {
|
private fun generateSecondaryConstructor(secondaryConstructor: KtSecondaryConstructor) {
|
||||||
val thisCall = secondaryConstructor.getDelegationCall().calleeExpression
|
val thisCall = secondaryConstructor.getDelegationCall().calleeExpression
|
||||||
val descriptor = state.bindingContext.get(BindingContext.CONSTRUCTOR, secondaryConstructor)
|
val descriptor = state.bindingContext.get(BindingContext.CONSTRUCTOR, secondaryConstructor)
|
||||||
|
|
||||||
val argFields = ArrayList<LLVMVariable>()
|
|
||||||
|
|
||||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||||
variableManager.addVariable("this", classVal, 0)
|
variableManager.addVariable("this", classVal, 0)
|
||||||
|
|
||||||
@@ -143,17 +128,15 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
LLVMInstanceOfStandardType(it.fqNameSafe.convertToNativeName(), it.type, state = state)
|
LLVMInstanceOfStandardType(it.fqNameSafe.convertToNativeName(), it.type, state = state)
|
||||||
}
|
}
|
||||||
|
|
||||||
argFields.add(classVal)
|
val argFields = mutableListOf(classVal)
|
||||||
argFields.addAll(secondaryConstructorArguments)
|
argFields.addAll(secondaryConstructorArguments)
|
||||||
val currentConstructorIndex = LLVMType.mangleFunctionArguments(secondaryConstructorArguments)
|
val currentConstructorIndex = LLVMType.mangleFunctionArguments(secondaryConstructorArguments)
|
||||||
constructorFields.put(currentConstructorIndex, argFields)
|
constructorFields.put(currentConstructorIndex, argFields)
|
||||||
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(fullName + currentConstructorIndex, argFields, LLVMVoidType()))
|
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(structName + currentConstructorIndex, argFields, LLVMVoidType()))
|
||||||
|
|
||||||
codeBuilder.addStartExpression()
|
codeBuilder.addStartExpression()
|
||||||
|
|
||||||
for (variable in secondaryConstructorArguments) {
|
secondaryConstructorArguments.map { variableManager.addVariable(it.label, it, 2) }
|
||||||
variableManager.addVariable(variable.label, variable, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {}
|
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {}
|
||||||
val mainConstructorThis = blockCodegen.evaluateConstructorDelegationReferenceExpression(thisCall!!, this, secondaryConstructorArguments, 1) as LLVMVariable
|
val mainConstructorThis = blockCodegen.evaluateConstructorDelegationReferenceExpression(thisCall!!, this, secondaryConstructorArguments, 1) as LLVMVariable
|
||||||
@@ -166,14 +149,13 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generatePrimaryConstructor() {
|
private fun generatePrimaryConstructor() {
|
||||||
val argFields = ArrayList<LLVMVariable>()
|
|
||||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||||
variableManager.addVariable("this", classVal, 0)
|
variableManager.addVariable("this", classVal, 0)
|
||||||
|
|
||||||
argFields.add(classVal)
|
val argFields = mutableListOf(classVal)
|
||||||
argFields.addAll(constructorFields[primaryConstructorIndex]!!)
|
argFields.addAll(constructorFields[primaryConstructorIndex]!!)
|
||||||
|
|
||||||
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(fullName + primaryConstructorIndex, argFields, LLVMVoidType()))
|
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(structName + primaryConstructorIndex, argFields, LLVMVoidType()))
|
||||||
|
|
||||||
codeBuilder.addStartExpression()
|
codeBuilder.addStartExpression()
|
||||||
generateLoadArguments(classVal)
|
generateLoadArguments(classVal)
|
||||||
@@ -235,7 +217,7 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
codeBuilder.memcpy(castedDst, castedSrc, size)
|
codeBuilder.memcpy(castedDst, castedSrc, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType): LLVMClassVariable {
|
protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType, offset: Int): LLVMClassVariable {
|
||||||
val annotations = parseFieldAnnotations(field)
|
val annotations = parseFieldAnnotations(field)
|
||||||
val fieldName = state.bindingContext.get(BindingContext.VALUE_PARAMETER, field as?KtParameter)?.fqNameSafe?.convertToNativeName()
|
val fieldName = state.bindingContext.get(BindingContext.VALUE_PARAMETER, field as?KtParameter)?.fqNameSafe?.convertToNativeName()
|
||||||
?: field.fqName?.asString() ?: field.name!!
|
?: field.fqName?.asString() ?: field.name!!
|
||||||
@@ -243,9 +225,8 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
val result = LLVMInstanceOfStandardType(fieldName, ktType, LLVMRegisterScope(), state = state)
|
val result = LLVMInstanceOfStandardType(fieldName, ktType, LLVMRegisterScope(), state = state)
|
||||||
|
|
||||||
if (result.type is LLVMReferenceType) {
|
if (result.type is LLVMReferenceType) {
|
||||||
val type = result.type
|
result.type.prefix = "class"
|
||||||
type.prefix = "class"
|
result.type.byRef = true
|
||||||
type.byRef = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.classes.containsKey(field.name!!)) {
|
if (state.classes.containsKey(field.name!!)) {
|
||||||
@@ -256,30 +237,17 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
result.pointer = 0
|
result.pointer = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return LLVMClassVariable(result.label, result.type, result.pointer)
|
return LLVMClassVariable(result.label, result.type, result.pointer, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseFieldAnnotations(field: KtNamedDeclaration): Set<String> {
|
private fun parseFieldAnnotations(field: KtNamedDeclaration): Set<String> =
|
||||||
val result = HashSet<String>()
|
field.annotationEntries.map { state.bindingContext.get(BindingContext.ANNOTATION, it)?.type.toString() }.toHashSet()
|
||||||
|
|
||||||
for (annotation in field.annotationEntries) {
|
protected fun genClassInitializers() =
|
||||||
val annotationDescriptor = state.bindingContext.get(BindingContext.ANNOTATION, annotation)
|
classOrObject.getAnonymousInitializers().map {
|
||||||
val type = annotationDescriptor?.type.toString()
|
object : BlockCodegen(state, variableManager, codeBuilder) {
|
||||||
|
fun generate() = evaluateCodeBlock(it.body, scopeDepth = topLevel)
|
||||||
result.add(type)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun genClassInitializers() {
|
|
||||||
for (init in classOrObject.getAnonymousInitializers()) {
|
|
||||||
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {
|
|
||||||
fun generate(expr: PsiElement?) {
|
|
||||||
evaluateCodeBlock(expr, scopeDepth = topLevel)
|
|
||||||
}
|
}
|
||||||
}
|
}.map { it.generate() }
|
||||||
blockCodegen.generate(init.body)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -101,4 +101,4 @@ fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return if (analyzer.hasErrors()) null else analyzer.analysisResult
|
return if (analyzer.hasErrors()) null else analyzer.analysisResult
|
||||||
}
|
}
|
||||||
@@ -6,4 +6,5 @@ class LLVMCall(val returnType: LLVMType, val name: String, val arguments: Collec
|
|||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
"call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})"
|
"call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})"
|
||||||
}
|
|
||||||
|
}
|
||||||
@@ -3,4 +3,4 @@ package org.kotlinnative.translator.llvm
|
|||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||||
|
|
||||||
|
|
||||||
class LLVMClassVariable(label: String, type: LLVMType, pointer: Int = 0, var offset: Int = 0) : LLVMVariable(label, type, pointer = pointer)
|
class LLVMClassVariable(label: String, type: LLVMType, pointer: Int = 0, var offset: Int = 0) : LLVMVariable(label, type, pointer = pointer)
|
||||||
@@ -8,5 +8,4 @@ class LLVMVariableScope : LLVMScope() {
|
|||||||
|
|
||||||
class LLVMRegisterScope : LLVMScope() {
|
class LLVMRegisterScope : LLVMScope() {
|
||||||
override fun toString() = "%"
|
override fun toString() = "%"
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user