1
0
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:
jespergravgaard 2019-10-20 12:12:36 +02:00
parent 0298452244
commit 93456f0eb0
15 changed files with 86 additions and 91 deletions

View File

@ -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!

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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.");
}

View File

@ -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());
}
}
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ]

View File

@ -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