1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-10 10:29:36 +00:00

- Fix earlier manual merge mistakes.

- Fixed a couple of issues with AsmIdentifier.
- Global variables exported are volatile.
- Created proper generation of the protypes for exported global variables in _asm.h.
- Created new test cases.
- Struggled with the proper export of global struct variables, first version of it implemented but this will require rework ...
- There are issues with "types" of structures, will need more work in the future and a strategy for it...
- Made AsmLibrary functions as AsmExportLibrary to make the code more clear.
- Created isAsmExportLibraryGlobal and isAsmImportLibrary global functions.
This commit is contained in:
Sven Van de Velde 2024-01-02 19:41:03 +01:00
parent d477cb9eae
commit fab740f797
24 changed files with 373 additions and 105 deletions

View File

@ -291,7 +291,7 @@ public class AsmFormat {
if(symbol instanceof Variable boundVariable) {
if (boundVariable.getAsmName() != null) {
asmName = boundVariable.getAsmName();
asmLibraryLabel = boundVariable.getAsmLibraryLabel();
asmLibraryLabel = boundVariable.getAsmExportLibraryLabel();
}
}
if(!symbolScopeRef.equals(codeScopeRef)) {

View File

@ -39,7 +39,7 @@ public class AsmIdentifier extends AsmLine {
* @return the kickasm identifier version of the string.
*/
public String getAsm() {
return identifier != null ? identifier.replace("-","") : null;
return identifier != null ? identifier.replace("-","_") : null;
}
/**
@ -47,8 +47,7 @@ public class AsmIdentifier extends AsmLine {
* illegal kickasm identifier character replacement.
* @return The original string given.
*/
@Override
public String toString() {
return identifier;
return identifier != null ? identifier : null;
}
}

View File

@ -7,7 +7,8 @@ public class AsmIgnoredImportInlinedKickAsm extends AsmLine {
private AsmInlineKickAsm body;
public AsmIgnoredImportInlinedKickAsm(String identifier, AsmInlineKickAsm body) {
this.identifier = new AsmIdentifier(identifier).getAsm();
if(identifier != null)
this.identifier = new AsmIdentifier(identifier).getAsm();
this.body = body;
}

View File

@ -7,10 +7,6 @@ import java.util.HashMap;
public class AsmImportLibrary extends AsmLibrary {
public AsmImportLibrary(String name, Path resource, HashMap<String, Procedure.CallingConvention> procedures) {
super(name, resource, procedures);
}
public AsmImportLibrary(String name, Path resource) {
super(name, resource);
}

View File

@ -7,8 +7,7 @@ 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;
import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.model.values.*;
import java.nio.file.Path;
import java.util.*;
@ -30,7 +29,10 @@ public class AsmLibrary extends AsmLine {
private boolean exportAll;
public AsmLibrary(String asmLibraryName, Path resource, HashMap<String, Procedure.CallingConvention> procedures) {
this.asmLibraryName = new AsmIdentifier(asmLibraryName);
if(asmLibraryName != null)
this.asmLibraryName = new AsmIdentifier(asmLibraryName);
else
this.asmLibraryName = null;
this.resource = resource;
this.procedures = procedures;
}
@ -90,6 +92,25 @@ public class AsmLibrary extends AsmLine {
return;
}
void generatePrototypeVar(Variable var, StringBuilder signature) {
Registers.Register allocation = var.getAllocation();
if (allocation instanceof Registers.RegisterZpMem) {
Registers.RegisterZpMem registerZp = (Registers.RegisterZpMem) allocation;
signature.append("__zp(").append(AsmFormat.getAsmNumber(registerZp.getZp())).append(") ");
} else if (allocation instanceof Registers.RegisterMainMem) {
Registers.RegisterMainMem registerMainMem = (Registers.RegisterMainMem) allocation;
signature.append("__mem(").append(registerMainMem.getAddress() == null ? "" : AsmFormat.getAsmNumber(registerMainMem.getAddress())).append(") ");
} else if (allocation instanceof Registers.RegisterAByte) {
signature.append("__register(A) ");
} else if (allocation instanceof Registers.RegisterXByte) {
signature.append("__register(X) ");
} else if (allocation instanceof Registers.RegisterYByte) {
signature.append("__register(Y) ");
} else if (allocation instanceof Registers.RegisterZByte) {
signature.append("__register(Z) ");
}
}
/**
* Generate part of a comment that describes a returnvalue/parameter
*
@ -116,22 +137,7 @@ public class AsmLibrary extends AsmLine {
}
if(!isStackCall) {
Registers.Register allocation = param.getAllocation();
if (allocation instanceof Registers.RegisterZpMem) {
Registers.RegisterZpMem registerZp = (Registers.RegisterZpMem) allocation;
signature.append("__zp(").append(AsmFormat.getAsmNumber(registerZp.getZp())).append(") ");
} else if (allocation instanceof Registers.RegisterMainMem) {
Registers.RegisterMainMem registerMainMem = (Registers.RegisterMainMem) allocation;
signature.append("__mem(").append(registerMainMem.getAddress() == null ? "" : AsmFormat.getAsmNumber(registerMainMem.getAddress())).append(") ");
} else if (allocation instanceof Registers.RegisterAByte) {
signature.append("__register(A) ");
} else if (allocation instanceof Registers.RegisterXByte) {
signature.append("__register(X) ");
} else if (allocation instanceof Registers.RegisterYByte) {
signature.append("__register(Y) ");
} else if (allocation instanceof Registers.RegisterZByte) {
signature.append("__register(Z) ");
}
generatePrototypeVar(param, signature);
}
return param;
}
@ -175,7 +181,7 @@ public class AsmLibrary extends AsmLine {
* @param procedure The procedure to generate the header for.
* @return A String with the generated function prototype.
*/
private String generateHeader(Procedure procedure, Program program) {
private String generateProcedureHeader(Procedure procedure, Program program) {
StringBuilder signature = new StringBuilder();
Procedure.CallingConvention callingConvention = procedure.getCallingConvention();
boolean isStackCall = callingConvention == Procedure.CallingConvention.STACK_CALL;
@ -206,23 +212,75 @@ 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.
*/
private boolean hasData(Variable constantVar) {
ConstantValue constantValue = constantVar.getInitValue();
if (constantValue instanceof ConstantArray) return true;
else if (constantValue instanceof ConstantStructValue) return true;
else if (constantValue instanceof ConstantString) return true;
else return false;
}
private boolean hasExportAsmLibrary(Variable constantVar, String exportAsmLibrary) {
String varExportAsmLibrary = constantVar.getExportAsmLibrary();
if(exportAsmLibrary != null) {
if(varExportAsmLibrary != null) {
return constantVar.getExportAsmLibrary().equals(exportAsmLibrary);
} else {
return false;
}
} else {
return true;
}
}
private String generateVariableHeader(Variable variable, Program program) {
StringBuilder signature = new StringBuilder();
signature.append("extern ");
signature.append("__asm_import(\"").append(this.getAsmLibraryName()).append("\") ");
generatePrototypeVar(variable, signature);
// signature.append(variable.getType().toCDecl());
// signature.append(variable.getLocalName()).append(" ");
signature.append(variable.toCDecl());
if(variable.isKindConstant()) {
signature.append(" = ").append(variable.getInitValue());
}
signature.append(";");
signature.append("\n");
// Always add the signature comments...
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 for each the registers used, which can be `__mem`, `__zp`, `__register`:
* - the extern declaration of each exported global variable in the .asm library.
* - the extern declaration of each exported procedure in the .asm library,
* in terms of the registers used, 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();
// Generate the global variables headers.
Scope scope = program.getScope().getScope(ScopeRef.ROOT);
Collection<Variable> scopeConstants = scope.getAllVars(false);
Set<String> added = new LinkedHashSet<>();
// Add all constants arrays incl. strings with data
for (Variable constantVar : scopeConstants) {
if (hasExportAsmLibrary(constantVar, this.getAsmLibraryName())) {
headers.append(generateVariableHeader(constantVar, program));
}
}
// Generate the procedure headers.
for(String procedureName: this.getProcedures()) {
Procedure procedure = program.getScope().getProcedure(new ProcedureRef(procedureName));
if(procedure != null) {
if(procedure.isAsmExportLibrary())
headers.append(generateHeader(procedure, program));
headers.append(generateProcedureHeader(procedure, program));
}
}
return headers.toString();

View File

@ -286,7 +286,8 @@ public class Program {
}
public void setAsmLibraryName(String asmLibraryName) {
this.asmLibraryName = new AsmIdentifier(asmLibraryName);
if(asmLibraryName != null)
this.asmLibraryName = new AsmIdentifier(asmLibraryName);
}
public void setTargetPlatform(TargetPlatform targetPlatform) {

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.asm.AsmIdentifier;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeConversion;
@ -86,7 +87,11 @@ public class VariableBuilder {
variable.setMemoryAddress(this.getAddress());
variable.setDeclarationOnly(this.isDeclarationOnly());
variable.setStructUnwind(this.getStructUnwind());
variable.setAsmLibrary(this.getAsmLibrary());
// Set the Export and Import and associated variable flags.
// (note that these are set inside these procedures).
variable.setAsmExportLibrary(this.getAsmExportLibrary());
variable.setAsmImportLibrary(this.getAsmImportLibrary());
// Check if the symbol has already been declared
Symbol declaredSymbol = this.scope.getLocalSymbol(this.varName);
@ -317,7 +322,7 @@ public class VariableBuilder {
* @return true if the variable is declared but not defined.
*/
public boolean isDeclarationOnly() {
return hasDirective(Directive.Extern.class);
return hasDirective(Directive.Extern.class) && getAsmImportLibrary() == null;
}
/**
@ -444,12 +449,18 @@ public class VariableBuilder {
*
* @return The .asm export library
*/
public String getAsmLibrary() {
public String getAsmExportLibrary() {
Directive.AsmExportDirective asmLibraryDirective = findDirective(Directive.AsmExportDirective.class, directives);
if(asmLibraryDirective != null) {
if(isArray()) {
return asmLibraryDirective.getAsmLibrary();
}
return asmLibraryDirective.getAsmLibrary();
}
return null;
}
public String getAsmImportLibrary() {
Directive.AsmImportDirective asmLibraryDirective = findDirective(Directive.AsmImportDirective.class, directives);
if(asmLibraryDirective != null) {
return asmLibraryDirective.getAsmLibrary();
}
return null;
}

View File

@ -54,7 +54,7 @@ public class Procedure extends Scope {
private boolean asmExportLibrary;
public String getAsmLibrary() {
return asmLibrary.toString();
return asmLibrary != null ? asmLibrary.toString() : null;
}
public String getAsmLibraryLabel() {
@ -72,7 +72,8 @@ public class Procedure extends Scope {
* @param asmLibraryName The .asm library name that is imported.
*/
public void setAsmImportLibrary(String asmLibraryName) {
this.asmLibrary = new AsmIdentifier(asmLibraryName);
if(asmLibraryName != null)
this.asmLibrary = new AsmIdentifier(asmLibraryName);
this.asmImportLibrary = true;
}
@ -101,7 +102,8 @@ public class Procedure extends Scope {
* @param asmLibraryName The .asm library name that is exported.
*/
public void setAsmExportLibrary(String asmLibraryName) {
this.asmLibrary = new AsmIdentifier(asmLibraryName);
if(asmLibraryName != null)
this.asmLibrary = new AsmIdentifier(asmLibraryName);
this.asmExportLibrary = true;
}

View File

@ -6,10 +6,7 @@ import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeStruct;
import dk.camelot64.kickc.model.values.ConstantRef;
import dk.camelot64.kickc.model.values.ConstantValue;
import dk.camelot64.kickc.model.values.SymbolVariableRef;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.model.values.*;
import java.util.ArrayList;
import java.util.List;
@ -106,16 +103,32 @@ public class Variable implements Symbol {
private boolean structUnwind;
public void setAsmLibrary(String asmLibraryName) {
this.asmLibrary = new AsmIdentifier(asmLibraryName);
public void setAsmExportLibrary(String asmLibraryName) {
if(asmLibraryName != null) {
this.asmExportLibrary = new AsmIdentifier(asmLibraryName);
setExport(true);
setOptimize(false);
setDeclarationOnly(false);
}
}
public String getAsmLibraryLabel() {
return asmLibrary != null ? asmLibrary.getAsm() : null;
public void setAsmImportLibrary(String asmLibraryName) {
if(asmLibraryName != null) {
this.asmImportLibrary = new AsmIdentifier(asmLibraryName);
setExport(false);
setDeclarationOnly(false);
setOptimize(false);
}
}
public String getAsmExportLibraryLabel() {
return asmExportLibrary != null ? asmExportLibrary.getAsm() : null;
}
/** The imported asm library where the variable is declared for specific cases */
private AsmIdentifier asmLibrary;
private AsmIdentifier asmExportLibrary;
private AsmIdentifier asmImportLibrary;
/**
* Create a variable (or constant)
@ -203,6 +216,8 @@ public class Variable implements Symbol {
constVar.setExport(variable.isExport());
constVar.setComments(variable.getComments());
constVar.setStructUnwind(variable.isStructUnwind());
constVar.setAsmImportLibrary(variable.getImportAsmLibrary());
constVar.setAsmExportLibrary(variable.getExportAsmLibrary());
return constVar;
}
@ -299,7 +314,7 @@ public class Variable implements Symbol {
return Kind.LOAD_STORE.equals(getKind());
}
public boolean isAsmLibraryParameter() {
public boolean isAsmExportLibraryParameter() {
Procedure procedure = this.getContainingProcedure();
if(procedure != null)
return procedure.isAsmLibrary() && procedure.getParameters().contains(this);
@ -307,7 +322,7 @@ public class Variable implements Symbol {
return false;
}
public boolean isAsmLibraryReturn() {
public boolean isAsmExportLibraryReturn() {
Procedure procedure = this.getContainingProcedure();
if(procedure != null)
return procedure.isAsmLibrary() && procedure.isReturn(this);
@ -315,8 +330,20 @@ public class Variable implements Symbol {
return false;
}
public boolean isAsmExportLibraryGlobal() {
return this.asmExportLibrary != null && this.getScope().getRef().equals(ScopeRef.ROOT);
}
public boolean isAsmImportLibraryGlobal() {
return this.asmImportLibrary != null;
}
public String getExportAsmLibrary() {
return asmLibrary != null ? asmLibrary.toString() : null;
return asmExportLibrary != null ? asmExportLibrary.toString() : null;
}
public String getImportAsmLibrary() {
return asmImportLibrary != null ? asmImportLibrary.toString() : null;
}
public boolean isKindIntermediate() {

View File

@ -177,8 +177,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
constructorProc.setConstructor(true);
// #820/41 - Export the constructor_for procedure(s) so that when imported, they are not generated.
AsmExportLibrary asmExportLibrary = program.getAsmExports().get(program.getAsmLibraryName());
program.addAsmExportProcedure(asmExportLibrary, Procedure.CallingConvention.VAR_CALL, constructorProc.getLocalName());
constructorProc.setAsmExportLibrary(program.getAsmLibraryName());
if(asmExportLibrary != null) {
program.addAsmExportProcedure(asmExportLibrary, Procedure.CallingConvention.VAR_CALL, constructorProc.getLocalName());
constructorProc.setAsmExportLibrary(program.getAsmLibraryName());
}
}
}
}
@ -1507,9 +1509,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
public Object visitDirectiveAsmExport(KickCParser.DirectiveAsmExportContext ctx) {
String asmExport = program.getAsmLibraryName();
if(asmExport == null) {
throw new CompileError("__asm_export directive used before #pragma asm_library declaration.", new StatementSource(ctx));
}
// if(asmExport == null) {
// throw new CompileError("__asm_export directive used before #pragma asm_library declaration.", new StatementSource(ctx));
// }
return new Directive.AsmExportDirective(asmExport);
}

View File

@ -14,7 +14,7 @@ public class Pass1AssertVariableDefined extends Pass1Base {
@Override
public boolean step() {
for(Variable var : getProgramScope().getAllVars(true)) {
if(var.isDeclarationOnly())
if(var.isDeclarationOnly() && !var.isAsmImportLibraryGlobal())
throw new CompileError("Error! Variable is declared but never defined: " + var.getFullName());
}
return false;

View File

@ -62,7 +62,7 @@ public class Pass1CallVar extends Pass2SsaOptimization {
if(lValue!=null) {
Variable returnVar = procedure.getLocalVariable("return");
// #820/11 - Procedure return value of an asm library.
returnVar.setAsmLibrary(procedure.getAsmLibrary()); // This is key to bind the variable during assembler generation!
returnVar.setAsmExportLibrary(procedure.getAsmLibrary()); // This is key to bind the variable during assembler generation!
generateCallFinalize(lValue, returnVar, source, comments, stmtIt, statement);
}
stmtIt.remove();
@ -88,7 +88,7 @@ public class Pass1CallVar extends Pass2SsaOptimization {
final RValue parameterVal = call.getParameters().get(i);
final Variable parameterDef = parameterDefs.get(i);
// 820/10 - Procedure parameters in an asm library.
parameterDef.setAsmLibrary(procedure.getAsmLibrary());
parameterDef.setAsmExportLibrary(procedure.getAsmLibrary());
stmtIt.add(new StatementAssignment(parameterDef.getVariableRef(), parameterVal, false, source, comments));
comments = Comment.NO_COMMENTS;
}

View File

@ -39,6 +39,7 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
if(variable.getRegister()!=null && variable.getRegister().isMem())
// Skip variables allocated into memory
continue;
if(variable.isAsmExportLibraryGlobal()) continue; // Don't converted exported constant global variables.
if(!isParameter(variableRef)) {
final List<VarAssignments.VarAssignment> varAssignments = VarAssignments.get(variableRef, getGraph(), getProgramScope());
if(varAssignments.size() == 1) {

View File

@ -144,7 +144,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef varRef) {
Variable var = getProgramScope().getVariable(varRef);
if(var.isVolatile() || var.isKindLoadStore() || var.isAsmLibraryParameter())
if(var.isVolatile() || var.isKindLoadStore() || var.isAsmExportLibraryParameter())
// Do not examine volatiles and non-versioned variables
continue;
if(var.getRegister() != null && var.getRegister().isMem())
@ -175,7 +175,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
// Look for constants among non-versioned variables
for(Variable variable : getProgramScope().getAllVariables(true)) {
if(variable.isVolatile() || !variable.isKindLoadStore() || variable.isAsmLibraryParameter()) // #828 - Added
if(variable.isVolatile() || !variable.isKindLoadStore() || variable.isAsmExportLibraryParameter()) // #828 - Added
// Do not examine volatiles, non-constants or versioned variables
continue;
if(variable.getRegister() != null && variable.getRegister().isMem())

View File

@ -157,7 +157,7 @@ public class Pass4AssertNoCpuClobber extends Pass2Base {
}
Variable aliveVar = getProgram().getSymbolInfos().getVariable(aliveVarRef);
if(aliveVar.isAsmLibraryParameter()) {
if(aliveVar.isAsmExportLibraryParameter()) {
// Library parameters are external and cannot be clobbered.
continue;
}

View File

@ -116,6 +116,9 @@ public class Pass4CodeGeneration {
if (program.getAsmLibraryName() != null) {
asm.startChunk(currentScope, null, "Library");
asm.addNamespaceBegin(program.getAsmLibraryLabel());
} else {
asm.startChunk(currentScope, null, "Main Program");
asm.addNamespaceBegin(program.getOutputFileManager().getOutputBaseName());
}
asm.startChunk(currentScope, null, "Upstart");
@ -155,7 +158,7 @@ public class Pass4CodeGeneration {
// Generate global ZP labels
asm.startChunk(currentScope, null, "Global Constants & labels");
addConstantsAndLabels(asm, currentScope);
addConstantsAndLabels(asm, currentScope, null);
Procedure oldProcedure = null;
for (Graph.Block block : getGraph().getAllBlocks()) {
@ -191,7 +194,7 @@ public class Pass4CodeGeneration {
// Start the new scope
asm.addScopeBegin(AsmFormat.asmFix(block.getLabel().getFullName()));
// Add all ZP labels for the scope
addConstantsAndLabels(asm, currentScope);
addConstantsAndLabels(asm, currentScope, null);
}
}
@ -245,13 +248,17 @@ public class Pass4CodeGeneration {
addAbsoluteAddressData(asm, ScopeRef.ROOT, null);
// #820/24 - Close the namespace of the asm library.
if (program.getAsmLibraryName() != null) {
// if (program.getAsmLibraryName() != null) {
asm.addNamespaceEnd();
}
// }
asm.startChunk(currentScope, null, "Exported Global Data");
addData(asm, ScopeRef.ROOT, program.getAsmLibraryName());
addAbsoluteAddressData(asm, ScopeRef.ROOT, program.getAsmLibraryName());
// #820/34 - Export the global data, but when the compilation is an .asm export library.
if (program.getAsmLibraryName() != null) {
asm.startChunk(currentScope, null, "Exported Global Data");
// Add the global data elements for the ROOT scope of the .asm library.
addData(asm, ScopeRef.ROOT, program.getAsmLibraryName());
addAbsoluteAddressData(asm, ScopeRef.ROOT, program.getAsmLibraryName());
}
generateImportAsmLibraries(asm, program); // #820/25 - .asm library #import stub code.
@ -399,12 +406,16 @@ public class Pass4CodeGeneration {
String varExportAsmLibrary = constantVar.getExportAsmLibrary();
if(exportAsmLibrary != null) {
if(varExportAsmLibrary != null) {
return constantVar.getExportAsmLibrary().equals(exportAsmLibrary);
return varExportAsmLibrary.equals(exportAsmLibrary);
} else {
return false;
}
} else {
return true;
boolean isImportAsmLibraryGlobal = constantVar.isAsmImportLibraryGlobal();
boolean isExportAsmLibraryParameter = constantVar.isAsmExportLibraryParameter();
boolean isExportAsmLibraryReturn = constantVar.isAsmExportLibraryReturn();
return ( varExportAsmLibrary == null || isExportAsmLibraryParameter || isExportAsmLibraryReturn )
&& !isImportAsmLibraryGlobal;
}
}
@ -480,13 +491,16 @@ public class Pass4CodeGeneration {
}
/**
* Add constant declarations for constants without data and labels for memory variables without data.
* Added before the the code of the scope.
* Add global exported struct size constant declarations for structure variables that are exported and thus global.
* Added for all structure variables in a library at the end code of the ROOT scope.
*
* This is a dirty copy but I feel that the code to handle and create the size structure type symbols
* was also a bit "dirty" and this whole size thing is candidate for a some serious code rework overall ...
*
* @param asm The ASM program
* @param scopeRef The scope
*/
private void addConstantsAndLabels(AsmProgram asm, ScopeRef scopeRef) {
private void addGlobalStructSizeConstant(AsmProgram asm, ScopeRef scopeRef, Variable var) {
Scope scope = program.getScope().getScope(scopeRef);
Set<String> added = new LinkedHashSet<>();
Collection<Variable> scopeConstants = scope.getAllConstants(false);
@ -494,6 +508,36 @@ public class Pass4CodeGeneration {
// First add all constants without data that can become constants in KickAsm
for (Variable constantVar : scopeConstants) {
if (!hasData(constantVar)) {
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
if (asmName != null && !added.contains(asmName)) {
if ((constantVar.getLocalName().equals("SIZEOF_" + var.getType().getConstantFriendlyName()))) {
// Use constant otherwise
added.add(asmName);
// Find the constant value calculation
String asmConstant = AsmFormat.getAsmConstant(program, constantVar.getInitValue(), 99, scopeRef);
addConstant(asmName, constantVar, asmConstant, asm);
}
}
}
}
}
/**
* Add constant declarations for constants without data and labels for memory variables without data.
* Added before the the code of the scope.
*
* @param asm The ASM program
* @param scopeRef The scope
*/
private void addConstantsAndLabels(AsmProgram asm, ScopeRef scopeRef, String exportAsmLibrary) {
Scope scope = program.getScope().getScope(scopeRef);
Set<String> added = new LinkedHashSet<>();
Collection<Variable> scopeConstants = scope.getAllConstants(false);
// First add all constants without data that can become constants in KickAsm
for (Variable constantVar : scopeConstants) {
if (!hasData(constantVar) && hasExportAsmLibrary(constantVar, exportAsmLibrary)) {
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
if (asmName != null && !added.contains(asmName)) {
if (isIntTypeInScope(constantVar)) {
@ -518,7 +562,7 @@ public class Pass4CodeGeneration {
// Add constants without data that must be labels in KickAsm
for (Variable constantVar : scopeConstants) {
if (!hasData(constantVar)) {
if (!hasData(constantVar) && hasExportAsmLibrary(constantVar, exportAsmLibrary)) {
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
if (asmName != null && !added.contains(asmName)) {
if (constantVar.getType() instanceof SymbolTypePointer) {
@ -713,6 +757,8 @@ public class Pass4CodeGeneration {
}
if (variable.getInitValue() != null) {
// Variable has a constant init Value
if(exportAsmLibrary != null)
addGlobalStructSizeConstant(asm, scopeRef, variable);
ConstantValue constantValue = variable.getInitValue();
AsmDataChunk asmDataChunk = new AsmDataChunk();
addChunkData(asmDataChunk, constantValue, variable.getType(), variable.getArraySpec(), scopeRef);

View File

@ -2,11 +2,9 @@ package dk.camelot64.kickc.passes.calcs;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementCalling;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ProcedureRef;
@ -167,7 +165,7 @@ public class PassNCalcLiveRangeVariables extends PassNCalcBase<LiveRangeVariable
aliveVar)) {
// #828/26 - We check if the last is not a return of an imported .asm libraries routines.
Variable var = getProgram().getSymbolInfos().getVariable(aliveVar);
if(!var.isAsmLibraryReturn()) { // #820/26 - if it is a return, we skip ...
if(!var.isAsmExportLibraryReturn()) { // #820/26 - if it is a return, we skip ...
boolean added = liveRanges.addAlive(aliveVar,
previousStmt.getStatementIdx());
modified |= added;

View File

@ -8,25 +8,25 @@
#if defined(__CX16__) // For the moment only supported for the CX16 ...
#ifndef __STDIO_FILELEN
#define __STDIO_FILELEN 32
#endif
#ifndef __STDIO_FILELEN
#define __STDIO_FILELEN 32
#endif
#ifndef __STDIO_ERRORLEN
#define __STDIO_ERRORLEN 32
#endif
#ifndef __STDIO_ERRORLEN
#define __STDIO_ERRORLEN 32
#endif
#ifndef __STDIO_FILECOUNT
#define __STDIO_FILECOUNT 4
#endif
#ifndef __STDIO_FILECOUNT
#define __STDIO_FILECOUNT 4
#endif
typedef struct {
char filename[__STDIO_FILECOUNT*__STDIO_FILELEN];
char channel[__STDIO_FILECOUNT];
char device[__STDIO_FILECOUNT];
char secondary[__STDIO_FILECOUNT];
char status[__STDIO_FILECOUNT];
} FILE;
typedef struct file_handle_s {
char filename[__STDIO_FILECOUNT*__STDIO_FILELEN];
char channel[__STDIO_FILECOUNT];
char device[__STDIO_FILECOUNT];
char secondary[__STDIO_FILECOUNT];
char status[__STDIO_FILECOUNT];
} FILE;

View File

@ -0,0 +1,5 @@
extern __asm_import("set") char set_total;
extern __asm_import("set") char set_array[10];
extern __varcall __asm_import("set") __zp_reserve( 2,3 ) __zp(2) char get(__zp(3) char idx);

View File

@ -0,0 +1,22 @@
#pragma encoding(screencode_mixed)
#pragma var_model(zp)
#include <set_asm.h>
//#include "set.c"
extern char __asm_import("set") set_total = 10;
#include <conio.h>
#include <stdio.h>
#include <printf.h>
__export char r; // Ensure that r does not get deleted by the optimizer by exporting it.
void main() {
clrscr();
for(char i=0; i<set_total; i++) {
char data = set_array[i];
printf("set[%u] = %u\n", i, data);
}
}

View File

@ -0,0 +1,23 @@
#pragma encoding(screencode_mixed)
#pragma var_model(mem)
#pragma asm_library
#pragma calling(__varcall)
__export __asm_export char set_total = 10;
__export __asm_export char set_array[10] = {0,1,2,3,4,5,6,7,8,9};
char get(char idx) {
return set_array[idx];
}
void set(char idx, char n) {
set_array[idx] = n;
}
char sum2(char idx, char n) {
char r = set_array[idx];
idx++;
r += set_array[idx];
return r;
}

View File

@ -0,0 +1,5 @@
extern __asm_import("set") char set_total;
extern __asm_import("set") char set_array[10];
extern __varcall __asm_import("set") __zp_reserve( 2,3 ) __zp(2) char get(__zp(3) char idx);

View File

@ -0,0 +1,29 @@
#pragma encoding(screencode_mixed)
#pragma var_model(zp)
#define ARRAY_SIZE 10
#define DUMMY_SIZE 1024
struct set_array_s {
char x[ARRAY_SIZE];
char dummy[DUMMY_SIZE];
char y[ARRAY_SIZE];
};
#include <set_asm.h>
//#include "set.c"
#include <conio.h>
#include <stdio.h>
#include <printf.h>
__export char r; // Ensure that r does not get deleted by the optimizer by exporting it.
void main() {
clrscr();
for(char i=0; i<set_total; i++) {
char data = set_array.y[i];
printf("set[%u] = %u\n", i, data);
}
}

View File

@ -0,0 +1,42 @@
#pragma encoding(screencode_mixed)
#pragma var_model(mem)
#pragma asm_library
#pragma calling(__varcall)
//#include <conio.h>
#define ARRAY_SIZE 10
#define DUMMY_SIZE 1024
struct set_array_s {
char x[ARRAY_SIZE];
char dummy[DUMMY_SIZE];
char y[ARRAY_SIZE];
};
__asm_export char set_total = 10;
__asm_export struct set_array_s set_array;
char get_x(char idx) {
return set_array.x[idx];
}
char get_y(char idx) {
return set_array.y[idx];
}
void set_x(char idx, char n) {
set_array.x[idx] = n;
}
void set_y(char idx, char n) {
set_array.y[idx] = n;
}
char sum2(char idx) {
char r = set_array.x[idx];
idx++;
r += set_array.y[idx];
return r;
}