translator: add secondary constructors
This commit is contained in:
@@ -31,7 +31,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
var returnType: LLVMVariable? = null
|
var returnType: LLVMVariable? = null
|
||||||
var wasReturnOnTopLevel = false
|
var wasReturnOnTopLevel = false
|
||||||
|
|
||||||
protected fun evaluateCodeBlock(expr: PsiElement?, startLabel: LLVMLabel? = null, nextIterationLabel: LLVMLabel? = null, breakLabel: LLVMLabel? = null, scopeDepth: Int = 0, isBlock: Boolean = true) {
|
fun evaluateCodeBlock(expr: PsiElement?, startLabel: LLVMLabel? = null, nextIterationLabel: LLVMLabel? = null, breakLabel: LLVMLabel? = null, scopeDepth: Int = 0, isBlock: Boolean = true) {
|
||||||
codeBuilder.markWithLabel(startLabel)
|
codeBuilder.markWithLabel(startLabel)
|
||||||
if (isBlock) {
|
if (isBlock) {
|
||||||
expressionWalker(expr, breakLabel, scopeDepth)
|
expressionWalker(expr, breakLabel, scopeDepth)
|
||||||
@@ -116,6 +116,14 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun evaluateConstructorDelegationReferenceExpression(expr: KtConstructorDelegationReferenceExpression, structCodegen: StructCodegen, constructorArguments: List<LLVMVariable>, scopeDepth: Int): LLVMSingleValue? {
|
||||||
|
val targetCall = state.bindingContext.get(BindingContext.CALL, expr)
|
||||||
|
|
||||||
|
val names = parseValueArguments(targetCall!!.valueArguments, scopeDepth)
|
||||||
|
val args = loadArgsIfRequired(names, constructorArguments)
|
||||||
|
return evaluateConstructorCallExpression(LLVMVariable(structCodegen.fullName + structCodegen.primaryConstructorIndex, structCodegen.type, scope = LLVMVariableScope()), args)
|
||||||
|
}
|
||||||
|
|
||||||
private fun evaluateThisExpression(): LLVMSingleValue? {
|
private fun evaluateThisExpression(): LLVMSingleValue? {
|
||||||
return variableManager["this"]
|
return variableManager["this"]
|
||||||
}
|
}
|
||||||
@@ -247,7 +255,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
else -> LLVMVariable("type", standardType, pointer = 0)
|
else -> LLVMVariable("type", standardType, pointer = 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val args = mutableListOf(loadArgumentIfRequired(receiverExpression, typeThisArgument))
|
val args = mutableListOf(codeBuilder.loadArgumentIfRequired(receiverExpression, typeThisArgument))
|
||||||
args.addAll(loadArgsIfRequired(names, extensionCodegen.args))
|
args.addAll(loadArgsIfRequired(names, extensionCodegen.args))
|
||||||
return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args)
|
return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args)
|
||||||
}
|
}
|
||||||
@@ -315,7 +323,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
val arrayActionType = if (callMaker.callType == Call.CallType.ARRAY_SET_METHOD) "set" else "get"
|
val arrayActionType = if (callMaker.callType == Call.CallType.ARRAY_SET_METHOD) "set" else "get"
|
||||||
val explicitReceiver = callMaker.explicitReceiver as ExpressionReceiver
|
val explicitReceiver = callMaker.explicitReceiver as ExpressionReceiver
|
||||||
val receiver = evaluateExpression(explicitReceiver.expression, scope)!! as LLVMVariable
|
val receiver = evaluateExpression(explicitReceiver.expression, scope)!! as LLVMVariable
|
||||||
val pureReceiver = downLoadArgument(receiver, 1)
|
val pureReceiver = codeBuilder.downLoadArgument(receiver, 1)
|
||||||
|
|
||||||
val targetClassName = (receiver.type as LLVMReferenceType).type
|
val targetClassName = (receiver.type as LLVMReferenceType).type
|
||||||
|
|
||||||
@@ -397,7 +405,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
val names = parseArgList(expr, scopeDepth)
|
val names = parseArgList(expr, scopeDepth)
|
||||||
var name = expr.firstChild.firstChild.text
|
var name = expr.firstChild.firstChild.text
|
||||||
val external = state.externalFunctions.containsKey(name)
|
val external = state.externalFunctions.containsKey(name)
|
||||||
|
|
||||||
val function = "$name${if (names.size > 0 && !external) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""}"
|
val function = "$name${if (names.size > 0 && !external) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""}"
|
||||||
|
|
||||||
if (state.functions.containsKey(function) || state.externalFunctions.containsKey(function)) {
|
if (state.functions.containsKey(function) || state.externalFunctions.containsKey(function)) {
|
||||||
@@ -408,8 +415,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
|
|
||||||
if (state.classes.containsKey(name) || classScope?.structName == name) {
|
if (state.classes.containsKey(name) || classScope?.structName == name) {
|
||||||
val descriptor = state.classes[name] ?: classScope ?: return null
|
val descriptor = state.classes[name] ?: classScope ?: return null
|
||||||
val args = loadArgsIfRequired(names, descriptor.constructorFields)
|
val detectedConstructor = LLVMType.mangleFunctionArguments(names)
|
||||||
return evaluateConstructorCallExpression(LLVMVariable(descriptor.fullName, descriptor.type, scope = LLVMVariableScope()), args)
|
val args = loadArgsIfRequired(names, descriptor.constructorFields[detectedConstructor]!!)
|
||||||
|
return evaluateConstructorCallExpression(LLVMVariable(descriptor.fullName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
val localFunction = variableManager[name]
|
val localFunction = variableManager[name]
|
||||||
@@ -437,7 +445,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 = loadArgsIfRequired(names, nestedConstructor.constructorFields)
|
val args = loadArgsIfRequired(names, nestedConstructor.constructorFields[nestedConstructor.primaryConstructorIndex]!!)
|
||||||
return evaluateConstructorCallExpression(LLVMVariable(nestedConstructor.fullName, nestedConstructor.type, scope = LLVMVariableScope()), args)
|
return evaluateConstructorCallExpression(LLVMVariable(nestedConstructor.fullName, nestedConstructor.type, scope = LLVMVariableScope()), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,7 +453,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
name = "${containingClass.fullName}.$function"
|
name = "${containingClass.fullName}.$function"
|
||||||
val method = containingClass.methods[name]!!
|
val method = containingClass.methods[name]!!
|
||||||
val args = mutableListOf<LLVMSingleValue>()
|
val args = mutableListOf<LLVMSingleValue>()
|
||||||
val leftName = (expr.context as? KtDotQualifiedExpression)?.receiverExpression?.text
|
|
||||||
|
|
||||||
if (caller != null) {
|
if (caller != null) {
|
||||||
args.add(caller)
|
args.add(caller)
|
||||||
@@ -467,7 +474,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
if (location.size > 0) {
|
if (location.size > 0) {
|
||||||
val type = LLVMReferenceType(name, prefix = "class")
|
val type = LLVMReferenceType(name, prefix = "class")
|
||||||
type.location.addAll(location)
|
type.location.addAll(location)
|
||||||
|
|
||||||
return resolveClassOrObjectLocation(type)
|
return resolveClassOrObjectLocation(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,34 +516,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadArgumentIfRequired(value: LLVMSingleValue, argument: LLVMVariable): LLVMSingleValue {
|
|
||||||
var result = value
|
|
||||||
|
|
||||||
while (argument.pointer < result.pointer) {
|
|
||||||
result = codeBuilder.getNewVariable(argument.type, pointer = result.pointer - 1)
|
|
||||||
codeBuilder.loadVariable(result, value as LLVMVariable)
|
|
||||||
}
|
|
||||||
|
|
||||||
when (value.type) {
|
|
||||||
is LLVMStringType -> if (!(value.type as LLVMStringType).isLoaded) {
|
|
||||||
val newVariable = codeBuilder.getNewVariable(value.type!!, pointer = result.pointer + 1)
|
|
||||||
codeBuilder.allocStackVar(newVariable, asValue = true)
|
|
||||||
codeBuilder.copyVariable(result as LLVMVariable, newVariable)
|
|
||||||
|
|
||||||
result = codeBuilder.getNewVariable(argument.type, pointer = newVariable.pointer - 1)
|
|
||||||
codeBuilder.loadVariable(result, newVariable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun downLoadArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue =
|
|
||||||
loadArgumentIfRequired(value, LLVMVariable("", value.type!!, pointer = pointer))
|
|
||||||
|
|
||||||
private fun loadArgsIfRequired(names: List<LLVMSingleValue>, args: List<LLVMVariable>) =
|
private fun loadArgsIfRequired(names: List<LLVMSingleValue>, args: List<LLVMVariable>) =
|
||||||
names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue {
|
names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue {
|
||||||
return loadArgumentIfRequired(value, args[i])
|
return codeBuilder.loadArgumentIfRequired(value, args[i])
|
||||||
}).toList()
|
}).toList()
|
||||||
|
|
||||||
private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List<LLVMSingleValue>): LLVMSingleValue? {
|
private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List<LLVMSingleValue>): LLVMSingleValue? {
|
||||||
@@ -968,7 +949,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
|
|
||||||
private fun evaluateIfOperator(element: KtIfExpression, scopeDepth: Int, isExpression: Boolean = true): LLVMVariable? {
|
private fun evaluateIfOperator(element: KtIfExpression, scopeDepth: Int, isExpression: Boolean = true): LLVMVariable? {
|
||||||
val conditionResult = evaluateExpression(element.condition, scopeDepth)!!
|
val conditionResult = evaluateExpression(element.condition, scopeDepth)!!
|
||||||
val conditionNativeResult = downLoadArgument(conditionResult, 0)
|
val conditionNativeResult = codeBuilder.downLoadArgument(conditionResult, 0)
|
||||||
|
|
||||||
return if (isExpression)
|
return if (isExpression)
|
||||||
executeIfExpression(conditionNativeResult, element.then!!, element.`else`, element, scopeDepth + 1)
|
executeIfExpression(conditionNativeResult, element.then!!, element.`else`, element, scopeDepth + 1)
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ 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 java.util.*
|
||||||
|
|
||||||
class ClassCodegen(state: TranslationState,
|
class ClassCodegen(state: TranslationState,
|
||||||
variableManager: VariableManager,
|
variableManager: VariableManager,
|
||||||
@@ -49,15 +52,17 @@ class ClassCodegen(state: TranslationState,
|
|||||||
if (annotation) {
|
if (annotation) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
val currentConstructorFields = ArrayList<LLVMVariable>()
|
||||||
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
|
||||||
|
|
||||||
constructorFields.add(item)
|
currentConstructorFields.add(item)
|
||||||
fields.add(item)
|
fields.add(item)
|
||||||
fieldsIndex[item.label] = item
|
fieldsIndex[item.label] = item
|
||||||
}
|
}
|
||||||
|
primaryConstructorIndex = LLVMType.mangleFunctionArguments(currentConstructorFields)
|
||||||
|
constructorFields.put(primaryConstructorIndex!!, currentConstructorFields)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareForGenerate() {
|
override fun prepareForGenerate() {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.kotlinnative.translator.llvm.LLVMBuilder
|
|||||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||||
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||||
|
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||||
|
|
||||||
class ObjectCodegen(state: TranslationState,
|
class ObjectCodegen(state: TranslationState,
|
||||||
variableManager: VariableManager,
|
variableManager: VariableManager,
|
||||||
@@ -25,6 +26,9 @@ class ObjectCodegen(state: TranslationState,
|
|||||||
type.location.addAll(parentCodegen.type.location)
|
type.location.addAll(parentCodegen.type.location)
|
||||||
type.location.add(parentCodegen.structName)
|
type.location.add(parentCodegen.structName)
|
||||||
}
|
}
|
||||||
|
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
|
||||||
|
constructorFields.put(primaryConstructorIndex!!, arrayListOf())
|
||||||
|
|
||||||
generateInnerFields(objectDeclaration.declarations)
|
generateInnerFields(objectDeclaration.declarations)
|
||||||
|
|
||||||
calculateTypeSize()
|
calculateTypeSize()
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.kotlinnative.translator.llvm.*
|
import org.kotlinnative.translator.llvm.*
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMCharType
|
import org.kotlinnative.translator.llvm.types.LLVMCharType
|
||||||
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.LLVMVoidType
|
import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -24,7 +25,8 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
val nestedClasses = HashMap<String, ClassCodegen>()
|
val nestedClasses = HashMap<String, ClassCodegen>()
|
||||||
val enumFields = HashMap<String, LLVMVariable>()
|
val enumFields = HashMap<String, LLVMVariable>()
|
||||||
|
|
||||||
val constructorFields = ArrayList<LLVMVariable>()
|
val constructorFields = HashMap<String, ArrayList<LLVMVariable>>()
|
||||||
|
var primaryConstructorIndex: String? = null
|
||||||
val initializedFields = HashMap<LLVMVariable, KtExpression>()
|
val initializedFields = HashMap<LLVMVariable, KtExpression>()
|
||||||
|
|
||||||
abstract val type: LLVMReferenceType
|
abstract val type: LLVMReferenceType
|
||||||
@@ -67,6 +69,9 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
open fun generate() {
|
open fun generate() {
|
||||||
generateEnumFields()
|
generateEnumFields()
|
||||||
generatePrimaryConstructor()
|
generatePrimaryConstructor()
|
||||||
|
for (secondaryConstructor in classOrObject.getSecondaryConstructors()) {
|
||||||
|
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)
|
||||||
@@ -110,6 +115,7 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun generateEnumFields() {
|
private fun generateEnumFields() {
|
||||||
val enumEntries = classOrObject.declarations.filter { it is KtEnumEntry }
|
val enumEntries = classOrObject.declarations.filter { it is KtEnumEntry }
|
||||||
|
|
||||||
@@ -121,7 +127,7 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
val field = codeBuilder.getNewVariable(type, scope = LLVMVariableScope())
|
val field = codeBuilder.getNewVariable(type, scope = LLVMVariableScope())
|
||||||
val enumField = enumFields[name]!!
|
val enumField = enumFields[name]!!
|
||||||
|
|
||||||
codeBuilder.defineGlobalVariable(field, codeBuilder.makeStructInitializer(constructorFields, 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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,24 +136,56 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
codeBuilder.createClass(fullName, fields)
|
codeBuilder.createClass(fullName, fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateSecondaryConstructor(secondaryConstructor: KtSecondaryConstructor) {
|
||||||
|
val thisCall = secondaryConstructor.getDelegationCall().calleeExpression
|
||||||
|
val descriptor = state.bindingContext.get(BindingContext.CONSTRUCTOR, secondaryConstructor)
|
||||||
|
|
||||||
|
val argFields = ArrayList<LLVMVariable>()
|
||||||
|
|
||||||
|
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||||
|
variableManager.addVariable("this", classVal, 0)
|
||||||
|
|
||||||
|
val secondaryConstructorArguments = descriptor!!.valueParameters.map {
|
||||||
|
LLVMInstanceOfStandardType(it.name.toString(), it.type, state = state)
|
||||||
|
}
|
||||||
|
|
||||||
|
argFields.add(classVal)
|
||||||
|
argFields.addAll(secondaryConstructorArguments)
|
||||||
|
val currentConstructorIndex = LLVMType.mangleFunctionArguments(secondaryConstructorArguments)
|
||||||
|
constructorFields.put(currentConstructorIndex, argFields)
|
||||||
|
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName + currentConstructorIndex, argFields, LLVMVoidType(), arm = state.arm))
|
||||||
|
|
||||||
|
codeBuilder.addStartExpression()
|
||||||
|
|
||||||
|
for (variable in secondaryConstructorArguments) {
|
||||||
|
variableManager.addVariable(variable.label, variable, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {}
|
||||||
|
val mainConstructorThis = blockCodegen.evaluateConstructorDelegationReferenceExpression(thisCall!!, this, secondaryConstructorArguments, 1) as LLVMVariable
|
||||||
|
variableManager.addVariable("this", mainConstructorThis, 0)
|
||||||
|
|
||||||
|
blockCodegen.evaluateCodeBlock(secondaryConstructor.bodyExpression, scopeDepth = 1)
|
||||||
|
generateReturn(codeBuilder.downLoadArgument(variableManager.get("this")!!, 1) as LLVMVariable)
|
||||||
|
codeBuilder.addAnyReturn(LLVMVoidType())
|
||||||
|
codeBuilder.addEndExpression()
|
||||||
|
}
|
||||||
|
|
||||||
private fun generatePrimaryConstructor() {
|
private fun generatePrimaryConstructor() {
|
||||||
val argFields = ArrayList<LLVMVariable>()
|
val argFields = ArrayList<LLVMVariable>()
|
||||||
val refType = type.makeClone() as LLVMReferenceType
|
|
||||||
refType.addParam("sret")
|
|
||||||
refType.byRef = true
|
|
||||||
|
|
||||||
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)
|
argFields.add(classVal)
|
||||||
argFields.addAll(constructorFields)
|
argFields.addAll(constructorFields[primaryConstructorIndex]!!)
|
||||||
|
|
||||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName, argFields, LLVMVoidType(), arm = state.arm))
|
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName + primaryConstructorIndex, argFields, LLVMVoidType(), arm = state.arm))
|
||||||
|
|
||||||
codeBuilder.addStartExpression()
|
codeBuilder.addStartExpression()
|
||||||
generateLoadArguments(classVal)
|
generateLoadArguments(classVal)
|
||||||
generateAssignments()
|
generateAssignments()
|
||||||
generateReturn()
|
generateReturn(LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1))
|
||||||
genClassInitializers()
|
genClassInitializers()
|
||||||
codeBuilder.addAnyReturn(LLVMVoidType())
|
codeBuilder.addAnyReturn(LLVMVoidType())
|
||||||
codeBuilder.addEndExpression()
|
codeBuilder.addEndExpression()
|
||||||
@@ -157,7 +195,7 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
|
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
|
||||||
codeBuilder.loadArgument(thisVariable, false)
|
codeBuilder.loadArgument(thisVariable, false)
|
||||||
|
|
||||||
constructorFields.forEach {
|
constructorFields[primaryConstructorIndex]!!.forEach {
|
||||||
if (it.type !is LLVMReferenceType) {
|
if (it.type !is LLVMReferenceType) {
|
||||||
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
|
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
|
||||||
codeBuilder.loadArgument(loadVariable)
|
codeBuilder.loadArgument(loadVariable)
|
||||||
@@ -166,7 +204,7 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateAssignments() {
|
private fun generateAssignments() {
|
||||||
constructorFields.forEach {
|
constructorFields[primaryConstructorIndex]!!.forEach {
|
||||||
when (it.type) {
|
when (it.type) {
|
||||||
is LLVMReferenceType -> {
|
is LLVMReferenceType -> {
|
||||||
val classField = codeBuilder.getNewVariable(it.type, pointer = it.pointer + 1)
|
val classField = codeBuilder.getNewVariable(it.type, pointer = it.pointer + 1)
|
||||||
@@ -200,9 +238,8 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
codeBuilder.addComment("field initilizers ends")
|
codeBuilder.addComment("field initilizers ends")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateReturn() {
|
private fun generateReturn(src: LLVMVariable) {
|
||||||
val dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
|
val dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||||
val src = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
|
|
||||||
|
|
||||||
val castedDst = codeBuilder.bitcast(dst, LLVMVariable("", LLVMCharType(), pointer = 1))
|
val castedDst = codeBuilder.bitcast(dst, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||||
val castedSrc = codeBuilder.bitcast(src, LLVMVariable("", LLVMCharType(), pointer = 1))
|
val castedSrc = codeBuilder.bitcast(src, LLVMVariable("", LLVMCharType(), pointer = 1))
|
||||||
|
|||||||
@@ -72,6 +72,31 @@ class LLVMBuilder(val arm: Boolean = false) {
|
|||||||
else -> throw UnsupportedOperationException()
|
else -> throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun loadArgumentIfRequired(value: LLVMSingleValue, argument: LLVMVariable): LLVMSingleValue {
|
||||||
|
var result = value
|
||||||
|
|
||||||
|
while (argument.pointer < result.pointer) {
|
||||||
|
result = getNewVariable(argument.type, pointer = result.pointer - 1)
|
||||||
|
loadVariable(result, value as LLVMVariable)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (value.type) {
|
||||||
|
is LLVMStringType -> if (!(value.type as LLVMStringType).isLoaded) {
|
||||||
|
val newVariable = getNewVariable(value.type!!, pointer = result.pointer + 1)
|
||||||
|
allocStackVar(newVariable, asValue = true)
|
||||||
|
copyVariable(result as LLVMVariable, newVariable)
|
||||||
|
|
||||||
|
result = getNewVariable(argument.type, pointer = newVariable.pointer - 1)
|
||||||
|
loadVariable(result, newVariable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun downLoadArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue =
|
||||||
|
loadArgumentIfRequired(value, LLVMVariable("", value.type!!, pointer = pointer))
|
||||||
|
|
||||||
fun clean() {
|
fun clean() {
|
||||||
localCode = StringBuilder()
|
localCode = StringBuilder()
|
||||||
globalCode = StringBuilder()
|
globalCode = StringBuilder()
|
||||||
|
|||||||
@@ -15,16 +15,10 @@ class LLVMReferenceType(val type: String, var prefix: String = "", override var
|
|||||||
|
|
||||||
override fun toString() = "%$typename"
|
override fun toString() = "%$typename"
|
||||||
|
|
||||||
private val params = ArrayList<String>()
|
|
||||||
|
|
||||||
val location = ArrayList<String>()
|
val location = ArrayList<String>()
|
||||||
|
|
||||||
override fun mangle() = "Ref_$type"
|
override fun mangle() = "Ref_$type"
|
||||||
|
|
||||||
fun addParam(param: String) {
|
|
||||||
params.add(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
|
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
|
||||||
LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
|
LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ abstract class LLVMType() : Cloneable {
|
|||||||
open fun operatorDec(firstOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
open fun operatorDec(firstOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||||
open fun parseArg(inputArg: String) = inputArg
|
open fun parseArg(inputArg: String) = inputArg
|
||||||
|
|
||||||
fun makeClone() = clone()
|
|
||||||
|
|
||||||
open fun convertFrom(source: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
open fun convertFrom(source: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||||
|
|
||||||
abstract fun mangle(): String
|
abstract fun mangle(): String
|
||||||
@@ -38,6 +36,12 @@ abstract class LLVMType() : Cloneable {
|
|||||||
abstract var size: Int
|
abstract var size: Int
|
||||||
abstract val defaultValue: String
|
abstract val defaultValue: String
|
||||||
open fun isPrimitive(): Boolean = false
|
open fun isPrimitive(): Boolean = false
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun mangleFunctionArguments(names: List<LLVMSingleValue>) =
|
||||||
|
"_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseLLVMType(type: String): LLVMType = when (type) {
|
fun parseLLVMType(type: String): LLVMType = when (type) {
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
secondary_constructor_1_Int(1389) == 1401
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class secondary_constructor_1_class(var field1: Int) {
|
||||||
|
constructor(field1: Int, field2: Int) : this(field1) {
|
||||||
|
this.field1 = field1 + field2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun secondary_constructor_1(x: Int): Int {
|
||||||
|
val cls = secondary_constructor_1_class(12, x)
|
||||||
|
return cls.field1
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user