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

Procedure.bank is now never null.

This commit is contained in:
jespergravgaard 2023-04-23 22:04:23 +02:00
parent 8c7a144579
commit 8b7afa4ad0
5 changed files with 57 additions and 65 deletions

View File

@ -116,8 +116,23 @@ public record Bank(String bankArea, Long bankNumber) {
public Bank { public Bank {
} }
/** The common/shared bank which is always visible. */
public static Bank COMMON = new Bank("", 0L);
/**
* Is this the common/shared bank which is always visible.
* @return True if this is the common bank
*/
public boolean isCommon() {
return COMMON.equals(this);
}
@Override @Override
public String toString() { public String toString() {
return "__bank(" + this.bankArea() + ", " + this.bankNumber() + ") "; if(isCommon()) {
return "";
} else {
return "__bank(" + this.bankArea() + ", " + this.bankNumber() + ") ";
}
} }
} }

View File

@ -44,11 +44,9 @@ public class Procedure extends Scope {
/** /**
* The bank that the procedure code is placed in. * The bank that the procedure code is placed in.
* Used to decide whether to produce near, close or far call code when generating calls. * Used to decide whether to produce near, close or far call code when generating calls.
* If null, the procedure is in a common bank (always visible) and all calls will be near.
*/ */
private Bank bank; private Bank bank;
/** The names of all legal intrinsic procedures. */ /** The names of all legal intrinsic procedures. */
final public static List<String> INTRINSIC_PROCEDURES = Arrays.asList( final public static List<String> INTRINSIC_PROCEDURES = Arrays.asList(
Pass1PrintfIntrinsicRewrite.INTRINSIC_PRINTF_NAME, Pass1PrintfIntrinsicRewrite.INTRINSIC_PRINTF_NAME,
@ -62,7 +60,7 @@ public class Procedure extends Scope {
} }
public void setBank(Bank bank) { public void setBank(Bank bank) {
this.bank = bank; this.bank = Objects.requireNonNull(bank);
} }
/** The bank distance between a caller and callee, which will determine the type of call needed. */ /** The bank distance between a caller and callee, which will determine the type of call needed. */
@ -75,13 +73,13 @@ public class Procedure extends Scope {
FAR; FAR;
public static CallingDistance forCall(Bank from, Bank to) { public static CallingDistance forCall(Bank from, Bank to) {
if(to==null) { if(to.isCommon()) {
// NEAR: call to the common bank // NEAR: call to the common bank
return NEAR; return NEAR;
} else if(to.equals(from)) { } else if(to.equals(from)) {
// NEAR: call to the same bank in the same banking area // NEAR: call to the same bank in the same banking area
return NEAR; return NEAR;
} else if(from==null) { } else if(from.isCommon()) {
// CLOSE: call from common bank to any bank // CLOSE: call from common bank to any bank
return CLOSE; return CLOSE;
} else if(!from.bankArea().equals(to.bankArea())) { } else if(!from.bankArea().equals(to.bankArea())) {
@ -146,10 +144,10 @@ public class Procedure extends Scope {
super(name, parentScope, segmentData); super(name, parentScope, segmentData);
this.procedureType = procedureType; this.procedureType = procedureType;
this.declaredInline = false; this.declaredInline = false;
this.bank = bank; this.bank = Objects.requireNonNull(bank);
this.interruptType = null; this.interruptType = null;
this.comments = new ArrayList<>(); this.comments = new ArrayList<>();
this.segmentCode = segmentCode; this.segmentCode = Objects.requireNonNull(segmentCode);
this.callingConvention = callingConvention; this.callingConvention = callingConvention;
this.constructorRefs = new ArrayList<>(); this.constructorRefs = new ArrayList<>();
this.isConstructor = false; this.isConstructor = false;
@ -260,24 +258,6 @@ public class Procedure extends Scope {
this.declaredInline = declaredInline; this.declaredInline = declaredInline;
} }
public boolean isBanked() {
return bank != null;
}
public Long getBankNumber() {
if(bank != null)
return bank.bankNumber();
else
return 0L;
}
public String getBankArea() {
if(bank != null)
return bank.bankArea();
else
return "";
}
public String getInterruptType() { public String getInterruptType() {
return interruptType; return interruptType;
} }
@ -338,9 +318,7 @@ public class Procedure extends Scope {
if(declaredIntrinsic) { if(declaredIntrinsic) {
res.append("__intrinsic "); res.append("__intrinsic ");
} }
if(isBanked()) { res.append(bank.toString());
res.append("__bank(").append(this.getBankArea()).append(", ").append(this.getBankNumber()).append(") ");
}
if(!callingConvention.equals(CallingConvention.PHI_CALL)) { if(!callingConvention.equals(CallingConvention.PHI_CALL)) {
res.append(getCallingConvention().getName()).append(" "); res.append(getCallingConvention().getName()).append(" ");
} }

View File

@ -30,7 +30,7 @@ public abstract class Scope implements Symbol {
this.name = name; this.name = name;
this.parentScope = parentScope; this.parentScope = parentScope;
this.symbols = new LinkedHashMap<>(); this.symbols = new LinkedHashMap<>();
this.segmentData = segmentData; this.segmentData = Objects.requireNonNull(segmentData);
setFullName(); setFullName();
} }

View File

@ -130,7 +130,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Procedure initProc = program.getScope().getLocalProcedure(SymbolRef.INIT_PROC_NAME); Procedure initProc = program.getScope().getLocalProcedure(SymbolRef.INIT_PROC_NAME);
if(initProc == null) { if(initProc == null) {
// Create the _init() procedure // Create the _init() procedure
initProc = new Procedure(SymbolRef.INIT_PROC_NAME, new SymbolTypeProcedure(SymbolType.VOID, new ArrayList<>()), program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL, null); initProc = new Procedure(SymbolRef.INIT_PROC_NAME, new SymbolTypeProcedure(SymbolType.VOID, new ArrayList<>()), program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL, Bank.COMMON);
initProc.setDeclaredInline(true); initProc.setDeclaredInline(true);
initProc.setParameters(new ArrayList<>()); initProc.setParameters(new ArrayList<>());
program.getScope().add(initProc); program.getScope().add(initProc);
@ -187,7 +187,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
// Add the _start() procedure to the program // Add the _start() procedure to the program
{ {
program.setStartProcedure(new ProcedureRef(SymbolRef.START_PROC_NAME)); program.setStartProcedure(new ProcedureRef(SymbolRef.START_PROC_NAME));
final Procedure startProcedure = new Procedure(SymbolRef.START_PROC_NAME, new SymbolTypeProcedure(SymbolType.VOID, new ArrayList<>()), program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL, null); final Procedure startProcedure = new Procedure(SymbolRef.START_PROC_NAME, new SymbolTypeProcedure(SymbolType.VOID, new ArrayList<>()), program.getScope(), Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Procedure.CallingConvention.PHI_CALL, Bank.COMMON);
startProcedure.setParameters(new ArrayList<>()); startProcedure.setParameters(new ArrayList<>());
program.getScope().add(startProcedure); program.getScope().add(startProcedure);
final ProcedureCompilation startProcedureCompilation = program.createProcedureCompilation(startProcedure.getRef()); final ProcedureCompilation startProcedureCompilation = program.createProcedureCompilation(startProcedure.getRef());
@ -305,7 +305,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
} }
break; break;
case CParser.PRAGMA_NOBANK: case CParser.PRAGMA_NOBANK:
this.currentBank = null; // When the current segment is null, the procedure will not be declared as far. this.currentBank = Bank.COMMON; // When the current segment is null, the procedure will not be declared as far.
break; break;
case CParser.PRAGMA_RESOURCE: case CParser.PRAGMA_RESOURCE:
String resourceFileName = pragmaParamString(pragmaParamSingle(ctx)); String resourceFileName = pragmaParamString(pragmaParamSingle(ctx));
@ -450,7 +450,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
private String currentSegmentData = Scope.SEGMENT_DATA_DEFAULT; private String currentSegmentData = Scope.SEGMENT_DATA_DEFAULT;
/** The current far segment. If null, the sequent procedures won't be banked. */ /** The current far segment. If null, the sequent procedures won't be banked. */
private Bank currentBank; private Bank currentBank = Bank.COMMON;
/** The current default interrupt type. */ /** The current default interrupt type. */
private String currentInterruptType; private String currentInterruptType;
@ -564,10 +564,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
parameterList.add(paramVar); parameterList.add(paramVar);
} }
procedure.setParameters(parameterList); procedure.setParameters(parameterList);
procedure.setSegmentData(currentSegmentData); // When a procedure is defined, the currentDataSegment is to be set. procedure.setSegmentData(currentSegmentData);
procedure.setSegmentCode(currentSegmentCode); // When a procedure is defined, the currentSegmentCode is to be set. procedure.setSegmentCode(currentSegmentCode);
if(procedure.getBank() == null && currentBank != null) { if(procedure.getBank().isCommon()) {
procedure.setBank(currentBank); // When a procedure is defined, the currentBank is to be set, or far calls won't work. procedure.setBank(currentBank);
} }
// Add return variable // Add return variable
if(!SymbolType.VOID.equals(procedure.getReturnType())) { if(!SymbolType.VOID.equals(procedure.getReturnType())) {
@ -2508,7 +2508,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
new SymbolTypeProcedure(SymbolType.DWORD, Arrays.asList(new SymbolType[]{SymbolType.BYTE, SymbolType.BYTE, SymbolType.BYTE, SymbolType.BYTE})), new SymbolTypeProcedure(SymbolType.DWORD, Arrays.asList(new SymbolType[]{SymbolType.BYTE, SymbolType.BYTE, SymbolType.BYTE, SymbolType.BYTE})),
program.getScope(), program.getScope(),
Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT, Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT,
Procedure.CallingConvention.INTRINSIC_CALL, null); Procedure.CallingConvention.INTRINSIC_CALL, Bank.COMMON);
makeword4.setDeclaredIntrinsic(true); makeword4.setDeclaredIntrinsic(true);
final Variable hihi = new Variable("hihi", Variable.Kind.PHI_MASTER, SymbolType.BYTE, makeword4, Variable.MemoryArea.ZEROPAGE_MEMORY, Scope.SEGMENT_DATA_DEFAULT, null); final Variable hihi = new Variable("hihi", Variable.Kind.PHI_MASTER, SymbolType.BYTE, makeword4, Variable.MemoryArea.ZEROPAGE_MEMORY, Scope.SEGMENT_DATA_DEFAULT, null);
makeword4.add(hihi); makeword4.add(hihi);

View File

@ -240,7 +240,7 @@ public class Pass4CodeGeneration {
if (i > 0) { if (i > 0) {
asm.addComment(signature.toString(), false); asm.addComment(signature.toString(), false);
} }
if(procedure.getBank() != null) { if(!procedure.getBank().isCommon()) {
asm.addComment(" " + procedure.getBank(), false); asm.addComment(" " + procedure.getBank(), false);
} }
} }
@ -583,31 +583,30 @@ public class Pass4CodeGeneration {
if (registerMainMem.getAddress() == null) { if (registerMainMem.getAddress() == null) {
// Generate into the data segment // Generate into the data segment
// Set segment // Set segment
// We check first the bank of the variable. Only local variables can be stored in the bank. // // We check first the bank of the variable. Only local variables can be stored in the bank.
// Parameters must be stored in main memory. // // Parameters must be stored in main memory.
if(!variable.getDataSegment().equals(Scope.SEGMENT_DATA_DEFAULT)) { // if(!variable.getDataSegment().equals(Scope.SEGMENT_DATA_DEFAULT)) {
if(scope instanceof Procedure) { // if(scope instanceof Procedure) {
Procedure procedure = (Procedure) scope; // Procedure procedure = (Procedure) scope;
List<Variable> parameters = procedure.getParameters(); // List<Variable> parameters = procedure.getParameters();
if (variable.isKindPhiVersion()) { // if (variable.isKindPhiVersion()) {
Variable master = variable.getPhiMaster(); // Variable master = variable.getPhiMaster();
if (master != null) { // if (master != null) {
if (parameters.contains(master) || master.getLocalName().equals("return")) { // if (parameters.contains(master) || master.getLocalName().equals("return")) {
variable.setDataSegment(Scope.SEGMENT_DATA_DEFAULT); // variable.setDataSegment(Scope.SEGMENT_DATA_DEFAULT);
} // }
} // }
} // }
} // }
} // }
//
// Intermediate variables are placed at the banked data segment, but parameters and return values are kept untouched. // // Intermediate variables are placed at the banked data segment, but parameters and return values are kept untouched.
if (variable.isKindIntermediate()) { // if (variable.isKindIntermediate()) {
if (scope instanceof Procedure) { // if (scope instanceof Procedure) {
Procedure procedure = (Procedure) scope; // Procedure procedure = (Procedure) scope;
variable.setDataSegment(procedure.getSegmentData()); // variable.setDataSegment(procedure.getSegmentData());
} // }
} // }
setCurrentSegment(variable.getDataSegment(), asm);
setCurrentSegment(variable.getDataSegment(), asm); setCurrentSegment(variable.getDataSegment(), asm);
// Add any comments // Add any comments
generateComments(asm, variable.getComments()); generateComments(asm, variable.getComments());