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:
parent
d477cb9eae
commit
fab740f797
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
22
src/test/kc/library/export-global-variables-1/main.c
Normal file
22
src/test/kc/library/export-global-variables-1/main.c
Normal 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);
|
||||
}
|
||||
}
|
23
src/test/kc/library/export-global-variables-1/set.c
Normal file
23
src/test/kc/library/export-global-variables-1/set.c
Normal 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;
|
||||
}
|
|
@ -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);
|
29
src/test/kc/library/export-global-variables-2/main.c
Normal file
29
src/test/kc/library/export-global-variables-2/main.c
Normal 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);
|
||||
}
|
||||
}
|
42
src/test/kc/library/export-global-variables-2/set.c
Normal file
42
src/test/kc/library/export-global-variables-2/set.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user