From ebc2c614d7722a9aa07c18ee5542784564eba8cf Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 2 Nov 2020 19:59:27 +0100 Subject: [PATCH] use non-stack call conv for builtin functions --- .../c64/codegen/BuiltinFunctionsAsmGen.kt | 32 ++++++++++++-- .../src/prog8/functions/BuiltinFunctions.kt | 42 ++++++++++--------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt index fa7363c74..4aef72bb6 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt @@ -1045,10 +1045,36 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val private fun translateArguments(args: MutableList, signature: FSignature) { val callConv = signature.callConvention(args.map { it.inferType(program).typeOrElse(DataType.STRUCT) }) - print("ARGS FOR ${signature.name} -> CALLCONV = $callConv") // TODO actually use the call convention - args.forEach { - asmgen.translateExpression(it) // TODO if possible, function args via registers + args.zip(callConv.params).zip(signature.parameters).forEach { + val paramName = it.second.name + val conv = it.first.second + val value = it.first.first + when { + conv.variable -> { + val varname = "prog8_lib.func_${signature.name}_cc.arg_${paramName}" // TODO after all builtin funcs have been changed into _cc, remove that suffix again + val src = AsmAssignSource.fromAstSource(value, program, asmgen) + val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, conv.dt, null, variableAsmName = varname) + val assign = AsmAssignment(src, tgt, false, value.position) + asmgen.translateNormalAssignment(assign) + } + conv.reg != null -> { + if(conv.dt==DataType.FLOAT || conv.dt in PassByReferenceDatatypes) { + // put the address of the argument in AY + val addr = AddressOf(value as IdentifierReference, value.position) + val src = AsmAssignSource.fromAstSource(addr, program, asmgen) + val tgt = AsmAssignTarget.fromRegisters(conv.reg, null, program, asmgen) + val assign = AsmAssignment(src, tgt, false, value.position) + asmgen.translateNormalAssignment(assign) + } else { + val src = AsmAssignSource.fromAstSource(value, program, asmgen) + val tgt = AsmAssignTarget.fromRegisters(conv.reg, null, program, asmgen) + val assign = AsmAssignment(src, tgt, false, value.position) + asmgen.translateNormalAssignment(assign) + } + } + else -> throw AssemblyError("callconv") + } } } diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index a691645b1..65cfce235 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -15,8 +15,8 @@ class FParam(val name: String, val possibleDatatypes: Set) typealias ConstExpressionCaller = (args: List, position: Position, program: Program) -> NumericLiteralValue -class ReturnConvention(val reg: RegisterOrPair?, val floatFac1: Boolean) -class ParamConvention(val reg: RegisterOrPair?, val variable: Boolean) +class ReturnConvention(val dt: DataType, val reg: RegisterOrPair?, val floatFac1: Boolean) +class ParamConvention(val dt: DataType, val reg: RegisterOrPair?, val variable: Boolean) class CallConvention(val params: List, val returns: ReturnConvention) { override fun toString(): String { val paramConvs = params.mapIndexed { index, it -> @@ -45,22 +45,23 @@ class FSignature(val name: String, fun callConvention(actualParamTypes: List): CallConvention { val returns = when(known_returntype) { - DataType.UBYTE, DataType.BYTE -> ReturnConvention(RegisterOrPair.A, false) - DataType.UWORD, DataType.WORD -> ReturnConvention(RegisterOrPair.AY, false) - DataType.FLOAT -> ReturnConvention(null, true) - in PassByReferenceDatatypes -> ReturnConvention(RegisterOrPair.AY, false) + DataType.UBYTE, DataType.BYTE -> ReturnConvention(known_returntype, RegisterOrPair.A, false) + DataType.UWORD, DataType.WORD -> ReturnConvention(known_returntype, RegisterOrPair.AY, false) + DataType.FLOAT -> ReturnConvention(known_returntype, null, true) + in PassByReferenceDatatypes -> ReturnConvention(known_returntype!!, RegisterOrPair.AY, false) else -> { + val paramType = actualParamTypes.first() if(pure) // return type depends on arg type - when(actualParamTypes.first()) { - DataType.UBYTE, DataType.BYTE -> ReturnConvention(RegisterOrPair.A, false) - DataType.UWORD, DataType.WORD -> ReturnConvention(RegisterOrPair.AY, false) - DataType.FLOAT -> ReturnConvention(null, true) - in PassByReferenceDatatypes -> ReturnConvention(RegisterOrPair.AY, false) - else -> ReturnConvention(null, false) + when(paramType) { + DataType.UBYTE, DataType.BYTE -> ReturnConvention(paramType, RegisterOrPair.A, false) + DataType.UWORD, DataType.WORD -> ReturnConvention(paramType, RegisterOrPair.AY, false) + DataType.FLOAT -> ReturnConvention(paramType, null, true) + in PassByReferenceDatatypes -> ReturnConvention(paramType, RegisterOrPair.AY, false) + else -> ReturnConvention(paramType, null, false) } else { - ReturnConvention(null, false) + ReturnConvention(paramType, null, false) } } } @@ -68,18 +69,19 @@ class FSignature(val name: String, actualParamTypes.isEmpty() -> CallConvention(emptyList(), returns) actualParamTypes.size==1 -> { // one parameter? via register/registerpair - val paramConv = when(actualParamTypes[0]) { - DataType.UBYTE, DataType.BYTE -> ParamConvention(RegisterOrPair.A, false) - DataType.UWORD, DataType.WORD -> ParamConvention(RegisterOrPair.AY, false) - DataType.FLOAT -> ParamConvention(RegisterOrPair.AY, false) - in PassByReferenceDatatypes -> ParamConvention(RegisterOrPair.AY, false) - else -> ParamConvention(null, false) + val paramType = actualParamTypes[0] + val paramConv = when(paramType) { + DataType.UBYTE, DataType.BYTE -> ParamConvention(paramType, RegisterOrPair.A, false) + DataType.UWORD, DataType.WORD -> ParamConvention(paramType, RegisterOrPair.AY, false) + DataType.FLOAT -> ParamConvention(paramType, RegisterOrPair.AY, false) + in PassByReferenceDatatypes -> ParamConvention(paramType, RegisterOrPair.AY, false) + else -> ParamConvention(paramType, null, false) } CallConvention(listOf(paramConv), returns) } else -> { // multiple parameters? via variables - val paramConvs = actualParamTypes.map { ParamConvention(null, true) } + val paramConvs = actualParamTypes.map { ParamConvention(it, null, true) } CallConvention(paramConvs, returns) } }