translator: add secondary constructors

This commit is contained in:
Alexey Stepanov
2016-08-19 16:36:07 +03:00
parent d98df3c748
commit 4535c94c28
9 changed files with 119 additions and 58 deletions
@@ -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
}