1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-27 06:34:19 +00:00

Started implementing register uplift with clobber checks. Added a bunch of missing fragments. Added a few failing tests of errors that should give a nice error message.

This commit is contained in:
Jesper Gravgaard 2017-07-30 16:31:59 +02:00
parent 3a14d2ef5b
commit 18bbde8a44
32 changed files with 272 additions and 141 deletions

View File

@ -145,7 +145,6 @@ public class Compiler {
log.append(program.getScope().getSymbolTableContents(Variable.class));
new Pass3RegistersFinalize(program, log).allocate();
new Pass3AssertNoCpuClobber(program, log).check();
new Pass3RegisterUplifting(program, log).uplift();
@ -156,7 +155,7 @@ public class Compiler {
new Pass3ZeroPageCoalesce(program, log).allocate();
new Pass3AssertNoCpuClobber(program, log).check();
//new Pass3CustomRegisters(program).allocate();
//new Pass3CustomRegisters(program).setRegister();
//new Pass3AssertNoCpuClobber(program, log).check();
}

View File

@ -0,0 +1 @@
sty {cowo1}

View File

@ -0,0 +1,2 @@
clc
adc #1

View File

@ -0,0 +1,2 @@
sec
sbc #{coby1}

View File

@ -0,0 +1,2 @@
cmp #{coby1}
bcs {la1}

View File

@ -0,0 +1,2 @@
cpx #{coby1}
bcs {la1}

View File

@ -0,0 +1,3 @@
tax
lda {zpby1}
sta {cowo1},x

View File

@ -0,0 +1,3 @@
txa
ldx {zpby1}
sta {cowo1},x

View File

@ -0,0 +1,3 @@
tya
ldy {zpby1}
sta {cowo1},y

View File

@ -0,0 +1,2 @@
lda {cowo1},x
tax

View File

@ -0,0 +1,3 @@
ldx {zpby1}
lda {cowo1},x
tax

View File

@ -0,0 +1,4 @@
txa
clc
adc #{coby1}
tax

View File

@ -0,0 +1,4 @@
txa
clc
adc {zpby1}
tax

View File

@ -0,0 +1,2 @@
lda {cowo1},y
tay

View File

@ -0,0 +1,3 @@
ldy {zpby1}
lda {cowo1},y
tay

View File

@ -0,0 +1,4 @@
tya
clc
adc {zpby1}
tay

View File

@ -0,0 +1,4 @@
txa
clc
adc #{coby1}
sta {zpby1}

View File

@ -0,0 +1,4 @@
tya
clc
adc #{coby1}
sta {zpby1}

View File

@ -0,0 +1,3 @@
tay
lda {zpby1}
sta ({zpptrby1}),y

View File

@ -0,0 +1,4 @@
txa
tay
lda {zpby1}
sta ({zpptrby1}),y

View File

@ -0,0 +1,2 @@
lda {zpby1}
sta ({zpptrby1}),y

View File

@ -61,4 +61,16 @@ public class LiveRangeEquivalenceClassSet {
equivalenceClasses.remove(equivalenceClass);
}
public RegisterAllocation createRegisterAllocation() {
RegisterAllocation allocation = new RegisterAllocation();
for (LiveRangeEquivalenceClass equivalenceClass : getEquivalenceClasses()) {
RegisterAllocation.Register register = equivalenceClass.getRegister();
for (VariableRef variable : equivalenceClass.getVariables()) {
allocation.setRegister(variable, register);
}
}
return allocation;
}
}

View File

