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 {
}
/** 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
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.
* 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;
/** The names of all legal intrinsic procedures. */
final public static List<String> INTRINSIC_PROCEDURES = Arrays.asList(
Pass1PrintfIntrinsicRewrite.INTRINSIC_PRINTF_NAME,
@ -62,7 +60,7 @@ public class Procedure extends Scope {
}
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. */
@ -75,13 +73,13 @@ public class Procedure extends Scope {
FAR;
public static CallingDistance forCall(Bank from, Bank to) {
if(to==null) {
if(to.isCommon()) {
// NEAR: call to the common bank
return NEAR;
} else if(to.equals(from)) {
// NEAR: call to the same bank in the same banking area
return NEAR;
} else if(from==null) {
} else if(from.isCommon()) {
// CLOSE: call from common bank to any bank
return CLOSE;
} else if(!from.bankArea().equals(to.bankArea())) {
@ -146,10 +144,10 @@ public class Procedure extends Scope {
super(name, parentScope, segmentData);
this.procedureType = procedureType;
this.declaredInline = false;
this.bank = bank;
this.bank = Objects.requireNonNull(bank);
this.interruptType = null;
this.comments = new ArrayList<>();
this.segmentCode = segmentCode;
this.segmentCode = Objects.requireNonNull(segmentCode);
this.callingConvention = callingConvention;
this.constructorRefs = new ArrayList<>();
this.isConstructor = false;
@ -260,24 +258,6 @@ public class Procedure extends Scope {
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() {
return interruptType;
}
@ -338,9 +318,7 @@ public class Procedure extends Scope {
if(declaredIntrinsic) {
res.append("__intrinsic ");
}
if(isBanked()) {
res.append("__bank(").append(this.getBankArea()).append(", ").append(this.getBankNumber()).append(") ");
}
res.append(bank.toString());
if(!callingConvention.equals(CallingConvention.PHI_CALL)) {
res.append(getCallingConvention().getName()).append(" ");
}

View File

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

View File

@ -130,7 +130,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
Procedure initProc = program.getScope().getLocalProcedure(SymbolRef.INIT_PROC_NAME);
if(initProc == null) {
// 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.setParameters(new ArrayList<>());
program.getScope().add(initProc);
@ -187,7 +187,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
// Add the _start() procedure to the program
{
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<>());
program.getScope().add(startProcedure);
final ProcedureCompilation startProcedureCompilation = program.createProcedureCompilation(startProcedure.getRef());
@ -305,7 +305,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
}
break;
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;
case CParser.PRAGMA_RESOURCE:
String resourceFileName = pragmaParamString(pragmaParamSingle(ctx));
@ -450,7 +450,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
private String currentSegmentData = Scope.SEGMENT_DATA_DEFAULT;
/** 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. */
private String currentInterruptType;
@ -564,10 +564,10 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
parameterList.add(paramVar);
}
procedure.setParameters(parameterList);
procedure.setSegmentData(currentSegmentData); // When a procedure is defined, the currentDataSegment is to be set.
procedure.setSegmentCode(currentSegmentCode); // When a procedure is defined, the currentSegmentCode is to be set.
if(procedure.getBank() == null && currentBank != null) {
procedure.setBank(currentBank); // When a procedure is defined, the currentBank is to be set, or far calls won't work.
procedure.setSegmentData(currentSegmentData);
procedure.setSegmentCode(currentSegmentCode);
if(procedure.getBank().isCommon()) {
procedure.setBank(currentBank);
}
// Add return variable
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})),
program.getScope(),
Scope.SEGMENT_CODE_DEFAULT, Scope.SEGMENT_DATA_DEFAULT,
Procedure.CallingConvention.INTRINSIC_CALL, null);
Procedure.CallingConvention.INTRINSIC_CALL, Bank.COMMON);
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);
makeword4.add(hihi);

View File

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