1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-27 21:57:28 +00:00

- 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.

This commit is contained in:
Sven Van de Velde 2023-12-13 17:16:06 +01:00
parent ff06b2eddf
commit b9472afb31

View File

@ -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<Variable> 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()) {