@ -24,7 +24,7 @@ public class RegisterAllocation {
}
public void allocate(VariableRef variable, Register register) {
public void setRegister(VariableRef variable, Register register) {
if(variable!=null) {
allocation.put(variable, register);
}

View File

@ -30,11 +30,19 @@ public class Pass3AssertNoCpuClobber {
/** Check that no statement clobbers a CPU register used by an alive variable */
public void check() {
LiveRangeVariables liveRangeVariables = program.getScope().getLiveRangeVariables();
if(hasClobberProblem()) {
throw new RuntimeException("CLOBBER ERROR! See log for more info.");
}
}
/**
* Determines whether any statement in the program clobbers a CPU register used by an alive variable
* @return true if there is a clobber problem in the program
*/
public boolean hasClobberProblem() {
RegisterAllocation allocation = program.getScope().getAllocation();
LiveRangeVariables liveRangeVariables = program.getScope().getLiveRangeVariables();
boolean error = false;
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for (Statement statement : block.getStatements()) {
@ -66,11 +74,7 @@ public class Pass3AssertNoCpuClobber {
}
}
}
if(error) {
throw new RuntimeException("CLOBBER ERROR! See log for more info.");
}
return error;
}
@ -133,5 +137,4 @@ public class Pass3AssertNoCpuClobber {
return asm;
}
}

View File

@ -18,96 +18,96 @@ public class Pass3CustomRegisters {
RegisterAllocation allocation = program.getScope().getAllocation();
// Register allocation for loopnest.kc
allocation.allocate(new VariableRef("nest2::j#2"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("nest2::j#1"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("nest2::i#2"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("nest2::i#1"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("nest2::j#2"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("nest2::j#1"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("nest2::i#2"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("nest2::i#1"), RegisterAllocation.getRegisterY());
// Register allocation for fibmem.kc
/*
allocation.allocate(new VariableRef("i#1"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("i#2"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("$1"), new RegisterAllocation.RegisterAByte());
allocation.allocate(new VariableRef("$3"), new RegisterAllocation.RegisterALUByte());
allocation.allocate(new VariableRef("$4"), new RegisterAllocation.RegisterAByte());
allocation.setRegister(new VariableRef("i#1"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("i#2"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("$1"), new RegisterAllocation.RegisterAByte());
allocation.setRegister(new VariableRef("$3"), new RegisterAllocation.RegisterALUByte());
allocation.setRegister(new VariableRef("$4"), new RegisterAllocation.RegisterAByte());
*/
// Registers for postinc.kc
/*
allocation.allocate(new VariableRef("c#0"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("c#1"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("c#2"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("b#0"), new RegisterAllocation.RegisterZpByte(102));
allocation.allocate(new VariableRef("b#1"), new RegisterAllocation.RegisterZpByte(102));
allocation.allocate(new VariableRef("b#2"), new RegisterAllocation.RegisterZpByte(102));
allocation.allocate(new VariableRef("$1"), new RegisterAllocation.RegisterZpByte(101));
allocation.allocate(new VariableRef("a#0"), new RegisterAllocation.RegisterZpByte(103));
allocation.allocate(new VariableRef("a#1"), new RegisterAllocation.RegisterZpByte(103));
allocation.allocate(new VariableRef("a#2"), new RegisterAllocation.RegisterZpByte(103));
allocation.allocate(new VariableRef("$0"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("i#0"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("i#1"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("i#2"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("c#0"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("c#1"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("c#2"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("b#0"), new RegisterAllocation.RegisterZpByte(102));
allocation.setRegister(new VariableRef("b#1"), new RegisterAllocation.RegisterZpByte(102));
allocation.setRegister(new VariableRef("b#2"), new RegisterAllocation.RegisterZpByte(102));
allocation.setRegister(new VariableRef("$1"), new RegisterAllocation.RegisterZpByte(101));
allocation.setRegister(new VariableRef("a#0"), new RegisterAllocation.RegisterZpByte(103));
allocation.setRegister(new VariableRef("a#1"), new RegisterAllocation.RegisterZpByte(103));
allocation.setRegister(new VariableRef("a#2"), new RegisterAllocation.RegisterZpByte(103));
allocation.setRegister(new VariableRef("$0"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("i#0"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("i#1"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("i#2"), RegisterAllocation.getRegisterX());
*/
// Optimal Registers for flipper-rex2.kc
/*
allocation.allocate(new VariableRef("plot::i#0"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("plot::i#1"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("plot::i#2"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("plot::i#3"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("plot::i#4"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("plot::x#0"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("plot::x#1"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("plot::x#2"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("plot::y#0"), new RegisterAllocation.RegisterZpByte(100));
allocation.allocate(new VariableRef("plot::y#1"), new RegisterAllocation.RegisterZpByte(100));
allocation.allocate(new VariableRef("plot::y#2"), new RegisterAllocation.RegisterZpByte(100));
allocation.allocate(new VariableRef("plot::y#3"), new RegisterAllocation.RegisterZpByte(100));
allocation.allocate(new VariableRef("plot::y#4"), new RegisterAllocation.RegisterZpByte(100));
allocation.allocate(new VariableRef("plot::line#0"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.allocate(new VariableRef("plot::line#1"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.allocate(new VariableRef("plot::line#2"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.allocate(new VariableRef("plot::line#3"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.allocate(new VariableRef("plot::line#4"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.allocate(new VariableRef("plot::$3"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("prepare::i#0"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("prepare::i#1"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("prepare::i#2"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::srcIdx#0"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::srcIdx#0"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::srcIdx#1"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::srcIdx#2"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::srcIdx#3"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::srcIdx#4"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::dstIdx#0"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("flip::dstIdx#1"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("flip::dstIdx#2"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("flip::dstIdx#3"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("flip::dstIdx#4"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("flip::dstIdx#5"), RegisterAllocation.getRegisterY());
allocation.allocate(new VariableRef("flip::c#0"), new RegisterAllocation.RegisterZpByte(103));
allocation.allocate(new VariableRef("flip::c#1"), new RegisterAllocation.RegisterZpByte(103));
allocation.allocate(new VariableRef("flip::c#2"), new RegisterAllocation.RegisterZpByte(103));
allocation.allocate(new VariableRef("flip::r#0"), new RegisterAllocation.RegisterZpByte(104));
allocation.allocate(new VariableRef("flip::r#1"), new RegisterAllocation.RegisterZpByte(104));
allocation.allocate(new VariableRef("flip::r#2"), new RegisterAllocation.RegisterZpByte(104));
allocation.allocate(new VariableRef("flip::r#3"), new RegisterAllocation.RegisterZpByte(104));
allocation.allocate(new VariableRef("flip::r#4"), new RegisterAllocation.RegisterZpByte(104));
allocation.allocate(new VariableRef("flip::i#0"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::i#1"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::i#2"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("flip::$0"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("flip::$8"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("flip::$4"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("main::$1"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("main::$3"), RegisterAllocation.getRegisterA());
allocation.allocate(new VariableRef("main::c#0"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("main::c#1"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("main::c#2"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("main::c#3"), RegisterAllocation.getRegisterX());
allocation.allocate(new VariableRef("main::c#4"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("plot::i#0"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("plot::i#1"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("plot::i#2"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("plot::i#3"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("plot::i#4"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("plot::x#0"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("plot::x#1"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("plot::x#2"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("plot::y#0"), new RegisterAllocation.RegisterZpByte(100));
allocation.setRegister(new VariableRef("plot::y#1"), new RegisterAllocation.RegisterZpByte(100));
allocation.setRegister(new VariableRef("plot::y#2"), new RegisterAllocation.RegisterZpByte(100));
allocation.setRegister(new VariableRef("plot::y#3"), new RegisterAllocation.RegisterZpByte(100));
allocation.setRegister(new VariableRef("plot::y#4"), new RegisterAllocation.RegisterZpByte(100));
allocation.setRegister(new VariableRef("plot::line#0"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.setRegister(new VariableRef("plot::line#1"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.setRegister(new VariableRef("plot::line#2"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.setRegister(new VariableRef("plot::line#3"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.setRegister(new VariableRef("plot::line#4"), new RegisterAllocation.RegisterZpPointerByte(101));
allocation.setRegister(new VariableRef("plot::$3"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("prepare::i#0"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("prepare::i#1"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("prepare::i#2"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::srcIdx#0"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::srcIdx#0"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::srcIdx#1"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::srcIdx#2"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::srcIdx#3"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::srcIdx#4"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::dstIdx#0"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("flip::dstIdx#1"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("flip::dstIdx#2"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("flip::dstIdx#3"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("flip::dstIdx#4"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("flip::dstIdx#5"), RegisterAllocation.getRegisterY());
allocation.setRegister(new VariableRef("flip::c#0"), new RegisterAllocation.RegisterZpByte(103));
allocation.setRegister(new VariableRef("flip::c#1"), new RegisterAllocation.RegisterZpByte(103));
allocation.setRegister(new VariableRef("flip::c#2"), new RegisterAllocation.RegisterZpByte(103));
allocation.setRegister(new VariableRef("flip::r#0"), new RegisterAllocation.RegisterZpByte(104));
allocation.setRegister(new VariableRef("flip::r#1"), new RegisterAllocation.RegisterZpByte(104));
allocation.setRegister(new VariableRef("flip::r#2"), new RegisterAllocation.RegisterZpByte(104));
allocation.setRegister(new VariableRef("flip::r#3"), new RegisterAllocation.RegisterZpByte(104));
allocation.setRegister(new VariableRef("flip::r#4"), new RegisterAllocation.RegisterZpByte(104));
allocation.setRegister(new VariableRef("flip::i#0"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::i#1"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::i#2"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("flip::$0"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("flip::$8"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("flip::$4"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("main::$1"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("main::$3"), RegisterAllocation.getRegisterA());
allocation.setRegister(new VariableRef("main::c#0"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("main::c#1"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("main::c#2"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("main::c#3"), RegisterAllocation.getRegisterX());
allocation.setRegister(new VariableRef("main::c#4"), RegisterAllocation.getRegisterX());
*/
@ -121,16 +121,16 @@ public class Pass3CustomRegisters {
} else if (symbol instanceof VariableIntermediate || symbol instanceof VariableVersion) {
Variable var = (Variable) symbol;
if (symbol.getType().equals(SymbolTypeBasic.BYTE)) {
allocation.allocate(var.getRef(), new RegisterAllocation.RegisterZpByte(currentZp++));
allocation.setRegister(var.getRef(), new RegisterAllocation.RegisterZpByte(currentZp++));
} else if (symbol.getType().equals(SymbolTypeBasic.WORD)) {
allocation.allocate(var.getRef(), new RegisterAllocation.RegisterZpWord(currentZp));
allocation.setRegister(var.getRef(), new RegisterAllocation.RegisterZpWord(currentZp));
currentZp = currentZp + 2;
} else if (symbol.getType().equals(SymbolTypeBasic.BOOLEAN)) {
allocation.allocate(var.getRef(), new RegisterAllocation.RegisterZpBool(currentZp++));
allocation.setRegister(var.getRef(), new RegisterAllocation.RegisterZpBool(currentZp++));
} else if (symbol.getType().equals(SymbolTypeBasic.VOID)) {
// No need to allocate register for VOID value
// No need to setRegister register for VOID value
} else if (symbol.getType() instanceof SymbolTypePointer) {
allocation.allocate(var.getRef(), new RegisterAllocation.RegisterZpPointerByte(currentZp));
allocation.setRegister(var.getRef(), new RegisterAllocation.RegisterZpPointerByte(currentZp));
currentZp = currentZp + 2;
} else {
throw new RuntimeException("Unhandled variable type " + symbol);

View File

@ -5,7 +5,10 @@ import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.asm.parser.AsmClobber;
import dk.camelot64.kickc.icl.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/*** Uplift one variable into the A register - and check if the program still works */
public class Pass3RegisterUplifting {
@ -30,31 +33,56 @@ public class Pass3RegisterUplifting {
* Uplift one variable
*/
public void uplift() {
VariableRegisterWeights variableRegisterWeights = program.getScope().getVariableRegisterWeights();
LiveRangeEquivalenceClassSet equivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet();
double maxWeight = 0.0;
Variable maxVar = null;
LiveRangeEquivalenceClass maxEquivalenceClass = null;
Collection<Variable> allVars = program.getScope().getAllVariables(true);
RegisterAllocation allocation = program.getScope().getAllocation();
for (Variable variable : allVars) {
RegisterAllocation.Register currentRegister = allocation.getRegister(variable.getRef());
if (currentRegister!=null && currentRegister.isZp()) {
Double w = variableRegisterWeights.getWeight(variable.getRef());
if (w != null && w > maxWeight) {
maxWeight = w;
maxVar = variable;
}
// Find the live range equivalence class with the highest total weight
for (LiveRangeEquivalenceClass equivalenceClass : equivalenceClassSet.getEquivalenceClasses()) {
double totalWeight = 0.0;
List<VariableRef> vars = equivalenceClass.getVariables();
for (VariableRef var : vars) {
Double varWeight = variableRegisterWeights.getWeight(var);
totalWeight += varWeight;
}
if (maxWeight < totalWeight) {
maxEquivalenceClass = equivalenceClass;
maxWeight = totalWeight;
}
}
// Found max variable!
if(maxVar!=null) {
log.append("Uplifting of variable " + maxVar + " to A");
allocation.allocate(maxVar.getRef(), new RegisterAllocation.RegisterAByte());
if (maxEquivalenceClass != null) {
log.append("Uplifting max weight " + maxWeight + " live range equivalence class " + maxEquivalenceClass);
// Try the A register first
List<RegisterAllocation.Register> registers =
Arrays.asList(
RegisterAllocation.getRegisterA(),
RegisterAllocation.getRegisterX(),
RegisterAllocation.getRegisterY());
for (RegisterAllocation.Register register : registers) {
attemptUplift(maxEquivalenceClass, register);
}
}
RegisterAllocation allocation = program.getScope().getLiveRangeEquivalenceClassSet().createRegisterAllocation();
program.getScope().setAllocation(allocation);
}
private void attemptUplift(LiveRangeEquivalenceClass equivalenceClass, RegisterAllocation.Register register) {
RegisterAllocation allocation = program.getScope().getLiveRangeEquivalenceClassSet().createRegisterAllocation();
for (VariableRef var : equivalenceClass.getVariables()) {
allocation.setRegister(var, register);
}
program.getScope().setAllocation(allocation);
Pass3AssertNoCpuClobber clobber = new Pass3AssertNoCpuClobber(program, log);
if (clobber.hasClobberProblem()) {
log.append("Uplift to " + register + " resulted in clobber.");
} else {
log.append("Uplift to " + register + " succesfull.");
}
}

View File

@ -19,8 +19,17 @@ public class Pass3RegistersFinalize {
public void allocate() {
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet();
reallocateZp(liveRangeEquivalenceClassSet);
RegisterAllocation allocation = liveRangeEquivalenceClassSet.createRegisterAllocation();
program.getScope().setAllocation(allocation);
}
RegisterAllocation allocation = new RegisterAllocation();
/**
* Reallocate all ZP registers to minimize ZP usage
*
* @param liveRangeEquivalenceClassSet The
*/
private void reallocateZp(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
for (LiveRangeEquivalenceClass equivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
RegisterAllocation.Register register = equivalenceClass.getRegister();
if(register.isZp()) {
@ -28,14 +37,12 @@ public class Pass3RegistersFinalize {
VariableRef variable = equivalenceClass.getVariables().get(0);
Variable symbol = program.getScope().getVariable(variable);
register = allocateNewRegisterZp(symbol.getType());
log.append("Re-allocated ZP register from "+before+" to "+register.toString());
}
for (VariableRef variable : equivalenceClass.getVariables()) {
allocation.allocate(variable, register);
equivalenceClass.setRegister(register);
if(!before.equals(register.toString())) {
log.append("Re-allocated ZP register from " + before + " to " + register.toString());
}
}
}
program.getScope().setAllocation(allocation);
}
/**
@ -61,7 +68,7 @@ public class Pass3RegistersFinalize {
} else if (varType.equals(SymbolTypeBasic.BOOLEAN)) {
return new RegisterAllocation.RegisterZpBool(currentZp++);
} else if (varType.equals(SymbolTypeBasic.VOID)) {
// No need to allocate register for VOID value
// No need to setRegister register for VOID value
return null;
} else if (varType instanceof SymbolTypePointer) {
RegisterAllocation.RegisterZpPointerByte registerZpPointerByte =

View File

@ -178,7 +178,7 @@ public class Pass3ZeroPageAllocation {
} else if (varType.equals(SymbolTypeBasic.BOOLEAN)) {
return new RegisterAllocation.RegisterZpBool(currentZp++);
} else if (varType.equals(SymbolTypeBasic.VOID)) {
// No need to allocate register for VOID value
// No need to setRegister register for VOID value
return null;
} else if (varType instanceof SymbolTypePointer) {
RegisterAllocation.RegisterZpPointerByte registerZpPointerByte =

View File

@ -23,56 +23,63 @@ public class TestCompilationOutput extends TestCase {
}
public void testFlipper() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("flipper-rex2");
compileAndCompare("flipper-rex2");
}
public void testBresenham() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("bresenham");
compileAndCompare("bresenham");
}
public void testMinus() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("minus");
compileAndCompare("minus");
}
public void testLoopMin() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("loopmin");
compileAndCompare("loopmin");
}
public void testSumMin() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("summin");
compileAndCompare("summin");
}
public void testLoopSplit() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("loopsplit");
compileAndCompare("loopsplit");
}
public void testLoopNest() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("loopnest");
compileAndCompare("loopnest");
}
public void testLoopNest2() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("loopnest2");
compileAndCompare("loopnest2");
}
public void testFibMem() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("fibmem");
compileAndCompare("fibmem");
}
public void testPtrTest() throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile("ptrtest");
compileAndCompare("ptrtest");
}
public void testUseGlobal() throws IOException, URISyntaxException {
compileAndCompare("useglobal");
}
public void testUseUninitialized() throws IOException, URISyntaxException {
String filename = "useuninitialized";
compileAndCompare(filename);
}
public void testUseUndeclared() throws IOException, URISyntaxException {
compileAndCompare("useundeclared");
}
private void compileAndCompare(String filename) throws IOException, URISyntaxException {
TestCompilationOutput tester = new TestCompilationOutput();
tester.testFile(filename);
}
private void testFile(String fileName) throws IOException, URISyntaxException {
String inputPath = testPath + fileName + ".kc";

View File

@ -0,0 +1,6 @@
// Tests procedures using global variables (should not fail)
byte* SCREEN = $0400;
main();
void main() {
*SCREEN = 1;
}

View File

@ -0,0 +1,5 @@
// Uses an undeclared variable - should fail gracefully
main();
void main() {
byte s = b+1;
}

View File

@ -0,0 +1,7 @@
// Use an uninitialized variable - should fail gracefully!
main();
void main() {
byte b;
byte s=b+1;
}