mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-08 14:37:40 +00:00
Cleaned up code generation and register.isZp()
This commit is contained in:
parent
0298452244
commit
93456f0eb0
@ -457,7 +457,7 @@ public class AsmFragmentInstanceSpecFactory {
|
||||
Value boundValue = bindings.get(boundName);
|
||||
if(boundValue instanceof Variable) {
|
||||
Registers.Register boundRegister = ((Variable) boundValue).getAllocation();
|
||||
if(boundRegister != null && boundRegister.isZp()) {
|
||||
if(boundRegister != null && Registers.RegisterType.ZP_MEM.equals(boundRegister.getType())) {
|
||||
Registers.RegisterZpMem boundRegisterZp = (Registers.RegisterZpMem) boundRegister;
|
||||
if(registerZp.getZp() == boundRegisterZp.getZp()) {
|
||||
// Found other register with same ZP address!
|
||||
|
@ -56,8 +56,6 @@ public class Registers {
|
||||
|
||||
RegisterType getType();
|
||||
|
||||
boolean isZp();
|
||||
|
||||
boolean isMem();
|
||||
|
||||
int getBytes();
|
||||
@ -86,11 +84,6 @@ public class Registers {
|
||||
return RegisterType.MAIN_MEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMem() {
|
||||
return true;
|
||||
@ -156,11 +149,6 @@ public class Registers {
|
||||
return zp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMem() {
|
||||
return true;
|
||||
@ -210,11 +198,6 @@ public class Registers {
|
||||
@Override
|
||||
public abstract RegisterType getType();
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMem() {
|
||||
return false;
|
||||
@ -324,11 +307,6 @@ public class Registers {
|
||||
return RegisterType.CONSTANT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isZp() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMem() {
|
||||
return false;
|
||||
|
@ -1,6 +1,8 @@
|
||||
package dk.camelot64.kickc.model.values;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.Registers;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.symbols.Symbol;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
@ -39,9 +41,11 @@ public class ConstantSymbolPointer implements ConstantValue {
|
||||
Symbol symbol = scope.getSymbol(toSymbol);
|
||||
if(symbol instanceof Variable) {
|
||||
Registers.Register allocation = ((Variable) symbol).getAllocation();
|
||||
if(allocation!=null && allocation.isZp()) {
|
||||
if(allocation!=null && Registers.RegisterType.ZP_MEM.equals(allocation.getType())) {
|
||||
int zp = ((Registers.RegisterZpMem) allocation).getZp();
|
||||
return new ConstantInteger((long)zp, SymbolType.BYTE);
|
||||
} else if(allocation!=null && Registers.RegisterType.MAIN_MEM.equals(allocation.getType())) {
|
||||
throw new ConstantNotLiteral("Cannot calculate literal var pointer");
|
||||
}
|
||||
}
|
||||
// WE cannot calculate a literal value
|
||||
|
@ -102,7 +102,7 @@ public class Pass4AssertNoCpuClobber extends Pass2Base {
|
||||
for(VariableRef aliveVar : aliveVars) {
|
||||
Variable variable = getProgram().getSymbolInfos().getVariable(aliveVar);
|
||||
Registers.Register aliveVarRegister = variable.getAllocation();
|
||||
if(aliveVarRegister.isZp()) {
|
||||
if(aliveVarRegister.isMem()) {
|
||||
// No need to check a zp-register - here we are only interested in CPU registers
|
||||
continue;
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ public class Pass4AssertZeropageAllocation extends Pass2Base {
|
||||
Collection<Variable> allVariables = getSymbols().getAllVariables(true);
|
||||
for(Variable variable : allVariables) {
|
||||
Registers.Register allocation = variable.getAllocation();
|
||||
if(allocation!=null && allocation.isZp()) {
|
||||
if(allocation != null && Registers.RegisterType.ZP_MEM.equals(allocation.getType())) {
|
||||
int zp = ((Registers.RegisterZpMem) allocation).getZp();
|
||||
int sizeBytes = variable.getType().getSizeBytes();
|
||||
if(zp+sizeBytes>0x100) {
|
||||
if(zp + sizeBytes > 0x100) {
|
||||
// Allocation is outside ZP!
|
||||
throw new CompileError("Error! Variables used in program do not fit on zeropage. Maybe try compiling with -Ocoalesce to optimize ZP usage.");
|
||||
}
|
||||
|
@ -104,8 +104,7 @@ public class Pass4CodeGeneration {
|
||||
|
||||
// Generate global ZP labels
|
||||
asm.startChunk(currentScope, null, "Global Constants & labels");
|
||||
addConstants(asm, currentScope);
|
||||
addMemLabels(asm, currentScope);
|
||||
addConstantsAndLabels(asm, currentScope);
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
if(!block.getScope().equals(currentScope)) {
|
||||
// The current block is in a different scope. End the old scope.
|
||||
@ -127,8 +126,7 @@ public class Pass4CodeGeneration {
|
||||
// Start the new scope
|
||||
asm.addScopeBegin(AsmFormat.asmFix(block.getLabel().getFullName()));
|
||||
// Add all ZP labels for the scope
|
||||
addConstants(asm, currentScope);
|
||||
addMemLabels(asm, currentScope);
|
||||
addConstantsAndLabels(asm, currentScope);
|
||||
}
|
||||
|
||||
generateComments(asm, block.getComments());
|
||||
@ -289,48 +287,6 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add constant declarations for all scope constants
|
||||
*
|
||||
* @param asm The ASM program
|
||||
* @param scopeRef The scope
|
||||
*/
|
||||
private void addConstants(AsmProgram asm, ScopeRef scopeRef) {
|
||||
Scope scope = program.getScope().getScope(scopeRef);
|
||||
Collection<ConstantVar> scopeConstants = scope.getAllConstants(false);
|
||||
Set<String> added = new LinkedHashSet<>();
|
||||
for(ConstantVar constantVar : scopeConstants) {
|
||||
if(!hasData(constantVar)) {
|
||||
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
|
||||
if(asmName != null && !added.contains(asmName)) {
|
||||
added.add(asmName);
|
||||
// Add any comments
|
||||
generateComments(asm, constantVar.getComments());
|
||||
// Ensure encoding is good
|
||||
ensureEncoding(asm, constantVar.getValue());
|
||||
// Find the constant value calculation
|
||||
String asmConstant = AsmFormat.getAsmConstant(program, constantVar.getValue(), 99, scopeRef);
|
||||
if(constantVar.getType() instanceof SymbolTypePointer) {
|
||||
// Must use a label for pointers
|
||||
asm.addLabelDecl(AsmFormat.asmFix(asmName), asmConstant);
|
||||
} else if(SymbolType.isInteger(constantVar.getType()) && constantVar.getRef().getScopeDepth() > 0) {
|
||||
// Use label for integers referenced in other scope - to allow cross-scope referencing
|
||||
if(useLabelForConst(scopeRef, constantVar)) {
|
||||
// Use label for integers referenced in other scope - to allow cross-scope referencing
|
||||
asm.addLabelDecl(AsmFormat.asmFix(asmName), asmConstant);
|
||||
} else {
|
||||
// Use constant for constant integers not referenced outside scope
|
||||
asm.addConstant(AsmFormat.asmFix(asmName), asmConstant);
|
||||
}
|
||||
} else {
|
||||
// Use constant otherwise
|
||||
asm.addConstant(AsmFormat.asmFix(asmName), asmConstant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add comments to the assembler program
|
||||
*
|
||||
@ -424,18 +380,55 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add label declarations for all scope variables assigned to memory registers (before the scope code)
|
||||
* 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 scope The scope
|
||||
* @param scopeRef The scope
|
||||
*/
|
||||
private void addMemLabels(AsmProgram asm, ScopeRef scope) {
|
||||
Collection<Variable> scopeVars = program.getScope().getScope(scope).getAllVariables(false);
|
||||
private void addConstantsAndLabels(AsmProgram asm, ScopeRef scopeRef) {
|
||||
Scope scope = program.getScope().getScope(scopeRef);
|
||||
Set<String> added = new LinkedHashSet<>();
|
||||
Collection<ConstantVar> scopeConstants = scope.getAllConstants(false);
|
||||
|
||||
// Add all constants without data
|
||||
for(ConstantVar constantVar : scopeConstants) {
|
||||
if(!hasData(constantVar)) {
|
||||
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
|
||||
if(asmName != null && !added.contains(asmName)) {
|
||||
added.add(asmName);
|
||||
// Add any comments
|
||||
generateComments(asm, constantVar.getComments());
|
||||
// Ensure encoding is good
|
||||
ensureEncoding(asm, constantVar.getValue());
|
||||
// Find the constant value calculation
|
||||
String asmConstant = AsmFormat.getAsmConstant(program, constantVar.getValue(), 99, scopeRef);
|
||||
if(constantVar.getType() instanceof SymbolTypePointer) {
|
||||
// Must use a label for pointers
|
||||
asm.addLabelDecl(AsmFormat.asmFix(asmName), asmConstant);
|
||||
} else if(SymbolType.isInteger(constantVar.getType()) && constantVar.getRef().getScopeDepth() > 0) {
|
||||
// Use label for integers referenced in other scope - to allow cross-scope referencing
|
||||
if(useLabelForConst(scopeRef, constantVar)) {
|
||||
// Use label for integers referenced in other scope - to allow cross-scope referencing
|
||||
asm.addLabelDecl(AsmFormat.asmFix(asmName), asmConstant);
|
||||
} else {
|
||||
// Use constant for constant integers not referenced outside scope
|
||||
asm.addConstant(AsmFormat.asmFix(asmName), asmConstant);
|
||||
}
|
||||
} else {
|
||||
// Use constant otherwise
|
||||
asm.addConstant(AsmFormat.asmFix(asmName), asmConstant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add labels for memory variables without data
|
||||
Collection<Variable> scopeVars = scope.getAllVariables(false);
|
||||
for(Variable scopeVar : scopeVars) {
|
||||
Registers.Register register = scopeVar.getAllocation();
|
||||
if(register != null) {
|
||||
if(register.isZp()) {
|
||||
if(Registers.RegisterType.ZP_MEM.equals(register.getType())) {
|
||||
Registers.RegisterZpMem registerZp = (Registers.RegisterZpMem) register;
|
||||
String asmName = scopeVar.getAsmName();
|
||||
if(asmName != null && !added.contains(asmName)) {
|
||||
@ -445,7 +438,7 @@ public class Pass4CodeGeneration {
|
||||
asm.addLabelDecl(AsmFormat.asmFix(asmName), AsmFormat.getAsmNumber(registerZp.getZp()));
|
||||
added.add(asmName);
|
||||
}
|
||||
} else if(register instanceof Registers.RegisterMainMem && scopeVar.getDeclaredMemoryAddress() != null) {
|
||||
} else if(Registers.RegisterType.MAIN_MEM.equals(register.getType()) && scopeVar.getDeclaredMemoryAddress() != null) {
|
||||
String asmName = scopeVar.getAsmName();
|
||||
if(asmName != null && !added.contains(asmName)) {
|
||||
// Add any comments
|
||||
@ -459,9 +452,9 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add data for a scope (after the code)
|
||||
* Add constants with data and memory variables with data for a scope.
|
||||
* Added after the the code of the scope.
|
||||
*
|
||||
* @param asm The ASM program
|
||||
* @param scopeRef The scope
|
||||
@ -507,8 +500,7 @@ public class Pass4CodeGeneration {
|
||||
if(variable.isStoragePhiMaster())
|
||||
continue;
|
||||
// Skip if already added
|
||||
String asmName = variable.getAsmName();
|
||||
if(added.contains(asmName)) {
|
||||
if(added.contains(variable.getAsmName())) {
|
||||
continue;
|
||||
}
|
||||
if(variable.isStorageLoadStore() || variable.isStoragePhiVersion() || variable.isStorageIntermediate()) {
|
||||
@ -536,12 +528,12 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
AsmDataChunk asmDataChunk = new AsmDataChunk();
|
||||
addChunkData(asmDataChunk, ZeroConstantValues.zeroValue(variable.getType(), getScope()), variable.getType(), scopeRef);
|
||||
asmDataChunk.addToAsm(AsmFormat.asmFix(asmName), asm);
|
||||
asmDataChunk.addToAsm(AsmFormat.asmFix(variable.getAsmName()), asm);
|
||||
}
|
||||
} else {
|
||||
throw new InternalError("Not handled variable storage " + variable.toString());
|
||||
}
|
||||
added.add(asmName);
|
||||
added.add(variable.getAsmName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,7 @@ public class Pass4RegisterUpliftRemains extends Pass2Base {
|
||||
|
||||
for(LiveRangeEquivalenceClass equivalenceClass : equivalenceClasses) {
|
||||
Registers.Register register = equivalenceClass.getRegister();
|
||||
boolean isByte2 = register.isZp() && register.getBytes()==1;
|
||||
if(isByte2) {
|
||||
if(register.isMem() && register.getBytes()==1) {
|
||||
getLog().append("Attempting to uplift remaining variables in" + equivalenceClass);
|
||||
RegisterCombinationIterator combinationIterator = new RegisterCombinationIterator(Arrays.asList(equivalenceClass), getProgram().getRegisterPotentials());
|
||||
VariableRef variableRef = equivalenceClass.getVariables().get(0);
|
||||
|
@ -154,11 +154,11 @@ public class Pass4RegistersFinalize extends Pass2Base {
|
||||
Registers.Register register = equivalenceClass.getRegister();
|
||||
boolean reallocate = true;
|
||||
if(register!=null) {
|
||||
if(!register.isZp()) {
|
||||
if(!Registers.RegisterType.ZP_MEM.equals(register.getType())) {
|
||||
// Do not allocate non-ZP registers
|
||||
reallocate = false;
|
||||
} else if(register.isZp() && register.isNonRelocatable()) {
|
||||
// Do not allocate declared ZP registers
|
||||
} else if(register.isNonRelocatable()) {
|
||||
// Do not allocate non-relocatable ZP registers
|
||||
reallocate = false;
|
||||
}
|
||||
}
|
||||
|
@ -209,6 +209,8 @@ Uplift Scope [] 5: mem[1]:idx [ idx ]
|
||||
|
||||
Uplifting [main] best 409 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 409 combination mem[1]:idx [ idx ]
|
||||
Attempting to uplift remaining variables inmem[1]:idx [ idx ]
|
||||
Uplifting [] best 409 combination mem[1]:idx [ idx ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
|
@ -232,6 +232,8 @@ Uplift Scope [] 20: mem[1]:idx [ idx ]
|
||||
|
||||
Uplifting [main] best 409 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 409 combination mem[1]:idx [ idx ]
|
||||
Attempting to uplift remaining variables inmem[1]:idx [ idx ]
|
||||
Uplifting [] best 409 combination mem[1]:idx [ idx ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
|
@ -229,6 +229,10 @@ Uplift Scope [main]
|
||||
Uplifting [] best 49 combination mem[1]:bar_thing1 [ bar_thing1 ] mem[1]:bar_thing2 [ bar_thing2 ]
|
||||
Uplifting [foo] best 49 combination
|
||||
Uplifting [main] best 49 combination
|
||||
Attempting to uplift remaining variables inmem[1]:bar_thing1 [ bar_thing1 ]
|
||||
Uplifting [] best 49 combination mem[1]:bar_thing1 [ bar_thing1 ]
|
||||
Attempting to uplift remaining variables inmem[1]:bar_thing2 [ bar_thing2 ]
|
||||
Uplifting [] best 49 combination mem[1]:bar_thing2 [ bar_thing2 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
|
@ -371,6 +371,10 @@ Uplift Scope [foo]
|
||||
Uplifting [] best 576 combination mem[1]:bar_thing1 [ bar_thing1 ] mem[1]:bar_thing2 [ bar_thing2 ] zp[2]:4 [ bar_thing3 ]
|
||||
Uplifting [main] best 366 combination reg byte y [ main::j#2 main::j#1 ] reg byte x [ main::i#4 main::i#3 ]
|
||||
Uplifting [foo] best 366 combination
|
||||
Attempting to uplift remaining variables inmem[1]:bar_thing1 [ bar_thing1 ]
|
||||
Uplifting [] best 366 combination mem[1]:bar_thing1 [ bar_thing1 ]
|
||||
Attempting to uplift remaining variables inmem[1]:bar_thing2 [ bar_thing2 ]
|
||||
Uplifting [] best 366 combination mem[1]:bar_thing2 [ bar_thing2 ]
|
||||
Allocated (was zp[2]:4) zp[2]:2 [ bar_thing3 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
|
@ -194,6 +194,10 @@ Uplift Scope [main]
|
||||
Uplifting [] best 49 combination mem[1]:bar_thing1 [ bar_thing1 ] mem[1]:bar_thing2 [ bar_thing2 ]
|
||||
Uplifting [foo] best 49 combination
|
||||
Uplifting [main] best 49 combination
|
||||
Attempting to uplift remaining variables inmem[1]:bar_thing1 [ bar_thing1 ]
|
||||
Uplifting [] best 49 combination mem[1]:bar_thing1 [ bar_thing1 ]
|
||||
Attempting to uplift remaining variables inmem[1]:bar_thing2 [ bar_thing2 ]
|
||||
Uplifting [] best 49 combination mem[1]:bar_thing2 [ bar_thing2 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
|
@ -821,6 +821,10 @@ Attempting to uplift remaining variables inzp[1]:4 [ main::notreg_zp_flex ]
|
||||
Uplifting [main] best 237 combination zp[1]:4 [ main::notreg_zp_flex ]
|
||||
Attempting to uplift remaining variables inzp[1]:16 [ main::notreg_zp_abs ]
|
||||
Uplifting [main] best 237 combination zp[1]:16 [ main::notreg_zp_abs ]
|
||||
Attempting to uplift remaining variables inmem[1]:main::notreg_mem_flex [ main::notreg_mem_flex ]
|
||||
Uplifting [main] best 237 combination mem[1]:main::notreg_mem_flex [ main::notreg_mem_flex ]
|
||||
Attempting to uplift remaining variables inmem[1]:main::notreg_mem_abs [ main::notreg_mem_abs ]
|
||||
Uplifting [main] best 237 combination mem[1]:main::notreg_mem_abs [ main::notreg_mem_abs ]
|
||||
Attempting to uplift remaining variables inzp[1]:5 [ main::notreg_default ]
|
||||
Uplifting [main] best 237 combination zp[1]:5 [ main::notreg_default ]
|
||||
Allocated (was zp[1]:4) zp[1]:2 [ main::notreg_zp_flex ]
|
||||
|
@ -210,6 +210,8 @@ Uplift Scope [] 5: mem[1]:idx [ idx ]
|
||||
|
||||
Uplifting [main] best 409 combination reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 409 combination mem[1]:idx [ idx ]
|
||||
Attempting to uplift remaining variables inmem[1]:idx [ idx ]
|
||||
Uplifting [] best 409 combination mem[1]:idx [ idx ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
|
Loading…
x
Reference in New Issue
Block a user