From b9472afb31266342b280f330b3d932d26cd7375b Mon Sep 17 00:00:00 2001 From: Sven Van de Velde Date: Wed, 13 Dec 2023 17:16:06 +0100 Subject: [PATCH] - zeropages allocated for local variables, used in procedures exported to .Asm libraries, are also added as part of the function prototype using the directive __zp_reserve. --- .../dk/camelot64/kickc/asm/AsmLibrary.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmLibrary.java b/src/main/java/dk/camelot64/kickc/asm/AsmLibrary.java index e9c72465e..750105fee 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmLibrary.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmLibrary.java @@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.Registers; import dk.camelot64.kickc.model.symbols.Procedure; import dk.camelot64.kickc.model.symbols.Scope; +import dk.camelot64.kickc.model.symbols.Symbol; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.values.ProcedureRef; @@ -56,6 +57,39 @@ public class AsmLibrary extends AsmLine { return procedures.containsKey(procedureName); } + + /** + * Generate the zeropages used + * + * @param param The variable to investigate + * @param scope The scope (procedure) + * @param zp The zero pages to append + */ + void generateZPVar(Variable param, Scope scope, StringBuilder zp) { + if (param == null) return; + if (param.isKindPhiMaster()) { + List versions = new ArrayList<>(scope.getVersions(param)); + if (versions.size() > 0) if (param.getLocalName().equals("return")) { + // Choose the last version for return values + param = versions.get(versions.size() - 1); + } else { + // Choose the first version for parameters + param = versions.get(0); + } + else + // Parameter optimized away to a constant or unused + return; + } + + Registers.Register allocation = param.getAllocation(); + if (allocation instanceof Registers.RegisterZpMem registerZp) { + if(!zp.isEmpty()) zp.append(", "); + zp.append(AsmFormat.getAsmNumber(registerZp.getZp())); + } + + return; + } + /** * Generate part of a comment that describes a returnvalue/parameter * @@ -99,11 +133,34 @@ public class AsmLibrary extends AsmLine { return param; } + /** + * Generate a header for a C function prototype for .asm library import. + * It defines the signature of each procedure in terms of the registers used, + * which can be __mem, __zp, __register for the procedure parameters and return value. + * Local variables, when allocated to __zp within the pre-compiled .asm library, + * are reserved using __zp_reserve directive. + * @param procedure The procedure to generate the header for. + * @return A String with the generated function prototype. + */ private String generateHeader(Procedure procedure) { StringBuilder signature = new StringBuilder(); signature.append("extern "); signature.append(procedure.getCallingConvention().getName()).append(" "); signature.append("__asm_import(\"").append(this.getName()).append("\") "); + + // reserve used zero pages if any. + StringBuilder zp = new StringBuilder(); + for(Symbol symbol : procedure.getSymbols().values()) { + if(symbol instanceof Variable variable) { + generateZPVar(variable, procedure, zp); + } + } + if(!zp.isEmpty()) { + zp.insert(0, "__zp_reserve("); + zp.append(") "); + } + signature.append(zp); + generateSignatureVar(procedure.getLocalVar("return"), procedure, signature); signature.append(procedure.getReturnType().toCDecl()); signature.append(" ").append(procedure.getLocalName()).append("("); @@ -119,6 +176,16 @@ public class AsmLibrary extends AsmLine { return signature.toString(); } + /** + * Generate a header file for an .asm library import. + * This is to be used by the main program to import an .asm library. + * It defines the signature of each procedure in terms of the registers used, + * which can be __mem, __zp, __register for the procedure parameters and return value. + * Local variables, when allocated to __zp within the pre-compiled .asm library, + * are reserved using __zp_reserve directive. + * @param program The program + * @return A string with the generated function prototypes for import. + */ public String generateHeaders(Program program) { StringBuilder headers = new StringBuilder(); for(String procedureName: this.getProcedures()) {