mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-22 13:29:18 +00:00
Gathered all pass results in Program.
This commit is contained in:
parent
5d21c6aa97
commit
64d9ff3f23
@ -1,6 +1,5 @@
|
||||
package dk.camelot64.kickc;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
import dk.camelot64.kickc.parser.KickCLexer;
|
||||
import dk.camelot64.kickc.parser.KickCParser;
|
||||
@ -15,62 +14,34 @@ import java.util.List;
|
||||
*/
|
||||
public class Compiler {
|
||||
|
||||
public static class CompilationResult {
|
||||
private AsmProgram asmProgram;
|
||||
private ControlFlowGraph graph;
|
||||
private ProgramScope scope;
|
||||
private CompileLog log;
|
||||
|
||||
public CompilationResult(AsmProgram asmProgram, ControlFlowGraph graph, ProgramScope scope, CompileLog log) {
|
||||
this.asmProgram = asmProgram;
|
||||
this.graph = graph;
|
||||
this.scope = scope;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public AsmProgram getAsmProgram() {
|
||||
return asmProgram;
|
||||
}
|
||||
|
||||
public ControlFlowGraph getGraph() {
|
||||
return graph;
|
||||
}
|
||||
|
||||
public ProgramScope getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
}
|
||||
}
|
||||
|
||||
public CompilationResult compile(final CharStream input) {
|
||||
public Program compile(final CharStream input) {
|
||||
CompileLog log = new CompileLog();
|
||||
try {
|
||||
KickCParser.FileContext file = pass0ParseInput(input, log);
|
||||
Program program = pass1GenerateSSA(file, log);
|
||||
pass2OptimizeSSA(program, log);
|
||||
pass3RegisterAllocation(program, log);
|
||||
AsmProgram asmProgram = pass4GenerateAsm(program, log);
|
||||
pass5OptimizeAsm(asmProgram, log);
|
||||
pass2OptimizeSSA(program);
|
||||
pass3RegisterAllocation(program);
|
||||
pass4GenerateAsm(program);
|
||||
pass5OptimizeAsm(program);
|
||||
|
||||
log.append("FINAL SYMBOL TABLE");
|
||||
log.append(program.getScope().getSymbolTableContents());
|
||||
log.append(program.getScope().getSymbolTableContents(program));
|
||||
log.append("FINAL CODE");
|
||||
log.append(asmProgram.toString());
|
||||
log.append(program.getAsm().toString());
|
||||
|
||||
return new CompilationResult(asmProgram, program.getGraph(), program.getScope(), log);
|
||||
return program;
|
||||
} catch (Exception e) {
|
||||
System.out.println(log.getLog());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public void pass5OptimizeAsm(AsmProgram asmProgram, CompileLog log) {
|
||||
public void pass5OptimizeAsm(Program program) {
|
||||
CompileLog log = program.getLog();
|
||||
List<Pass5AsmOptimization> pass5Optimizations = new ArrayList<>();
|
||||
pass5Optimizations.add(new Pass5NextJumpElimination(asmProgram, log));
|
||||
pass5Optimizations.add(new Pass5UnnecesaryLoadElimination(asmProgram, log));
|
||||
pass5Optimizations.add(new Pass5NextJumpElimination(program, log));
|
||||
pass5Optimizations.add(new Pass5UnnecesaryLoadElimination(program, log));
|
||||
boolean asmOptimized = true;
|
||||
while (asmOptimized) {
|
||||
asmOptimized = false;
|
||||
@ -80,113 +51,112 @@ public class Compiler {
|
||||
log.append("Succesful ASM optimization " + optimization.getClass().getSimpleName());
|
||||
asmOptimized = true;
|
||||
log.append("ASSEMBLER");
|
||||
log.append(asmProgram.toString());
|
||||
log.append(program.getAsm().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AsmProgram pass4GenerateAsm(Program program, CompileLog log) {
|
||||
public void pass4GenerateAsm(Program program) {
|
||||
|
||||
Pass4CodeGeneration pass4CodeGeneration = new Pass4CodeGeneration(program);
|
||||
AsmProgram asmProgram = pass4CodeGeneration.generate();
|
||||
pass4CodeGeneration.generate();
|
||||
|
||||
log.append("INITIAL ASM");
|
||||
log.append(asmProgram.toString());
|
||||
return asmProgram;
|
||||
program.getLog().append("INITIAL ASM");
|
||||
program.getLog().append(program.getAsm().toString());
|
||||
}
|
||||
|
||||
|
||||
private void pass3RegisterAllocation(Program program, CompileLog log) {
|
||||
private void pass3RegisterAllocation(Program program) {
|
||||
|
||||
new Pass3BlockSequencePlanner(program, log).plan();
|
||||
new Pass3BlockSequencePlanner(program).plan();
|
||||
|
||||
// Phi lifting ensures that all variables in phi-blocks are in different live range equivalence classes
|
||||
new Pass3PhiLifting(program, log).perform();
|
||||
new Pass3BlockSequencePlanner(program, log).plan();
|
||||
log.append("CONTROL FLOW GRAPH - PHI LIFTED");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
pass2AssertSSA(program, log);
|
||||
new Pass3PhiLifting(program).perform();
|
||||
new Pass3BlockSequencePlanner(program).plan();
|
||||
program.getLog().append("CONTROL FLOW GRAPH - PHI LIFTED");
|
||||
program.getLog().append(program.getGraph().toString(program));
|
||||
pass2AssertSSA(program);
|
||||
|
||||
new Pass3LiveRangesAnalysis(program, log).findLiveRanges();
|
||||
log.append("CONTROL FLOW GRAPH - LIVE RANGES");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
pass2AssertSSA(program, log);
|
||||
new Pass3LiveRangesAnalysis(program).findLiveRanges();
|
||||
program.getLog().append("CONTROL FLOW GRAPH - LIVE RANGES");
|
||||
program.getLog().append(program.getGraph().toString(program));
|
||||
pass2AssertSSA(program);
|
||||
|
||||
// Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap
|
||||
new Pass3PhiMemCoalesce(program, log).optimize();
|
||||
new Pass2CullEmptyBlocks(program, log).optimize();
|
||||
new Pass3BlockSequencePlanner(program, log).plan();
|
||||
new Pass3LiveRangesAnalysis(program, log).findLiveRanges();
|
||||
log.append("CONTROL FLOW GRAPH - PHI MEM COALESCED");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
pass2AssertSSA(program, log);
|
||||
new Pass3PhiMemCoalesce(program).optimize();
|
||||
new Pass2CullEmptyBlocks(program).optimize();
|
||||
new Pass3BlockSequencePlanner(program).plan();
|
||||
new Pass3LiveRangesAnalysis(program).findLiveRanges();
|
||||
program.getLog().append("CONTROL FLOW GRAPH - PHI MEM COALESCED");
|
||||
program.getLog().append(program.getGraph().toString(program));
|
||||
pass2AssertSSA(program);
|
||||
|
||||
new Pass3CallGraphAnalysis(program, log).findCallGraph();
|
||||
log.append("CALL GRAPH");
|
||||
log.append(program.getGraph().getCallGraph().toString());
|
||||
new Pass3CallGraphAnalysis(program).findCallGraph();
|
||||
program.getLog().append("CALL GRAPH");
|
||||
program.getLog().append(program.getCallGraph().toString());
|
||||
|
||||
new Pass3DominatorsAnalysis(program, log).findDominators();
|
||||
log.append("DOMINATORS");
|
||||
log.append(program.getGraph().getDominators().toString());
|
||||
new Pass3DominatorsAnalysis(program).findDominators();
|
||||
program.getLog().append("DOMINATORS");
|
||||
program.getLog().append(program.getDominators().toString());
|
||||
|
||||
new Pass3LoopAnalysis(program, log).findLoops();
|
||||
log.append("NATURAL LOOPS");
|
||||
log.append(program.getGraph().getLoopSet().toString());
|
||||
new Pass3LoopAnalysis(program).findLoops();
|
||||
program.getLog().append("NATURAL LOOPS");
|
||||
program.getLog().append(program.getLoopSet().toString());
|
||||
|
||||
new Pass3LoopDepthAnalysis(program, log).findLoopDepths();
|
||||
log.append("NATURAL LOOPS WITH DEPTH");
|
||||
log.append(program.getGraph().getLoopSet().toString());
|
||||
new Pass3LoopDepthAnalysis(program).findLoopDepths();
|
||||
program.getLog().append("NATURAL LOOPS WITH DEPTH");
|
||||
program.getLog().append(program.getLoopSet().toString());
|
||||
|
||||
new Pass3ZeroPageAllocation(program, log).allocate();
|
||||
new Pass3ZeroPageAllocation(program).allocate();
|
||||
|
||||
new Pass3VariableRegisterWeightAnalysis(program, log).findWeights();
|
||||
log.append("\nVARIABLE REGISTER WEIGHTS");
|
||||
log.append(program.getScope().getSymbolTableContents(Variable.class));
|
||||
new Pass3VariableRegisterWeightAnalysis(program).findWeights();
|
||||
program.getLog().append("\nVARIABLE REGISTER WEIGHTS");
|
||||
program.getLog().append(program.getScope().getSymbolTableContents(program ,Variable.class));
|
||||
|
||||
new Pass3RegistersFinalize(program, log).allocate();
|
||||
new Pass3AssertNoCpuClobber(program, log).check();
|
||||
new Pass3RegistersFinalize(program).allocate();
|
||||
new Pass3AssertNoCpuClobber(program).check();
|
||||
|
||||
new Pass3RegisterUplifting(program, log).uplift();
|
||||
log.append("REGISTER UPLIFTING");
|
||||
log.append(program.getScope().getSymbolTableContents(Variable.class));
|
||||
new Pass3AssertNoCpuClobber(program, log).check();
|
||||
new Pass3RegisterUplifting(program).uplift();
|
||||
program.getLog().append("REGISTER UPLIFTING");
|
||||
program.getLog().append(program.getScope().getSymbolTableContents(program, Variable.class));
|
||||
new Pass3AssertNoCpuClobber(program).check();
|
||||
|
||||
new Pass3ZeroPageCoalesce(program, log).allocate();
|
||||
new Pass3AssertNoCpuClobber(program, log).check();
|
||||
new Pass3ZeroPageCoalesce(program).allocate();
|
||||
new Pass3AssertNoCpuClobber(program).check();
|
||||
|
||||
//new Pass3CustomRegisters(program).setRegister();
|
||||
//new Pass3AssertNoCpuClobber(program, log).check();
|
||||
//new Pass3AssertNoCpuClobber(program).check();
|
||||
|
||||
}
|
||||
|
||||
public void pass2OptimizeSSA(Program program, CompileLog log) {
|
||||
public void pass2OptimizeSSA(Program program) {
|
||||
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
|
||||
optimizations.add(new Pass2CullEmptyBlocks(program, log));
|
||||
optimizations.add(new Pass2ConstantPropagation(program, log));
|
||||
optimizations.add(new Pass2ConstantAdditionElimination(program, log));
|
||||
optimizations.add(new Pass2AliasElimination(program, log));
|
||||
optimizations.add(new Pass2RedundantPhiElimination(program, log));
|
||||
optimizations.add(new Pass2SelfPhiElimination(program, log));
|
||||
optimizations.add(new Pass2ConditionalJumpSimplification(program, log));
|
||||
optimizations.add(new Pass2CullEmptyBlocks(program));
|
||||
optimizations.add(new Pass2ConstantPropagation(program));
|
||||
optimizations.add(new Pass2ConstantAdditionElimination(program));
|
||||
optimizations.add(new Pass2AliasElimination(program));
|
||||
optimizations.add(new Pass2RedundantPhiElimination(program));
|
||||
optimizations.add(new Pass2SelfPhiElimination(program));
|
||||
optimizations.add(new Pass2ConditionalJumpSimplification(program));
|
||||
|
||||
boolean ssaOptimized = true;
|
||||
while (ssaOptimized) {
|
||||
pass2AssertSSA(program, log);
|
||||
pass2AssertSSA(program);
|
||||
ssaOptimized = false;
|
||||
for (Pass2SsaOptimization optimization : optimizations) {
|
||||
boolean stepOptimized = optimization.optimize();
|
||||
if (stepOptimized) {
|
||||
log.append("Succesful SSA optimization " + optimization.getClass().getSimpleName() + "");
|
||||
program.getLog().append("Succesful SSA optimization " + optimization.getClass().getSimpleName() + "");
|
||||
ssaOptimized = true;
|
||||
log.append("CONTROL FLOW GRAPH");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
program.getLog().append("CONTROL FLOW GRAPH");
|
||||
program.getLog().append(program.getGraph().toString(program));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pass2AssertSSA(Program program, CompileLog log) {
|
||||
public void pass2AssertSSA(Program program) {
|
||||
List<Pass2SsaAssertion> assertions = new ArrayList<>();
|
||||
assertions.add(new Pass2AssertSymbols(program));
|
||||
assertions.add(new Pass2AssertBlocks(program));
|
||||
@ -209,44 +179,46 @@ public class Compiler {
|
||||
Pass1TypeInference pass1TypeInference = new Pass1TypeInference(programScope);
|
||||
pass1TypeInference.inferTypes(statementSequence);
|
||||
|
||||
Program program = new Program(programScope, log);
|
||||
|
||||
log.append("PROGRAM");
|
||||
log.append(statementSequence.toString(programScope));
|
||||
log.append(statementSequence.toString(program));
|
||||
log.append("SYMBOLS");
|
||||
log.append(programScope.getSymbolTableContents());
|
||||
log.append(programScope.getSymbolTableContents(program));
|
||||
|
||||
Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(programScope);
|
||||
ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence);
|
||||
|
||||
Program program = new Program(programScope, controlFlowGraph);
|
||||
program.setGraph(controlFlowGraph);
|
||||
|
||||
log.append("INITIAL CONTROL FLOW GRAPH");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
log.append(program.getGraph().toString(program));
|
||||
|
||||
Pass1EliminateEmptyBlocks pass1EliminateEmptyBlocks = new Pass1EliminateEmptyBlocks(program, log);
|
||||
Pass1EliminateEmptyBlocks pass1EliminateEmptyBlocks = new Pass1EliminateEmptyBlocks(program);
|
||||
boolean blockEliminated = pass1EliminateEmptyBlocks.eliminate();
|
||||
if (blockEliminated) {
|
||||
log.append("CONTROL FLOW GRAPH");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
log.append(program.getGraph().toString(program));
|
||||
}
|
||||
|
||||
Pass1ProcedureCallParameters pass1ProcedureCallParameters =
|
||||
new Pass1ProcedureCallParameters(program);
|
||||
program.setGraph(pass1ProcedureCallParameters.generate());
|
||||
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
log.append(program.getGraph().toString(program));
|
||||
|
||||
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
|
||||
new Pass1GenerateSingleStaticAssignmentForm(log, program);
|
||||
pass1GenerateSingleStaticAssignmentForm.generate();
|
||||
|
||||
log.append("CONTROL FLOW GRAPH SSA");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
log.append(program.getGraph().toString(program));
|
||||
|
||||
Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue =
|
||||
new Pass1ProcedureCallsReturnValue(program);
|
||||
program.setGraph(pass1ProcedureCallsReturnValue.generate());
|
||||
log.append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
|
||||
log.append(program.getGraph().toString(program.getScope()));
|
||||
log.append(program.getGraph().toString(program));
|
||||
return program;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ public class AsmFragment {
|
||||
/**
|
||||
* The symbol table.
|
||||
*/
|
||||
private ProgramScope symbols;
|
||||
private Program program;
|
||||
|
||||
/**
|
||||
* Binding of named values in the fragment to values (constants, variables, ...) .
|
||||
@ -33,37 +33,37 @@ public class AsmFragment {
|
||||
*/
|
||||
private String signature;
|
||||
|
||||
public AsmFragment(StatementConditionalJump conditionalJump, ControlFlowBlock block, ProgramScope symbols, ControlFlowGraph graph) {
|
||||
public AsmFragment(StatementConditionalJump conditionalJump, ControlFlowBlock block, Program program, ControlFlowGraph graph) {
|
||||
this.bindings = new LinkedHashMap<>();
|
||||
this.symbols = symbols;
|
||||
this.program = program;
|
||||
String conditionalJumpSignature = conditionalJumpSignature(conditionalJump, block, graph);
|
||||
setSignature(conditionalJumpSignature);
|
||||
}
|
||||
|
||||
public AsmFragment(StatementAssignment assignment, ProgramScope symbols) {
|
||||
public AsmFragment(StatementAssignment assignment, Program program ) {
|
||||
this.bindings = new LinkedHashMap<>();
|
||||
this.symbols = symbols;
|
||||
this.program = program;
|
||||
setSignature(assignmentSignature(assignment.getlValue(), assignment.getrValue1(), assignment.getOperator(), assignment.getrValue2()));
|
||||
}
|
||||
|
||||
public AsmFragment(LValue lValue, RValue rValue, ProgramScope symbols) {
|
||||
public AsmFragment(LValue lValue, RValue rValue, Program program) {
|
||||
this.bindings = new LinkedHashMap<>();
|
||||
this.symbols = symbols;
|
||||
this.program = program;
|
||||
setSignature(assignmentSignature(lValue, null, null, rValue));
|
||||
}
|
||||
|
||||
public AsmFragment(StatementAssignment assignment, StatementAssignment assignmentAlu, ProgramScope symbols) {
|
||||
public AsmFragment(StatementAssignment assignment, StatementAssignment assignmentAlu, Program program) {
|
||||
this.bindings = new LinkedHashMap<>();
|
||||
this.symbols = symbols;
|
||||
this.program = program;
|
||||
setSignature(assignmentWithAluSignature(assignment, assignmentAlu));
|
||||
|
||||
}
|
||||
|
||||
private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) {
|
||||
RValue assignmentRValue2 = assignment.getrValue2();
|
||||
Variable assignmentVar = symbols.getVariable((VariableRef) assignmentRValue2);
|
||||
Variable assignmentVar = program.getScope().getVariable((VariableRef) assignmentRValue2);
|
||||
|
||||
RegisterAllocation.Register rVal2Register = symbols.getRegister(assignmentVar);
|
||||
RegisterAllocation.Register rVal2Register = program.getRegister(assignmentVar);
|
||||
if(!rVal2Register.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) {
|
||||
throw new RuntimeException("Error! ALU register only allowed as rValue2. "+assignment);
|
||||
}
|
||||
@ -145,7 +145,7 @@ public class AsmFragment {
|
||||
} else {
|
||||
destinationLabel = destination.getLocalName();
|
||||
}
|
||||
Symbol destSymbol = symbols.getSymbol(destination);
|
||||
Symbol destSymbol = program.getScope().getSymbol(destination);
|
||||
signature.append(bind(new Label(destinationLabel, destSymbol.getScope(),false)));
|
||||
return signature.toString();
|
||||
}
|
||||
@ -217,10 +217,10 @@ public class AsmFragment {
|
||||
*/
|
||||
public String bind(Value value) {
|
||||
if(value instanceof VariableRef) {
|
||||
value = symbols.getVariable((VariableRef) value);
|
||||
value = program.getScope().getVariable((VariableRef) value);
|
||||
}
|
||||
if (value instanceof Variable) {
|
||||
value = symbols.getRegister((Variable) value);
|
||||
value = program.getRegister((Variable) value);
|
||||
} else if (value instanceof PointerDereferenceSimple) {
|
||||
PointerDereferenceSimple deref = (PointerDereferenceSimple) value;
|
||||
return "_star_" + bind(deref.getPointer());
|
||||
|
@ -17,8 +17,8 @@ public class ConstantBool implements Constant {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
if(scope==null) {
|
||||
public String toString(Program program) {
|
||||
if(program ==null) {
|
||||
return Boolean.toString(value);
|
||||
} else {
|
||||
return //"("+SymbolTypeBasic.BOOLEAN.getTypeName()+") "+
|
||||
|
@ -21,8 +21,8 @@ public class ConstantDouble implements Constant {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
if(scope==null) {
|
||||
public String toString(Program program) {
|
||||
if(program ==null) {
|
||||
return Double.toString(number);
|
||||
} else {
|
||||
return "(" + SymbolTypeBasic.VOID.getTypeName() + ") " + Double.toString(number);
|
||||
|
@ -38,8 +38,8 @@ public class ConstantInteger implements Constant {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
if (scope == null) {
|
||||
public String toString(Program program) {
|
||||
if (program == null) {
|
||||
return Integer.toString(number);
|
||||
} else {
|
||||
return "(" + getType().getTypeName() + ") " + Integer.toString(number);
|
||||
|
@ -17,8 +17,8 @@ public class ConstantString implements Constant {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
if (scope == null) {
|
||||
public String toString(Program program) {
|
||||
if (program == null) {
|
||||
return "\\" + value + "\\";
|
||||
} else {
|
||||
return "(" + SymbolTypeBasic.STRING.getTypeName() + ") " + "\\" + value + "\\";
|
||||
|
@ -80,7 +80,8 @@ public class ControlFlowBlock {
|
||||
return statements;
|
||||
}
|
||||
|
||||
public String toString(ControlFlowGraph graph, ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
ControlFlowGraph graph = program.getGraph();
|
||||
StringBuffer out = new StringBuffer();
|
||||
out.append(label.getFullName() + ":" );
|
||||
out.append(" from");
|
||||
@ -96,7 +97,7 @@ public class ControlFlowBlock {
|
||||
}
|
||||
out.append("\n");
|
||||
for (Statement statement : statements) {
|
||||
out.append(" "+statement.toString(scope)+"\n");
|
||||
out.append(" "+statement.toString(program)+"\n");
|
||||
}
|
||||
if(defaultSuccessor!=null) {
|
||||
out.append(" to:");
|
||||
|
@ -15,12 +15,6 @@ public class ControlFlowGraph {
|
||||
|
||||
/** Sequence of blocks used when generating ASM */
|
||||
private List<LabelRef> sequence;
|
||||
/** Information about dominators of all blocks*/
|
||||
private DominatorsGraph dominators;
|
||||
/** Information about loops. */
|
||||
private NaturalLoopSet loopSet;
|
||||
/** Information about calls. */
|
||||
private CallGraph callGraph;
|
||||
|
||||
public ControlFlowGraph(Map<LabelRef, ControlFlowBlock> blocks, LabelRef firstBlockRef) {
|
||||
this.blocks = blocks;
|
||||
@ -152,29 +146,7 @@ public class ControlFlowGraph {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setDominators(DominatorsGraph dominators) {
|
||||
this.dominators = dominators;
|
||||
}
|
||||
|
||||
public DominatorsGraph getDominators() {
|
||||
return dominators;
|
||||
}
|
||||
|
||||
public void setLoops(NaturalLoopSet loopSet) {
|
||||
this.loopSet = loopSet;
|
||||
}
|
||||
|
||||
public NaturalLoopSet getLoopSet() {
|
||||
return loopSet;
|
||||
}
|
||||
|
||||
public CallGraph getCallGraph() {
|
||||
return callGraph;
|
||||
}
|
||||
|
||||
public void setCallGraph(CallGraph callGraph) {
|
||||
this.callGraph = callGraph;
|
||||
}
|
||||
|
||||
public ControlFlowBlock getBlockFromStatementIdx(int statementIdx) {
|
||||
for (ControlFlowBlock block : getAllBlocks()) {
|
||||
@ -187,10 +159,15 @@ public class ControlFlowGraph {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString(ProgramScope scope) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(null);
|
||||
}
|
||||
|
||||
public String toString(Program program) {
|
||||
StringBuffer out = new StringBuffer();
|
||||
for (ControlFlowBlock block : getAllBlocks()) {
|
||||
out.append(block.toString(this, scope));
|
||||
out.append(block.toString(program));
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
@ -93,8 +93,8 @@ public class Label implements Symbol {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
if(scope==null) {
|
||||
public String toString(Program program) {
|
||||
if(program ==null) {
|
||||
return getFullName();
|
||||
} else {
|
||||
return "("+getType().getTypeName() + ") "+getFullName();
|
||||
|
@ -44,7 +44,7 @@ public class LiveRangeEquivalenceClass {
|
||||
if(variables.contains(variable)) {
|
||||
return;
|
||||
}
|
||||
LiveRangeVariables liveRanges = program.getScope().getLiveRangeVariables();
|
||||
LiveRangeVariables liveRanges = program.getLiveRangeVariables();
|
||||
LiveRange varLiveRange = liveRanges.getLiveRange(variable);
|
||||
if (liveRange.overlaps(varLiveRange)) {
|
||||
throw new RuntimeException("Compilation error! Variable live range overlaps live range equivalence class live range. " + variable);
|
||||
|
@ -34,8 +34,8 @@ public class PointerDereferenceIndexed implements PointerDereference {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
return "*(" + pointer.toString(scope) + " + " +index.toString(scope) + ')';
|
||||
public String toString(Program program) {
|
||||
return "*(" + pointer.toString(program) + " + " +index.toString(program) + ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ public class PointerDereferenceSimple implements PointerDereference {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
return "*(" + pointer.toString(scope) + ')';
|
||||
public String toString(Program program) {
|
||||
return "*(" + pointer.toString(program) + ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -71,11 +71,11 @@ public class Procedure extends Scope {
|
||||
return super.getFullName();
|
||||
}
|
||||
|
||||
public String getSymbolTableContents(ProgramScope scope, Class symbolClass) {
|
||||
public String getSymbolTableContents(Program program, Class symbolClass) {
|
||||
StringBuilder res = new StringBuilder();
|
||||
res.append(toString(scope));
|
||||
res.append(toString(program));
|
||||
res.append("\n");
|
||||
res.append(super.getSymbolTableContents(scope, symbolClass));
|
||||
res.append(super.getSymbolTableContents(program, symbolClass));
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
@ -84,33 +84,13 @@ public class Procedure extends Scope {
|
||||
return new SymbolTypeProcedure(returnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public RegisterAllocation getAllocation() {
|
||||
if(getScope()!=null) {
|
||||
return getScope().getAllocation();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@JsonIgnore
|
||||
public VariableRegisterWeights getVariableRegisterWeights() {
|
||||
if(getScope()!=null) {
|
||||
return getScope().getVariableRegisterWeights();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
StringBuilder res = new StringBuilder();
|
||||
res.append("("+getType().getTypeName() + ") ");
|
||||
res.append(getFullName());
|
||||
@ -120,7 +100,7 @@ public class Procedure extends Scope {
|
||||
for (Variable parameter : getParameters()) {
|
||||
if (!first) res.append(" , ");
|
||||
first = false;
|
||||
res.append(parameter.toString(scope));
|
||||
res.append(parameter.toString(program));
|
||||
}
|
||||
}
|
||||
res.append(")");
|
||||
|
@ -2,6 +2,8 @@ package dk.camelot64.kickc.icl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
|
||||
/** A KickC Intermediate Compiler Language (ICL) Program */
|
||||
public class Program {
|
||||
@ -10,13 +12,41 @@ public class Program {
|
||||
private ProgramScope scope;
|
||||
/** The control flow graph. */
|
||||
private ControlFlowGraph graph;
|
||||
/** The 6502 ASM program. */
|
||||
private AsmProgram asm;
|
||||
|
||||
/** The log containing information about the compilation process. */
|
||||
private CompileLog log;
|
||||
|
||||
/** Information about calls. */
|
||||
private CallGraph callGraph;
|
||||
/** Information about dominators of all blocks*/
|
||||
private DominatorsGraph dominators;
|
||||
/** Information about loops. */
|
||||
private NaturalLoopSet loopSet;
|
||||
|
||||
/** The register allocation for the vairalbes used during ASM code generation. */
|
||||
private RegisterAllocation allocation;
|
||||
/** The live ranges of all variables. */
|
||||
private LiveRangeVariables liveRangeVariables;
|
||||
/** Live range equivalence classes containing variables that do not have overlapping live ranges. */
|
||||
private LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet;
|
||||
/** The register weight of all variables describing how much the variable would theoretically gain from being in a register */
|
||||
private VariableRegisterWeights variableRegisterWeights;
|
||||
|
||||
@JsonCreator
|
||||
public Program(
|
||||
@JsonProperty("scope") ProgramScope scope,
|
||||
@JsonProperty("graph") ControlFlowGraph graph) {
|
||||
@JsonProperty("graph") ControlFlowGraph graph,
|
||||
@JsonProperty("asm") AsmProgram asm) {
|
||||
this.scope = scope;
|
||||
this.graph = graph;
|
||||
this.asm = asm;
|
||||
}
|
||||
|
||||
public Program(ProgramScope programScope, CompileLog log) {
|
||||
this.scope = programScope;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public ProgramScope getScope() {
|
||||
@ -35,6 +65,87 @@ public class Program {
|
||||
this.graph = graph;
|
||||
}
|
||||
|
||||
public AsmProgram getAsm() {
|
||||
return asm;
|
||||
}
|
||||
|
||||
public void setAsm(AsmProgram asm) {
|
||||
this.asm = asm;
|
||||
}
|
||||
|
||||
public CallGraph getCallGraph() {
|
||||
return callGraph;
|
||||
}
|
||||
|
||||
public void setCallGraph(CallGraph callGraph) {
|
||||
this.callGraph = callGraph;
|
||||
}
|
||||
|
||||
public void setDominators(DominatorsGraph dominators) {
|
||||
this.dominators = dominators;
|
||||
}
|
||||
|
||||
public DominatorsGraph getDominators() {
|
||||
return dominators;
|
||||
}
|
||||
|
||||
public void setLoops(NaturalLoopSet loopSet) {
|
||||
this.loopSet = loopSet;
|
||||
}
|
||||
|
||||
public NaturalLoopSet getLoopSet() {
|
||||
return loopSet;
|
||||
}
|
||||
|
||||
public void setAllocation(RegisterAllocation allocation) {
|
||||
this.allocation = allocation;
|
||||
}
|
||||
|
||||
public RegisterAllocation getAllocation() {
|
||||
return allocation;
|
||||
}
|
||||
|
||||
public RegisterAllocation.Register getRegister(Variable variable) {
|
||||
RegisterAllocation.Register register = null;
|
||||
if (allocation != null) {
|
||||
register = allocation.getRegister(variable.getRef());
|
||||
}
|
||||
return register;
|
||||
}
|
||||
|
||||
public void setLiveRangeVariables(LiveRangeVariables liveRangeVariables) {
|
||||
this.liveRangeVariables = liveRangeVariables;
|
||||
}
|
||||
|
||||
public LiveRangeVariables getLiveRangeVariables() {
|
||||
return liveRangeVariables;
|
||||
}
|
||||
|
||||
public void setLiveRangeEquivalenceClassSet(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
|
||||
this.liveRangeEquivalenceClassSet = liveRangeEquivalenceClassSet;
|
||||
}
|
||||
|
||||
public LiveRangeEquivalenceClassSet getLiveRangeEquivalenceClassSet() {
|
||||
return liveRangeEquivalenceClassSet;
|
||||
}
|
||||
|
||||
public void setVariableRegisterWeights(VariableRegisterWeights variableRegisterWeights) {
|
||||
this.variableRegisterWeights = variableRegisterWeights;
|
||||
}
|
||||
|
||||
public VariableRegisterWeights getVariableRegisterWeights() {
|
||||
return variableRegisterWeights;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
}
|
||||
|
||||
public void setLog(CompileLog log) {
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@ -43,13 +154,16 @@ public class Program {
|
||||
Program program = (Program) o;
|
||||
|
||||
if (scope != null ? !scope.equals(program.scope) : program.scope != null) return false;
|
||||
return graph != null ? graph.equals(program.graph) : program.graph == null;
|
||||
if (graph != null ? !graph.equals(program.graph) : program.graph != null) return false;
|
||||
return asm != null ? asm.equals(program.asm) : program.asm == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = scope != null ? scope.hashCode() : 0;
|
||||
result = 31 * result + (graph != null ? graph.hashCode() : 0);
|
||||
result = 31 * result + (asm != null ? asm.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,10 +9,6 @@ import java.util.HashMap;
|
||||
/** The program scope containing the symbols of a program */
|
||||
public class ProgramScope extends Scope {
|
||||
|
||||
private RegisterAllocation allocation;
|
||||
private LiveRangeVariables liveRangeVariables;
|
||||
private LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet;
|
||||
private VariableRegisterWeights variableRegisterWeights;
|
||||
|
||||
public ProgramScope() {
|
||||
super("", null);
|
||||
@ -23,10 +19,8 @@ public class ProgramScope extends Scope {
|
||||
@JsonProperty("name") String name,
|
||||
@JsonProperty("symbols") HashMap<String, Symbol> symbols,
|
||||
@JsonProperty("intermediateVarCount") int intermediateVarCount,
|
||||
@JsonProperty("intermediateLabelCount") int intermediateLabelCount,
|
||||
@JsonProperty("allocation") RegisterAllocation allocation) {
|
||||
@JsonProperty("intermediateLabelCount") int intermediateLabelCount) {
|
||||
super(name, symbols, intermediateVarCount, intermediateLabelCount);
|
||||
this.allocation = allocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -34,77 +28,16 @@ public class ProgramScope extends Scope {
|
||||
return new SymbolTypeProgram();
|
||||
}
|
||||
|
||||
public void setAllocation(RegisterAllocation allocation) {
|
||||
this.allocation = allocation;
|
||||
}
|
||||
|
||||
public RegisterAllocation.Register getRegister(Variable variable) {
|
||||
RegisterAllocation.Register register = null;
|
||||
if (allocation != null) {
|
||||
register = allocation.getRegister(variable.getRef());
|
||||
}
|
||||
return register;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegisterAllocation getAllocation() {
|
||||
return allocation;
|
||||
}
|
||||
|
||||
public void setLiveRangeVariables(LiveRangeVariables liveRangeVariables) {
|
||||
this.liveRangeVariables = liveRangeVariables;
|
||||
}
|
||||
|
||||
public LiveRangeVariables getLiveRangeVariables() {
|
||||
return liveRangeVariables;
|
||||
}
|
||||
|
||||
public void setLiveRangeEquivalenceClassSet(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
|
||||
this.liveRangeEquivalenceClassSet = liveRangeEquivalenceClassSet;
|
||||
}
|
||||
|
||||
public LiveRangeEquivalenceClassSet getLiveRangeEquivalenceClassSet() {
|
||||
return liveRangeEquivalenceClassSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ProgramScope that = (ProgramScope) o;
|
||||
|
||||
return allocation != null ? allocation.equals(that.allocation) : that.allocation == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + (allocation != null ? allocation.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getSymbolTableContents() {
|
||||
return getSymbolTableContents(this, null);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getSymbolTableContents(Class symbolClass) {
|
||||
return getSymbolTableContents(this, symbolClass);
|
||||
public String getSymbolTableContents(Program program) {
|
||||
return getSymbolTableContents(program, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSymbolTableContents(ProgramScope scope, Class symbolClass) {
|
||||
public String getSymbolTableContents(Program program, Class symbolClass) {
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = program.getLiveRangeEquivalenceClassSet();
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append(super.getSymbolTableContents(scope, symbolClass));
|
||||
out.append(super.getSymbolTableContents(program, symbolClass));
|
||||
if(liveRangeEquivalenceClassSet!=null) {
|
||||
out.append("\n");
|
||||
for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
@ -116,15 +49,8 @@ public class ProgramScope extends Scope {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return "program";
|
||||
}
|
||||
|
||||
public void setVariableRegisterWeights(VariableRegisterWeights variableRegisterWeights) {
|
||||
this.variableRegisterWeights = variableRegisterWeights;
|
||||
}
|
||||
|
||||
public VariableRegisterWeights getVariableRegisterWeights() {
|
||||
return variableRegisterWeights;
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public class RegisterAllocation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@ -134,7 +134,7 @@ public class RegisterAllocation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@ -182,7 +182,7 @@ public class RegisterAllocation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ public class RegisterAllocation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@ -261,7 +261,7 @@ public class RegisterAllocation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ public class RegisterAllocation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@ -323,7 +323,7 @@ public class RegisterAllocation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ public class RegisterAllocation {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
|
@ -210,25 +210,22 @@ public abstract class Scope implements Symbol {
|
||||
return (Procedure) getSymbol(ref);
|
||||
}
|
||||
|
||||
public abstract RegisterAllocation getAllocation();
|
||||
|
||||
public abstract VariableRegisterWeights getVariableRegisterWeights();
|
||||
|
||||
@JsonIgnore
|
||||
public String getSymbolTableContents(ProgramScope scope, Class symbolClass) {
|
||||
public String getSymbolTableContents(Program program, Class symbolClass) {
|
||||
ProgramScope scope = program.getScope();
|
||||
RegisterAllocation allocation = program.getAllocation();
|
||||
VariableRegisterWeights registerWeights = program.getVariableRegisterWeights();
|
||||
StringBuilder res = new StringBuilder();
|
||||
Set<String> names = symbols.keySet();
|
||||
List<String> sortedNames = new ArrayList<>(names);
|
||||
Collections.sort(sortedNames);
|
||||
RegisterAllocation allocation = getAllocation();
|
||||
VariableRegisterWeights registerWeights = getVariableRegisterWeights();
|
||||
for (String name : sortedNames) {
|
||||
Symbol symbol = symbols.get(name);
|
||||
if (symbol instanceof Scope) {
|
||||
res.append(((Scope) symbol).getSymbolTableContents(scope, symbolClass));
|
||||
res.append(((Scope) symbol).getSymbolTableContents(program, symbolClass));
|
||||
} else {
|
||||
if (symbolClass == null || symbolClass.isInstance(symbol)) {
|
||||
res.append(symbol.toString(scope));
|
||||
res.append(symbol.toString(program));
|
||||
if (symbol instanceof Variable && allocation != null) {
|
||||
RegisterAllocation.Register register = allocation.getRegister(((Variable) symbol).getRef());
|
||||
if (register != null) {
|
||||
|
@ -21,7 +21,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
})
|
||||
public interface Statement {
|
||||
|
||||
String toString(ProgramScope scope);
|
||||
String toString(Program program);
|
||||
|
||||
/** Set the index of the statement. Indexes are used during live range analysis. */
|
||||
void setIndex(Integer idx);
|
||||
|
@ -94,14 +94,14 @@ public class StatementAssignment extends StatementBase implements StatementLValu
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return
|
||||
super.idxString() +
|
||||
lValue.toString(scope) + " ← " +
|
||||
(rValue1==null?"":rValue1.toString(scope)+" ") +
|
||||
lValue.toString(program) + " ← " +
|
||||
(rValue1==null?"":rValue1.toString(program)+" ") +
|
||||
(operator==null?"":operator+" ") +
|
||||
rValue2.toString(scope) +
|
||||
super.aliveString(scope);
|
||||
rValue2.toString(program) +
|
||||
super.aliveString(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,11 +45,11 @@ public abstract class StatementBase implements Statement {
|
||||
return toString(null);
|
||||
}
|
||||
|
||||
public String aliveString(ProgramScope scope) {
|
||||
if(scope==null || scope.getLiveRangeVariables()==null) {
|
||||
public String aliveString(Program program) {
|
||||
if(program==null || program.getLiveRangeVariables()==null) {
|
||||
return "";
|
||||
}
|
||||
LiveRangeVariables liveRanges = scope.getLiveRangeVariables();
|
||||
LiveRangeVariables liveRanges = program.getLiveRangeVariables();
|
||||
List<VariableRef> alive = liveRanges.getAlive(this);
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(" [ ");
|
||||
|
@ -97,11 +97,11 @@ public class StatementCall extends StatementBase implements StatementLValue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
StringBuilder res = new StringBuilder();
|
||||
res.append(super.idxString());
|
||||
if (lValue != null) {
|
||||
res.append(lValue.toString(scope));
|
||||
res.append(lValue.toString(program));
|
||||
res.append(" ← ");
|
||||
}
|
||||
res.append("call ");
|
||||
@ -112,13 +112,13 @@ public class StatementCall extends StatementBase implements StatementLValue {
|
||||
}
|
||||
if (parameters != null) {
|
||||
for (RValue parameter : parameters) {
|
||||
res.append(parameter.toString(scope) + " ");
|
||||
res.append(parameter.toString(program) + " ");
|
||||
}
|
||||
}
|
||||
if (parametersByAssignment) {
|
||||
res.append("param-assignment");
|
||||
}
|
||||
res.append(super.aliveString(scope));
|
||||
res.append(super.aliveString(program));
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
|
@ -82,18 +82,18 @@ public class StatementConditionalJump extends StatementBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append(super.idxString());
|
||||
out.append("if(");
|
||||
if(rValue1!=null) {
|
||||
out.append(rValue1.toString(scope));
|
||||
out.append(rValue1.toString(program));
|
||||
out.append(operator.getOperator());
|
||||
}
|
||||
out.append(rValue2.toString(scope));
|
||||
out.append(rValue2.toString(program));
|
||||
out.append(") goto ");
|
||||
out.append(destination.getFullName());
|
||||
out.append(super.aliveString(scope));
|
||||
out.append(super.aliveString(program));
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@ public class StatementJump extends StatementBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
return super.idxString() + "goto " + destination.getFullName()+ super.aliveString(scope);
|
||||
public String toString(Program program) {
|
||||
return super.idxString() + "goto " + destination.getFullName()+ super.aliveString(program);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ public class StatementLabel extends StatementBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
return super.idxString() + label.getFullName() + ":"+super.aliveString(scope);
|
||||
public String toString(Program program) {
|
||||
return super.idxString() + label.getFullName() + ":"+super.aliveString(program);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,23 +63,23 @@ public class StatementPhiBlock extends StatementBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
List<PhiVariable> variables = new ArrayList<>(phiVariables);
|
||||
Collections.reverse(variables);
|
||||
for (PhiVariable phiVariable : variables) {
|
||||
s.append(super.idxString());
|
||||
s.append(phiVariable.getVariable().toString(scope));
|
||||
s.append(phiVariable.getVariable().toString(program));
|
||||
s.append(" ← phi(");
|
||||
for (PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
s.append(" ");
|
||||
s.append(phiRValue.getPredecessor().toString(null));
|
||||
s.append("/");
|
||||
RValue rValue = phiRValue.getrValue();
|
||||
s.append(rValue==null?"null":rValue.toString(scope));
|
||||
s.append(rValue==null?"null":rValue.toString(program));
|
||||
}
|
||||
s.append(" )");
|
||||
s.append(super.aliveString(scope));
|
||||
s.append(super.aliveString(program));
|
||||
s.append("\n ");
|
||||
}
|
||||
if(s.length()>0) {
|
||||
|
@ -30,8 +30,8 @@ public class StatementProcedureBegin extends StatementBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
return super.idxString() + "proc " + procedure.toString(scope) + super.aliveString(scope);
|
||||
public String toString(Program program) {
|
||||
return super.idxString() + "proc " + procedure.toString(program) + super.aliveString(program);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public class StatementProcedureEnd extends StatementBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
return super.idxString() + "endproc // " + procedure.getFullName() + "()"+super.aliveString(scope);
|
||||
public String toString(Program program) {
|
||||
return super.idxString() + "endproc // " + procedure.getFullName() + "()"+super.aliveString(program);
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ public class StatementReturn extends StatementBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
return super.idxString() + "return " + (value == null ? "" : value.toString(scope)) + super.aliveString(scope);
|
||||
public String toString(Program program) {
|
||||
return super.idxString() + "return " + (value == null ? "" : value.toString(program)) + super.aliveString(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -20,13 +20,13 @@ public class StatementSequence {
|
||||
return statements;
|
||||
}
|
||||
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
StringBuffer out = new StringBuffer();
|
||||
for (Statement statement : statements) {
|
||||
if(!(statement instanceof StatementLabel)) {
|
||||
out.append(" ");
|
||||
}
|
||||
out.append(statement.toString(scope)+"\n");
|
||||
out.append(statement.toString(program)+"\n");
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
@ -40,11 +40,11 @@ public class SymbolRef implements Value {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
if (scope == null) {
|
||||
public String toString(Program program) {
|
||||
if (program == null) {
|
||||
return fullName;
|
||||
} else {
|
||||
return scope.getSymbol(fullName).toString(scope);
|
||||
return program.getScope().getSymbol(fullName).toString(program);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,6 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
})
|
||||
public interface Value {
|
||||
|
||||
String toString(ProgramScope scope);
|
||||
String toString(Program program);
|
||||
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ public abstract class Variable implements Symbol {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return "(" + type.getTypeName() + (inferredType ? "~" : "") + ") " + getFullName();
|
||||
}
|
||||
|
||||
|
@ -13,14 +13,13 @@ import java.util.List;
|
||||
public class Pass1EliminateEmptyBlocks {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass1EliminateEmptyBlocks(Program program, CompileLog log) {
|
||||
public Pass1EliminateEmptyBlocks(Program program) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public boolean eliminate() {
|
||||
CompileLog log = program.getLog();
|
||||
ControlFlowGraph graph = program.getGraph();
|
||||
Collection<ControlFlowBlock> blocks = graph.getAllBlocks();
|
||||
List<LabelRef> removeList = new ArrayList<>();
|
||||
|
@ -17,21 +17,19 @@ import java.util.Stack;
|
||||
*/
|
||||
public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
private CompileLog log;
|
||||
private ProgramScope programScope;
|
||||
private Program program;
|
||||
private Stack<Scope> scopeStack;
|
||||
private StatementSequence sequence;
|
||||
|
||||
public Pass1GenerateStatementSequence(CompileLog log) {
|
||||
this.log = log;
|
||||
this.programScope = new ProgramScope();
|
||||
this.program = new Program(new ProgramScope(), log);
|
||||
this.scopeStack = new Stack<>();
|
||||
scopeStack.push(programScope);
|
||||
scopeStack.push(program.getScope());
|
||||
this.sequence = new StatementSequence();
|
||||
}
|
||||
|
||||
public ProgramScope getProgramScope() {
|
||||
return programScope;
|
||||
return program.getScope();
|
||||
}
|
||||
|
||||
private Scope getCurrentSymbols() {
|
||||
@ -221,7 +219,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
@Override
|
||||
public Void visitStmtDeclaration(KickCParser.StmtDeclarationContext ctx) {
|
||||
if (ctx.getChild(0).getText().equals("const")) {
|
||||
log.append("Const!" + ctx.getText());
|
||||
program.getLog().append("Const!" + ctx.getText());
|
||||
}
|
||||
SymbolType type = (SymbolType) visit(ctx.typeDecl());
|
||||
VariableUnversioned lValue = getCurrentSymbols().addVariable(ctx.NAME().getText(), type);
|
||||
@ -308,7 +306,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
|
||||
@Override
|
||||
public RValue visitExprCast(KickCParser.ExprCastContext ctx) {
|
||||
log.append("Cast type ignored!");
|
||||
program.getLog().append("Cast type ignored!");
|
||||
return (RValue) visit(ctx.expr());
|
||||
}
|
||||
|
||||
@ -462,7 +460,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
|
||||
for (PrePostModifier mod : modifiers) {
|
||||
Statement stmt = new StatementAssignment((LValue) mod.child, mod.operator, mod.child);
|
||||
parser.sequence.addStatement(stmt);
|
||||
parser.log.append("Adding pre/post-modifier "+stmt.toString(parser.programScope));
|
||||
parser.program.getLog().append("Adding pre/post-modifier "+stmt.toString(parser.program));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ import java.util.*;
|
||||
*/
|
||||
public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2AliasElimination(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
public Pass2AliasElimination(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
|
||||
@ -25,12 +25,12 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
replaceVariables(aliases.getReplacements());
|
||||
for (AliasSet aliasSet : aliases.getAliasSets()) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append(aliasSet.getKeepVar().toString(getSymbols()));
|
||||
str.append(aliasSet.getKeepVar().toString(getProgram()));
|
||||
str.append(" = ");
|
||||
for (VariableRef var : aliasSet.getEliminateVars()) {
|
||||
str.append(var.toString(getSymbols()) + " ");
|
||||
str.append(var.toString(getProgram()) + " ");
|
||||
}
|
||||
log.append("Alias " + str);
|
||||
getLog().append("Alias " + str);
|
||||
}
|
||||
deleteVariables(aliases.getSymbolsToRemove());
|
||||
return (aliases.size() > 0);
|
||||
@ -238,7 +238,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||
RValue rValue = phiRValue.getrValue();
|
||||
if (aliasSet.contains(rValue)) {
|
||||
log.append("Alias candidate removed " + rValue.toString(getSymbols()));
|
||||
getLog().append("Alias candidate removed " + rValue.toString(getProgram()));
|
||||
aliasSet.remove(rValue);
|
||||
break;
|
||||
}
|
||||
@ -272,7 +272,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
if(variable.getScopeNames().equals(alias.getScopeNames())){
|
||||
aliases.add(variable, alias);
|
||||
} else {
|
||||
log.append("Not aliassing across scopes: "+variable+" "+alias);
|
||||
getLog().append("Not aliassing across scopes: "+variable+" "+alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -290,7 +290,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
|
||||
if(variable.getScopeNames().equals(alias.getScopeNames())){
|
||||
aliases.add(variable, alias);
|
||||
} else {
|
||||
log.append("Not aliassing across scopes: "+variable+" "+alias);
|
||||
getLog().append("Not aliassing across scopes: "+variable+" "+alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
34
src/main/java/dk/camelot64/kickc/passes/Pass2Base.java
Normal file
34
src/main/java/dk/camelot64/kickc/passes/Pass2Base.java
Normal file
@ -0,0 +1,34 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.ControlFlowGraph;
|
||||
import dk.camelot64.kickc.icl.Program;
|
||||
import dk.camelot64.kickc.icl.ProgramScope;
|
||||
|
||||
/** Base class for a compiler pass */
|
||||
public class Pass2Base {
|
||||
|
||||
|
||||
private Program program;
|
||||
|
||||
public Pass2Base(Program program) {
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return program.getLog();
|
||||
}
|
||||
|
||||
public ControlFlowGraph getGraph() {
|
||||
return program.getGraph();
|
||||
}
|
||||
|
||||
public ProgramScope getSymbols() {
|
||||
return program.getScope();
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
}
|
@ -12,8 +12,8 @@ import java.util.Map;
|
||||
*/
|
||||
public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2ConditionalJumpSimplification(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
public Pass2ConditionalJumpSimplification(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,7 +56,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
|
||||
conditionalJump.setOperator(conditionAssignment.getOperator());
|
||||
conditionalJump.setrValue2(conditionAssignment.getrValue2());
|
||||
simpleConditionVars.add(conditionVar);
|
||||
log.append("Simple Condition " + conditionVar.toString(getSymbols()) + " " + conditionalJump.toString(getSymbols()));
|
||||
getLog().append("Simple Condition " + conditionVar.toString(getProgram()) + " " + conditionalJump.toString(getProgram()));
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
|
||||
private Map<VariableRef, Integer> usages;
|
||||
|
||||
public Pass2ConstantAdditionElimination(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
public Pass2ConstantAdditionElimination(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +66,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
ConstantInteger idxConstant = (ConstantInteger) pointerDereferenceIndexed.getIndex();
|
||||
int newPtr = ptrConstant.getNumber() + idxConstant.getNumber();
|
||||
assignment.setlValue(new PointerDereferenceSimple(new ConstantInteger(newPtr)));
|
||||
log.append("Consolidated assigned array index constant in assignment " + assignment.getlValue());
|
||||
getLog().append("Consolidated assigned array index constant in assignment " + assignment.getlValue());
|
||||
return true;
|
||||
}
|
||||
if(pointerDereferenceIndexed.getPointer() instanceof ConstantInteger && pointerDereferenceIndexed.getIndex() instanceof VariableRef) {
|
||||
@ -76,7 +76,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
ConstantInteger ptrConstant = (ConstantInteger) pointerDereferenceIndexed.getPointer();
|
||||
int newPtr = ptrConstant.getNumber() + consolidated.getNumber();
|
||||
pointerDereferenceIndexed.setPointer(new ConstantInteger(newPtr));
|
||||
log.append("Consolidated assigned array index constant in assignment " + assignment.getlValue());
|
||||
getLog().append("Consolidated assigned array index constant in assignment " + assignment.getlValue());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -91,7 +91,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
assignment.setrValue1(null);
|
||||
assignment.setOperator(new Operator("*"));
|
||||
assignment.setrValue2(new ConstantInteger(newPtr));
|
||||
log.append("Consolidated referenced array index constant in assignment " + assignment.getlValue());
|
||||
getLog().append("Consolidated referenced array index constant in assignment " + assignment.getlValue());
|
||||
return true;
|
||||
}
|
||||
if (assignment.getrValue1() instanceof ConstantInteger && assignment.getrValue2() instanceof VariableRef) {
|
||||
@ -101,7 +101,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
ConstantInteger ptrConstant = (ConstantInteger) assignment.getrValue1();
|
||||
int newPtr = ptrConstant.getNumber() + consolidated.getNumber();
|
||||
assignment.setrValue1(new ConstantInteger(newPtr));
|
||||
log.append("Consolidated referenced array index constant in assignment " + assignment.getlValue());
|
||||
getLog().append("Consolidated referenced array index constant in assignment " + assignment.getlValue());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -115,7 +115,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
if (consolidated != null) {
|
||||
ConstantInteger const1 = (ConstantInteger) assignment.getrValue1();
|
||||
assignment.setrValue1(new ConstantInteger(const1.getNumber() + consolidated.getNumber()));
|
||||
log.append("Consolidated constant in assignment " + assignment.getlValue());
|
||||
getLog().append("Consolidated constant in assignment " + assignment.getlValue());
|
||||
return true;
|
||||
}
|
||||
} else if (assignment.getrValue1() instanceof VariableRef && assignment.getrValue2() instanceof ConstantInteger) {
|
||||
@ -130,7 +130,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
} else {
|
||||
assignment.setrValue2(new ConstantInteger(newNumber));
|
||||
}
|
||||
log.append("Consolidated constant in assignment " + assignment.getlValue());
|
||||
getLog().append("Consolidated constant in assignment " + assignment.getlValue());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -145,7 +145,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
|
||||
*/
|
||||
private ConstantInteger consolidateSubConstants(VariableRef variable) {
|
||||
if(getUsages(variable) >1) {
|
||||
log.append("Multiple usages for variable. Not optimizing sub-constant "+variable.toString(getSymbols()));
|
||||
getLog().append("Multiple usages for variable. Not optimizing sub-constant "+variable.toString(getProgram()));
|
||||
return null;
|
||||
}
|
||||
Variable var = getSymbols().getVariable(variable);
|
||||
|
@ -9,8 +9,8 @@ import java.util.Map;
|
||||
/** Compiler Pass propagating constants in expressions eliminating constant variables */
|
||||
public class Pass2ConstantPropagation extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2ConstantPropagation(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
public Pass2ConstantPropagation(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -22,7 +22,7 @@ public class Pass2ConstantPropagation extends Pass2SsaOptimization {
|
||||
final Map<VariableRef, Constant> constants = findConstantVariables();
|
||||
for (VariableRef constantVar : constants.keySet()) {
|
||||
Constant constantValue = constants.get(constantVar);
|
||||
log.append("Constant " + constantVar.toString(getSymbols()) + " " + constantValue.toString(getSymbols()));
|
||||
getLog().append("Constant " + constantVar.toString(getProgram()) + " " + constantValue.toString(getProgram()));
|
||||
}
|
||||
removeAssignments(constants.keySet());
|
||||
deleteVariables(constants.keySet());
|
||||
|
@ -8,8 +8,8 @@ import java.util.*;
|
||||
/** Pass that culls empty control flow blocks from the program */
|
||||
public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2CullEmptyBlocks(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
public Pass2CullEmptyBlocks(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -68,7 +68,7 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
|
||||
LabelRef removeBlockLabelRef = removeBlock.getLabel();
|
||||
Label removeBlockLabel = getSymbols().getLabel(removeBlockLabelRef);
|
||||
removeBlockLabel.getScope().remove(removeBlockLabel);
|
||||
log.append("Culled Empty Block " + removeBlockLabel.toString(getSymbols()));
|
||||
getLog().append("Culled Empty Block " + removeBlockLabel.toString(getProgram()));
|
||||
}
|
||||
return remove.size()>0;
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import java.util.Map;
|
||||
/** Compiler Pass eliminating redundant phi functions */
|
||||
public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2RedundantPhiElimination(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
public Pass2RedundantPhiElimination(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -23,7 +23,7 @@ public class Pass2RedundantPhiElimination extends Pass2SsaOptimization {
|
||||
replaceVariables(aliases);
|
||||
for (VariableRef var : aliases.keySet()) {
|
||||
RValue alias = aliases.get(var);
|
||||
log.append("Redundant Phi " + var.toString(getSymbols()) + " " + alias.toString(getSymbols()));
|
||||
getLog().append("Redundant Phi " + var.toString(getProgram()) + " " + alias.toString(getProgram()));
|
||||
}
|
||||
deleteVariables(aliases.keySet());
|
||||
return aliases.size()>0;
|
||||
|
@ -8,8 +8,8 @@ import java.util.Iterator;
|
||||
/** Compiler Pass eliminating phi self assignments */
|
||||
public class Pass2SelfPhiElimination extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2SelfPhiElimination(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
public Pass2SelfPhiElimination(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,7 +28,7 @@ public class Pass2SelfPhiElimination extends Pass2SsaOptimization {
|
||||
if (phiRValue.getrValue().equals(phiVariable.getVariable())) {
|
||||
iterator.remove();
|
||||
optimized[0] = Boolean.TRUE;
|
||||
log.append("Self Phi Eliminated "+phiVariable.getVariable().toString(getSymbols()));
|
||||
getLog().append("Self Phi Eliminated "+phiVariable.getVariable().toString(getProgram()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,16 +11,14 @@ import java.util.*;
|
||||
*/
|
||||
public abstract class Pass2SsaOptimization {
|
||||
|
||||
protected CompileLog log;
|
||||
private Program program;
|
||||
|
||||
public Pass2SsaOptimization(Program program,CompileLog log) {
|
||||
public Pass2SsaOptimization(Program program) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
return program.getLog();
|
||||
}
|
||||
|
||||
public ControlFlowGraph getGraph() {
|
||||
@ -52,7 +50,7 @@ public abstract class Pass2SsaOptimization {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ProgramScope scope) {
|
||||
public String toString(Program program) {
|
||||
return "VOID";
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.asm.AsmInstruction;
|
||||
import dk.camelot64.kickc.asm.AsmLine;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
@ -12,22 +11,10 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/*** Ensures that no statement clobbers a CPU register used by an alive variable - and that assigning statements clobber the CPU registers they assign to */
|
||||
public class Pass3AssertNoCpuClobber {
|
||||
public class Pass3AssertNoCpuClobber extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3AssertNoCpuClobber(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
public Pass3AssertNoCpuClobber(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/** Check that no statement clobbers a CPU register used by an alive variable */
|
||||
@ -42,12 +29,12 @@ public class Pass3AssertNoCpuClobber {
|
||||
* @return true if there is a clobber problem in the program
|
||||
*/
|
||||
public boolean hasClobberProblem(boolean verbose, RegisterAllocation.Register register) {
|
||||
RegisterAllocation allocation = program.getScope().getAllocation();
|
||||
LiveRangeVariables liveRangeVariables = program.getScope().getLiveRangeVariables();
|
||||
RegisterAllocation allocation = getProgram().getAllocation();
|
||||
LiveRangeVariables liveRangeVariables = getProgram().getLiveRangeVariables();
|
||||
boolean clobberProblem = false;
|
||||
Pass4CodeGeneration.AsmCodegenAluState aluState = new Pass4CodeGeneration.AsmCodegenAluState();
|
||||
int registerCycles = 0;
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
|
||||
// Generate ASM and find clobber
|
||||
@ -76,8 +63,8 @@ public class Pass3AssertNoCpuClobber {
|
||||
// Alive and not assigned to - clobber not allowed!
|
||||
if(clobberRegisters.contains(aliveVarRegister)) {
|
||||
if(verbose) {
|
||||
log.append("Error! Alive variable " + aliveVar + " register " + aliveVarRegister + " clobbered by the ASM generated by statement " + statement);
|
||||
log.append(asm.toString(false));
|
||||
getLog().append("Error! Alive variable " + aliveVar + " register " + aliveVarRegister + " clobbered by the ASM generated by statement " + statement);
|
||||
getLog().append(asm.toString(false));
|
||||
}
|
||||
clobberProblem = true;
|
||||
}
|
||||
@ -85,7 +72,7 @@ public class Pass3AssertNoCpuClobber {
|
||||
}
|
||||
}
|
||||
if(!clobberProblem && register!=null) {
|
||||
log.append("Register Cycles: "+register+" "+registerCycles);
|
||||
getLog().append("Register Cycles: "+register+" "+registerCycles);
|
||||
}
|
||||
return clobberProblem;
|
||||
}
|
||||
@ -153,7 +140,7 @@ public class Pass3AssertNoCpuClobber {
|
||||
* @return The ASM code
|
||||
*/
|
||||
private AsmProgram getAsmProgram(Statement statement, ControlFlowBlock block, Pass4CodeGeneration.AsmCodegenAluState aluState) {
|
||||
Pass4CodeGeneration codegen = new Pass4CodeGeneration(program);
|
||||
Pass4CodeGeneration codegen = new Pass4CodeGeneration(getProgram());
|
||||
AsmProgram asm = new AsmProgram();
|
||||
codegen.generateStatementAsm(asm, block, statement, aluState);
|
||||
return asm;
|
||||
|
@ -1,29 +1,26 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
import dk.camelot64.kickc.icl.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.icl.LabelRef;
|
||||
import dk.camelot64.kickc.icl.Program;
|
||||
import dk.camelot64.kickc.icl.Scope;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/** Plan the optimal sequence for the blocks of the control flow graph */
|
||||
public class Pass3BlockSequencePlanner {
|
||||
public class Pass3BlockSequencePlanner extends Pass2Base {
|
||||
|
||||
private ControlFlowGraph graph;
|
||||
private ProgramScope scope;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3BlockSequencePlanner(Program program, CompileLog log) {
|
||||
this.graph = program.getGraph();
|
||||
this.scope = program.getScope();
|
||||
this.log = log;
|
||||
public Pass3BlockSequencePlanner(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public void plan() {
|
||||
ControlFlowBlock mainBlock = graph.getMainBlock();
|
||||
ControlFlowBlock mainBlock = getGraph().getMainBlock();
|
||||
if (mainBlock != null) {
|
||||
pushTodo(mainBlock);
|
||||
}
|
||||
pushTodo(graph.getFirstBlock());
|
||||
pushTodo(getGraph().getFirstBlock());
|
||||
List<LabelRef> sequence = new ArrayList<>();
|
||||
while(hasTodo()){
|
||||
ControlFlowBlock block = popTodo();
|
||||
@ -36,17 +33,17 @@ public class Pass3BlockSequencePlanner {
|
||||
}
|
||||
sequence.add(block.getLabel());
|
||||
if(block.getCallSuccessor()!=null) {
|
||||
pushTodo(graph.getCallSuccessor(block));
|
||||
pushTodo(getGraph().getCallSuccessor(block));
|
||||
}
|
||||
if(block.getConditionalSuccessor()!=null) {
|
||||
pushTodo(graph.getConditionalSuccessor(block));
|
||||
pushTodo(getGraph().getConditionalSuccessor(block));
|
||||
}
|
||||
if(graph.getDefaultSuccessor(block)!=null) {
|
||||
pushTodo(graph.getDefaultSuccessor(block));
|
||||
if(getGraph().getDefaultSuccessor(block)!=null) {
|
||||
pushTodo(getGraph().getDefaultSuccessor(block));
|
||||
}
|
||||
|
||||
}
|
||||
graph.setSequence(sequence);
|
||||
getGraph().setSequence(sequence);
|
||||
|
||||
StringBuilder entry = new StringBuilder();
|
||||
entry.append("Block Sequence Planned ");
|
||||
@ -54,7 +51,7 @@ public class Pass3BlockSequencePlanner {
|
||||
entry.append(labelRef.getFullName() + " ");
|
||||
|
||||
}
|
||||
log.append(entry.toString());
|
||||
getLog().append(entry.toString());
|
||||
}
|
||||
|
||||
|
||||
@ -62,7 +59,7 @@ public class Pass3BlockSequencePlanner {
|
||||
|
||||
void pushTodo(ControlFlowBlock block) {
|
||||
LabelRef blockRef = block.getLabel();
|
||||
Scope blockScope = this.scope.getSymbol(blockRef).getScope();
|
||||
Scope blockScope = getSymbols().getSymbol(blockRef).getScope();
|
||||
for (ScopeTodo todoScope : todoScopes) {
|
||||
if(todoScope.scope.equals(blockScope)) {
|
||||
todoScope.addTodo(block);
|
||||
|
@ -4,29 +4,18 @@ import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
/** Finds the call graph for the control flow graph - identifies all calls in all scopes and creates a graph from these. */
|
||||
public class Pass3CallGraphAnalysis {
|
||||
public class Pass3CallGraphAnalysis extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3CallGraphAnalysis(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
public Pass3CallGraphAnalysis(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public void findCallGraph() {
|
||||
CallGraph callGraph = new CallGraph();
|
||||
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
LabelRef scopeRef = getScopeRef(block, program);
|
||||
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
LabelRef scopeRef = getScopeRef(block, getProgram());
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if(statement instanceof StatementCall) {
|
||||
ProcedureRef procedure = ((StatementCall) statement).getProcedure();
|
||||
@ -36,7 +25,7 @@ public class Pass3CallGraphAnalysis {
|
||||
}
|
||||
}
|
||||
}
|
||||
program.getGraph().setCallGraph(callGraph);
|
||||
getProgram().setCallGraph(callGraph);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,7 @@ public class Pass3CustomRegisters {
|
||||
}
|
||||
|
||||
public void allocate() {
|
||||
RegisterAllocation allocation = program.getScope().getAllocation();
|
||||
RegisterAllocation allocation = program.getAllocation();
|
||||
|
||||
// Register allocation for loopnest.kc
|
||||
allocation.setRegister(new VariableRef("nest2::j#2"), RegisterAllocation.getRegisterX());
|
||||
|
@ -7,22 +7,10 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Finds the dominators for the control flow graph. */
|
||||
public class Pass3DominatorsAnalysis {
|
||||
public class Pass3DominatorsAnalysis extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3DominatorsAnalysis(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
public Pass3DominatorsAnalysis(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,14 +26,14 @@ public class Pass3DominatorsAnalysis {
|
||||
DominatorsGraph dominatorsGraph = new DominatorsGraph();
|
||||
|
||||
// Initialize dominators: Dom[first]={first}, Dom[block]={all}
|
||||
LabelRef firstBlock = program.getGraph().getFirstBlock().getLabel();
|
||||
LabelRef firstBlock = getGraph().getFirstBlock().getLabel();
|
||||
DominatorsBlock firstDominators = dominatorsGraph.addDominators(firstBlock);
|
||||
firstDominators.add(firstBlock);
|
||||
List<LabelRef> allBlocks = new ArrayList<>();
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
allBlocks.add(block.getLabel());
|
||||
}
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
if (!block.getLabel().equals(firstBlock)) {
|
||||
DominatorsBlock dominatorsBlock = dominatorsGraph.addDominators(block.getLabel());
|
||||
dominatorsBlock.addAll(allBlocks);
|
||||
@ -58,9 +46,9 @@ public class Pass3DominatorsAnalysis {
|
||||
boolean change = false;
|
||||
do {
|
||||
change = false;
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
if (!block.getLabel().equals(firstBlock)) {
|
||||
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(block);
|
||||
List<ControlFlowBlock> predecessors = getGraph().getPredecessors(block);
|
||||
DominatorsBlock newDominators = new DominatorsBlock();
|
||||
newDominators.addAll(allBlocks);
|
||||
for (ControlFlowBlock predecessor : predecessors) {
|
||||
@ -77,7 +65,7 @@ public class Pass3DominatorsAnalysis {
|
||||
}
|
||||
|
||||
} while (change);
|
||||
program.getGraph().setDominators(dominatorsGraph);
|
||||
getProgram().setDominators(dominatorsGraph);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,21 +4,16 @@ package dk.camelot64.kickc.passes;
|
||||
* Identify the alive intervals for all variables. Add the intervals to the ProgramScope.
|
||||
*/
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Pass3LiveRangesAnalysis {
|
||||
public class Pass3LiveRangesAnalysis extends Pass2Base {
|
||||
|
||||
private final Program program;
|
||||
private final CompileLog log;
|
||||
|
||||
public Pass3LiveRangesAnalysis(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
public Pass3LiveRangesAnalysis(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public void findLiveRanges() {
|
||||
@ -26,20 +21,20 @@ public class Pass3LiveRangesAnalysis {
|
||||
generateStatementIndexes();
|
||||
|
||||
LiveRangeVariables liveRanges = initializeLiveRanges();
|
||||
program.getScope().setLiveRangeVariables(liveRanges);
|
||||
getProgram().setLiveRangeVariables(liveRanges);
|
||||
//log.append("CONTROL FLOW GRAPH - LIVE RANGES");
|
||||
//log.append(program.getGraph().toString(program.getScope()));
|
||||
|
||||
boolean propagating;
|
||||
do {
|
||||
propagating = propagateLiveRanges(liveRanges);
|
||||
program.getScope().setLiveRangeVariables(liveRanges);
|
||||
log.append("Propagating live ranges...");
|
||||
getProgram().setLiveRangeVariables(liveRanges);
|
||||
getLog().append("Propagating live ranges...");
|
||||
//log.append("CONTROL FLOW GRAPH - LIVE RANGES");
|
||||
//log.append(program.getGraph().toString(program.getScope()));
|
||||
} while (propagating);
|
||||
|
||||
program.getScope().setLiveRangeVariables(liveRanges);
|
||||
getProgram().setLiveRangeVariables(liveRanges);
|
||||
}
|
||||
|
||||
|
||||
@ -48,7 +43,7 @@ public class Pass3LiveRangesAnalysis {
|
||||
*/
|
||||
private void generateStatementIndexes() {
|
||||
int currentIdx = 0;
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for (ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
statement.setIndex(currentIdx++);
|
||||
}
|
||||
@ -62,7 +57,7 @@ public class Pass3LiveRangesAnalysis {
|
||||
* @return The initial live ranges.
|
||||
*/
|
||||
private LiveRangeVariables initializeLiveRanges() {
|
||||
LiveRangeInitializer liveRangeInitializer = new LiveRangeInitializer(program);
|
||||
LiveRangeInitializer liveRangeInitializer = new LiveRangeInitializer(getProgram());
|
||||
return liveRangeInitializer.initialize();
|
||||
}
|
||||
|
||||
@ -202,7 +197,7 @@ public class Pass3LiveRangesAnalysis {
|
||||
* @return true if any propagation was done. (and more propagation is necessary to complete the live ranges)
|
||||
*/
|
||||
private boolean propagateLiveRanges(LiveRangeVariables liveRanges) {
|
||||
LiveRangePropagator liveRangePropagator = new LiveRangePropagator(program, liveRanges, log);
|
||||
LiveRangePropagator liveRangePropagator = new LiveRangePropagator(getProgram(), liveRanges);
|
||||
return liveRangePropagator.propagate();
|
||||
}
|
||||
|
||||
@ -217,7 +212,6 @@ public class Pass3LiveRangesAnalysis {
|
||||
* The variable live ranges being propagated.
|
||||
*/
|
||||
private LiveRangeVariables liveRanges;
|
||||
private CompileLog log;
|
||||
|
||||
/**
|
||||
* Has anything been modified.
|
||||
@ -234,10 +228,9 @@ public class Pass3LiveRangesAnalysis {
|
||||
*/
|
||||
private ControlFlowBlock currentBlock;
|
||||
|
||||
public LiveRangePropagator(Program program, LiveRangeVariables liveRanges, CompileLog log) {
|
||||
public LiveRangePropagator(Program program, LiveRangeVariables liveRanges) {
|
||||
this.program = program;
|
||||
this.liveRanges = liveRanges;
|
||||
this.log = log;
|
||||
this.modified = false;
|
||||
}
|
||||
|
||||
@ -291,7 +284,7 @@ public class Pass3LiveRangesAnalysis {
|
||||
LiveRange lValLiveRange = liveRanges.getLiveRange((VariableRef) lValue);
|
||||
if(lValLiveRange==null) {
|
||||
liveRanges.addEmptyAlive((VariableRef)lValue);
|
||||
log.append("Adding empty live range for unused variable "+lValue);
|
||||
program.getLog().append("Adding empty live range for unused variable "+lValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,22 +11,10 @@ import java.util.*;
|
||||
* <p>
|
||||
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
|
||||
*/
|
||||
public class Pass3LoopAnalysis {
|
||||
public class Pass3LoopAnalysis extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3LoopAnalysis(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
public Pass3LoopAnalysis(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -36,8 +24,8 @@ public class Pass3LoopAnalysis {
|
||||
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
|
||||
*/
|
||||
public void findLoops() {
|
||||
DominatorsGraph dominators = program.getGraph().getDominators();
|
||||
Collection<ControlFlowBlock> blocks = program.getGraph().getAllBlocks();
|
||||
DominatorsGraph dominators = getProgram().getDominators();
|
||||
Collection<ControlFlowBlock> blocks = getGraph().getAllBlocks();
|
||||
|
||||
// Look through graph for natural loop back edges
|
||||
NaturalLoopSet loopSet = new NaturalLoopSet();
|
||||
@ -47,7 +35,7 @@ public class Pass3LoopAnalysis {
|
||||
if (blockDominators.contains(successor)) {
|
||||
// Found a loop back edge!
|
||||
NaturalLoop loop = new NaturalLoop(successor, block.getLabel());
|
||||
log.append("Found back edge: "+loop.toString());
|
||||
getLog().append("Found back edge: "+loop.toString());
|
||||
loopSet.addLoop(loop);
|
||||
}
|
||||
}
|
||||
@ -64,8 +52,8 @@ public class Pass3LoopAnalysis {
|
||||
if(block.equals(loop.getHead())) {
|
||||
continue;
|
||||
}
|
||||
ControlFlowBlock controlFlowBlock = program.getGraph().getBlock(block);
|
||||
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(controlFlowBlock);
|
||||
ControlFlowBlock controlFlowBlock = getGraph().getBlock(block);
|
||||
List<ControlFlowBlock> predecessors = getGraph().getPredecessors(controlFlowBlock);
|
||||
for (ControlFlowBlock predecessor : predecessors) {
|
||||
if(!loopBlocks.contains(predecessor.getLabel()) && !todo.contains(predecessor.getLabel())) {
|
||||
todo.add(predecessor.getLabel());
|
||||
@ -73,7 +61,7 @@ public class Pass3LoopAnalysis {
|
||||
}
|
||||
}
|
||||
loop.setBlocks(loopBlocks);
|
||||
log.append("Populated: "+loop.toString());
|
||||
getLog().append("Populated: "+loop.toString());
|
||||
}
|
||||
|
||||
// Coalesce loops that are neither nested, nor disjoint
|
||||
@ -91,12 +79,12 @@ public class Pass3LoopAnalysis {
|
||||
loop.addTails(other.getTails());
|
||||
loop.addBlocks(other.getBlocks());
|
||||
loopSet.remove(other);
|
||||
log.append("Coalesced: "+loop.toString()) ;
|
||||
getLog().append("Coalesced: "+loop.toString()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
program.getGraph().setLoops(loopSet);
|
||||
getProgram().setLoops(loopSet);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
import java.util.*;
|
||||
@ -9,22 +8,10 @@ import java.util.*;
|
||||
* Finds the depth of loops in the control flow graph.
|
||||
* Uses the call graph and natural loops of the control flow graph.
|
||||
*/
|
||||
public class Pass3LoopDepthAnalysis {
|
||||
public class Pass3LoopDepthAnalysis extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3LoopDepthAnalysis(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
public Pass3LoopDepthAnalysis(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,8 +19,8 @@ public class Pass3LoopDepthAnalysis {
|
||||
* Uses the call graph and natural loops of the control flow graph.
|
||||
*/
|
||||
public void findLoopDepths() {
|
||||
CallGraph callGraph = program.getGraph().getCallGraph();
|
||||
NaturalLoopSet loopSet = program.getGraph().getLoopSet();
|
||||
CallGraph callGraph = getProgram().getCallGraph();
|
||||
NaturalLoopSet loopSet = getProgram().getLoopSet();
|
||||
|
||||
Deque<LabelRef> todo = new ArrayDeque<>();
|
||||
Set<LabelRef> done = new LinkedHashSet<>();
|
||||
@ -57,7 +44,7 @@ public class Pass3LoopDepthAnalysis {
|
||||
Collection<CallGraph.CallBlock.Call> calls = callingBlock.getCalls(currentScope);
|
||||
for (CallGraph.CallBlock.Call call : calls) {
|
||||
int callStatementIdx = call.getCallStatementIdx();
|
||||
ControlFlowBlock callingControlBlock = program.getGraph().getBlockFromStatementIdx(callStatementIdx);
|
||||
ControlFlowBlock callingControlBlock = getGraph().getBlockFromStatementIdx(callStatementIdx);
|
||||
Collection<NaturalLoop> callingLoops = loopSet.getLoopsContainingBlock(callingControlBlock.getLabel());
|
||||
for (NaturalLoop callingLoop : callingLoops) {
|
||||
int potentialDepth = callingLoop.getDepth()+1;
|
||||
@ -72,22 +59,22 @@ public class Pass3LoopDepthAnalysis {
|
||||
}
|
||||
|
||||
private void findLoopDepth(LabelRef currentScope, int initialDepth) {
|
||||
NaturalLoopSet loopSet = program.getGraph().getLoopSet();
|
||||
NaturalLoopSet loopSet = getProgram().getLoopSet();
|
||||
// Find loops in the current scope block
|
||||
List<NaturalLoop> currentScopeLoops = new ArrayList<>();
|
||||
for (NaturalLoop loop : loopSet.getLoops()) {
|
||||
LabelRef loopHead = loop.getHead();
|
||||
ControlFlowBlock loopHeadBlock = program.getGraph().getBlock(loopHead);
|
||||
LabelRef scopeRef = Pass3CallGraphAnalysis.getScopeRef(loopHeadBlock, program);
|
||||
ControlFlowBlock loopHeadBlock = getGraph().getBlock(loopHead);
|
||||
LabelRef scopeRef = Pass3CallGraphAnalysis.getScopeRef(loopHeadBlock, getProgram());
|
||||
if(scopeRef.equals(currentScope)) {
|
||||
// Loop is inside current scope block!
|
||||
currentScopeLoops.add(loop);
|
||||
}
|
||||
}
|
||||
|
||||
log.append("Found "+currentScopeLoops.size()+" loops in scope ["+currentScope.toString()+"]");
|
||||
getLog().append("Found "+currentScopeLoops.size()+" loops in scope ["+currentScope.toString()+"]");
|
||||
for (NaturalLoop loop : currentScopeLoops) {
|
||||
log.append(" "+loop.toString());
|
||||
getLog().append(" "+loop.toString());
|
||||
}
|
||||
|
||||
// Find loop nesting depths in current scope loops
|
||||
|
@ -22,11 +22,8 @@ public class Pass3PhiLifting {
|
||||
|
||||
private final Program program;
|
||||
|
||||
private final CompileLog log;
|
||||
|
||||
public Pass3PhiLifting(Program program, CompileLog log) {
|
||||
public Pass3PhiLifting(Program program) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public void perform() {
|
||||
@ -80,7 +77,7 @@ public class Pass3PhiLifting {
|
||||
if(block.getLabel().equals(predecessorBlock.getDefaultSuccessor())) {
|
||||
predecessorBlock.setDefaultSuccessor(newBlock.getLabel());
|
||||
}
|
||||
log.append("Added new block during phi lifting "+newBlock.getLabel() + "(between "+predecessorRef+" and "+block.getLabel()+")");
|
||||
program.getLog().append("Added new block during phi lifting "+newBlock.getLabel() + "(between "+predecessorRef+" and "+block.getLabel()+")");
|
||||
} else {
|
||||
newBlock = graph.getBlock(newBlockRef);
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ import java.util.Map;
|
||||
*/
|
||||
public class Pass3PhiMemCoalesce extends Pass2SsaOptimization {
|
||||
|
||||
public Pass3PhiMemCoalesce(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
public Pass3PhiMemCoalesce(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -32,13 +32,13 @@ public class Pass3PhiMemCoalesce extends Pass2SsaOptimization {
|
||||
EquivalenceClassPhiInitializer equivalenceClassPhiInitializer = new EquivalenceClassPhiInitializer(getProgram());
|
||||
equivalenceClassPhiInitializer.visitGraph(getGraph());
|
||||
LiveRangeEquivalenceClassSet phiEquivalenceClasses = equivalenceClassPhiInitializer.getPhiEquivalenceClasses();
|
||||
log.append("Created " + phiEquivalenceClasses.size() + " initial phi equivalence classes");
|
||||
getLog().append("Created " + phiEquivalenceClasses.size() + " initial phi equivalence classes");
|
||||
PhiMemCoalescer phiMemCoalescer = new PhiMemCoalescer(phiEquivalenceClasses);
|
||||
phiMemCoalescer.visitGraph(getGraph());
|
||||
removeAssignments(phiMemCoalescer.getRemove());
|
||||
replaceVariables(phiMemCoalescer.getReplace());
|
||||
deleteVariables(phiMemCoalescer.getRemove());
|
||||
log.append("Coalesced down to " + phiEquivalenceClasses.size() + " phi equivalence classes");
|
||||
getLog().append("Coalesced down to " + phiEquivalenceClasses.size() + " phi equivalence classes");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -75,15 +75,15 @@ public class Pass3PhiMemCoalesce extends Pass2SsaOptimization {
|
||||
if (lValEquivalenceClass.equals(assignVarEquivalenceClass)) {
|
||||
remove.add((VariableRef) assignment.getlValue());
|
||||
replace.put((VariableRef) assignment.getlValue(), assignVar);
|
||||
log.append("Coalesced (already) " + assignment);
|
||||
getLog().append("Coalesced (already) " + assignment);
|
||||
} else if (!lValEquivalenceClass.getLiveRange().overlaps(assignVarEquivalenceClass.getLiveRange())) {
|
||||
lValEquivalenceClass.addAll(assignVarEquivalenceClass);
|
||||
phiEquivalenceClassSet.remove(assignVarEquivalenceClass);
|
||||
remove.add((VariableRef) assignment.getlValue());
|
||||
replace.put((VariableRef) assignment.getlValue(), assignVar);
|
||||
log.append("Coalesced " + assignment);
|
||||
getLog().append("Coalesced " + assignment);
|
||||
} else {
|
||||
log.append("Not coalescing " + assignment);
|
||||
getLog().append("Not coalescing " + assignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +1,23 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
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 {
|
||||
public class Pass3RegisterUplifting extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3RegisterUplifting(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
public Pass3RegisterUplifting(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uplift one variable
|
||||
*/
|
||||
public void uplift() {
|
||||
VariableRegisterWeights variableRegisterWeights = program.getScope().getVariableRegisterWeights();
|
||||
LiveRangeEquivalenceClassSet equivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet();
|
||||
VariableRegisterWeights variableRegisterWeights = getProgram().getVariableRegisterWeights();
|
||||
LiveRangeEquivalenceClassSet equivalenceClassSet = getProgram().getLiveRangeEquivalenceClassSet();
|
||||
|
||||
double maxWeight = 0.0;
|
||||
LiveRangeEquivalenceClass maxEquivalenceClass = null;
|
||||
@ -54,7 +37,7 @@ public class Pass3RegisterUplifting {
|
||||
}
|
||||
|
||||
if (maxEquivalenceClass != null) {
|
||||
log.append("Uplifting max weight " + maxWeight + " live range equivalence class " + maxEquivalenceClass);
|
||||
getLog().append("Uplifting max weight " + maxWeight + " live range equivalence class " + maxEquivalenceClass);
|
||||
// Try the A register first
|
||||
List<RegisterAllocation.Register> registers =
|
||||
Arrays.asList(
|
||||
@ -66,22 +49,22 @@ public class Pass3RegisterUplifting {
|
||||
}
|
||||
}
|
||||
|
||||
RegisterAllocation allocation = program.getScope().getLiveRangeEquivalenceClassSet().createRegisterAllocation();
|
||||
program.getScope().setAllocation(allocation);
|
||||
RegisterAllocation allocation = getProgram().getLiveRangeEquivalenceClassSet().createRegisterAllocation();
|
||||
getProgram().setAllocation(allocation);
|
||||
|
||||
}
|
||||
|
||||
private void attemptUplift(LiveRangeEquivalenceClass equivalenceClass, RegisterAllocation.Register register) {
|
||||
RegisterAllocation allocation = program.getScope().getLiveRangeEquivalenceClassSet().createRegisterAllocation();
|
||||
RegisterAllocation allocation = getProgram().getLiveRangeEquivalenceClassSet().createRegisterAllocation();
|
||||
for (VariableRef var : equivalenceClass.getVariables()) {
|
||||
allocation.setRegister(var, register);
|
||||
}
|
||||
program.getScope().setAllocation(allocation);
|
||||
Pass3AssertNoCpuClobber clobber = new Pass3AssertNoCpuClobber(program, log);
|
||||
getProgram().setAllocation(allocation);
|
||||
Pass3AssertNoCpuClobber clobber = new Pass3AssertNoCpuClobber(getProgram());
|
||||
if (clobber.hasClobberProblem(false, register)) {
|
||||
log.append("Uplift to " + register + " resulted in clobber.");
|
||||
getLog().append("Uplift to " + register + " resulted in clobber.");
|
||||
} else {
|
||||
log.append("Uplift to " + register + " succesfull.");
|
||||
getLog().append("Uplift to " + register + " succesfull.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,27 +1,22 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
/**
|
||||
* Move register allocation from equivalence classes to RegisterAllocation.
|
||||
* Also rebase zero page registers.
|
||||
*/
|
||||
public class Pass3RegistersFinalize {
|
||||
public class Pass3RegistersFinalize extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3RegistersFinalize(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
public Pass3RegistersFinalize(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public void allocate() {
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet();
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = getProgram().getLiveRangeEquivalenceClassSet();
|
||||
reallocateZp(liveRangeEquivalenceClassSet);
|
||||
RegisterAllocation allocation = liveRangeEquivalenceClassSet.createRegisterAllocation();
|
||||
program.getScope().setAllocation(allocation);
|
||||
getProgram().setAllocation(allocation);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,11 +30,11 @@ public class Pass3RegistersFinalize {
|
||||
if(register.isZp()) {
|
||||
String before = register.toString();
|
||||
VariableRef variable = equivalenceClass.getVariables().get(0);
|
||||
Variable symbol = program.getScope().getVariable(variable);
|
||||
Variable symbol = getProgram().getScope().getVariable(variable);
|
||||
register = allocateNewRegisterZp(symbol.getType());
|
||||
equivalenceClass.setRegister(register);
|
||||
if(!before.equals(register.toString())) {
|
||||
log.append("Re-allocated ZP register from " + before + " to " + register.toString());
|
||||
getLog().append("Re-allocated ZP register from " + before + " to " + register.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
/**
|
||||
@ -12,25 +11,14 @@ import dk.camelot64.kickc.icl.*;
|
||||
* <p>
|
||||
* Based on ComputeWeight from http://compilers.cs.ucla.edu/fernando/projects/soc/reports/short_tech.pdf
|
||||
*/
|
||||
public class Pass3VariableRegisterWeightAnalysis {
|
||||
public class Pass3VariableRegisterWeightAnalysis extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
private NaturalLoopSet loopSet;
|
||||
private VariableRegisterWeights variableRegisterWeights;
|
||||
private LiveRangeVariables liveRangeVariables;
|
||||
|
||||
public Pass3VariableRegisterWeightAnalysis(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public Program getProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
return log;
|
||||
public Pass3VariableRegisterWeightAnalysis(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,10 +27,10 @@ public class Pass3VariableRegisterWeightAnalysis {
|
||||
public void findWeights() {
|
||||
|
||||
variableRegisterWeights = new VariableRegisterWeights();
|
||||
loopSet = program.getGraph().getLoopSet();
|
||||
liveRangeVariables = program.getScope().getLiveRangeVariables();
|
||||
loopSet = getProgram().getLoopSet();
|
||||
liveRangeVariables = getProgram().getLiveRangeVariables();
|
||||
|
||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||
for (ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if (statement instanceof StatementPhiBlock) {
|
||||
for (StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||
@ -84,7 +72,7 @@ public class Pass3VariableRegisterWeightAnalysis {
|
||||
}
|
||||
}
|
||||
|
||||
program.getScope().setVariableRegisterWeights(variableRegisterWeights);
|
||||
getProgram().setVariableRegisterWeights(variableRegisterWeights);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -9,53 +8,49 @@ import java.util.List;
|
||||
/**
|
||||
* Zero Page Register Allocation for variables based on live ranges and phi equivalence classes.
|
||||
*/
|
||||
public class Pass3ZeroPageAllocation {
|
||||
public class Pass3ZeroPageAllocation extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3ZeroPageAllocation(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
public Pass3ZeroPageAllocation(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public void allocate() {
|
||||
|
||||
// Initial equivalence classes from phi statements
|
||||
Pass3PhiMemCoalesce.EquivalenceClassPhiInitializer equivalenceClassPhiInitializer = new Pass3PhiMemCoalesce.EquivalenceClassPhiInitializer(program);
|
||||
equivalenceClassPhiInitializer.visitGraph(program.getGraph());
|
||||
Pass3PhiMemCoalesce.EquivalenceClassPhiInitializer equivalenceClassPhiInitializer = new Pass3PhiMemCoalesce.EquivalenceClassPhiInitializer(getProgram());
|
||||
equivalenceClassPhiInitializer.visitGraph(getGraph());
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = equivalenceClassPhiInitializer.getPhiEquivalenceClasses();
|
||||
log.append("Initial phi equivalence classes");
|
||||
getLog().append("Initial phi equivalence classes");
|
||||
for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
log.append(liveRangeEquivalenceClass.toString());
|
||||
getLog().append(liveRangeEquivalenceClass.toString());
|
||||
}
|
||||
|
||||
// Coalesce over copy assignments
|
||||
//EquivalenceClassCopyCoalescer equivalenceClassCopyCoalescer = new EquivalenceClassCopyCoalescer(liveRangeEquivalenceClassSet);
|
||||
//equivalenceClassCopyCoalescer.visitGraph(program.getGraph());
|
||||
//log.append("Copy Coalesced equivalence classes");
|
||||
//equivalenceClassCopyCoalescer.visitGraph(getGraph());
|
||||
//getLog().append("Copy Coalesced equivalence classes");
|
||||
//for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
// log.append(liveRangeEquivalenceClass.toString());
|
||||
// getLog().append(liveRangeEquivalenceClass.toString());
|
||||
//}
|
||||
|
||||
// Add all other variables one by one to an available equivalence class - or create a new one
|
||||
EquivalenceClassAdder equivalenceClassAdder = new EquivalenceClassAdder(liveRangeEquivalenceClassSet);
|
||||
equivalenceClassAdder.visitGraph(program.getGraph());
|
||||
log.append("Complete equivalence classes");
|
||||
equivalenceClassAdder.visitGraph(getGraph());
|
||||
getLog().append("Complete equivalence classes");
|
||||
for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
log.append(liveRangeEquivalenceClass.toString());
|
||||
getLog().append(liveRangeEquivalenceClass.toString());
|
||||
}
|
||||
|
||||
// Allocate zeropage registers to equivalence classes
|
||||
RegisterAllocation allocation = new RegisterAllocation();
|
||||
for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
List<VariableRef> variables = liveRangeEquivalenceClass.getVariables();
|
||||
Variable firstVar = program.getScope().getVariable(variables.get(0));
|
||||
Variable firstVar = getProgram().getScope().getVariable(variables.get(0));
|
||||
RegisterAllocation.Register zpRegister = allocateNewRegisterZp(firstVar.getType());
|
||||
liveRangeEquivalenceClass.setRegister(zpRegister);
|
||||
log.append("Allocated " + zpRegister + " to " + liveRangeEquivalenceClass);
|
||||
getLog().append("Allocated " + zpRegister + " to " + liveRangeEquivalenceClass);
|
||||
}
|
||||
program.getScope().setLiveRangeEquivalenceClassSet(liveRangeEquivalenceClassSet);
|
||||
getProgram().setLiveRangeEquivalenceClassSet(liveRangeEquivalenceClassSet);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,7 +77,7 @@ public class Pass3ZeroPageAllocation {
|
||||
}
|
||||
|
||||
private void addToEquivalenceClassSet(VariableRef lValVar, List<VariableRef> preferences) {
|
||||
LiveRangeVariables liveRangeVariables = program.getScope().getLiveRangeVariables();
|
||||
LiveRangeVariables liveRangeVariables = getProgram().getLiveRangeVariables();
|
||||
LiveRangeEquivalenceClass lValEquivalenceClass =
|
||||
liveRangeEquivalenceClassSet.getEquivalenceClass(lValVar);
|
||||
if (lValEquivalenceClass == null) {
|
||||
@ -92,8 +87,8 @@ public class Pass3ZeroPageAllocation {
|
||||
for (VariableRef preference : preferences) {
|
||||
LiveRangeEquivalenceClass preferenceEquivalenceClass = liveRangeEquivalenceClassSet.getEquivalenceClass(preference);
|
||||
if (preferenceEquivalenceClass != null) {
|
||||
Variable potentialVariable = program.getScope().getVariable(preference);
|
||||
Variable lValVariable = program.getScope().getVariable(lValVar);
|
||||
Variable potentialVariable = getProgram().getScope().getVariable(preference);
|
||||
Variable lValVariable = getProgram().getScope().getVariable(lValVar);
|
||||
if (lValVariable.getType().equals(potentialVariable.getType())) {
|
||||
if (!lValLiveRange.overlaps(preferenceEquivalenceClass.getLiveRange())) {
|
||||
chosen = preferenceEquivalenceClass;
|
||||
@ -107,7 +102,7 @@ public class Pass3ZeroPageAllocation {
|
||||
// No preference usable - create a new one
|
||||
chosen = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(lValVar);
|
||||
}
|
||||
log.append("Added variable " + lValVar + " to zero page equivalence class " + chosen);
|
||||
getLog().append("Added variable " + lValVar + " to zero page equivalence class " + chosen);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,13 +135,13 @@ public class Pass3ZeroPageAllocation {
|
||||
VariableRef assignVar = (VariableRef) assignment.getrValue2();
|
||||
LiveRangeEquivalenceClass assignVarEquivalenceClass = liveRangeEquivalenceClassSet.getOrCreateEquivalenceClass(assignVar);
|
||||
if (lValEquivalenceClass.equals(assignVarEquivalenceClass)) {
|
||||
log.append("Coalesced (already) " + assignment + " in " + lValEquivalenceClass);
|
||||
getLog().append("Coalesced (already) " + assignment + " in " + lValEquivalenceClass);
|
||||
} else if (!lValEquivalenceClass.getLiveRange().overlaps(assignVarEquivalenceClass.getLiveRange())) {
|
||||
lValEquivalenceClass.addAll(assignVarEquivalenceClass);
|
||||
liveRangeEquivalenceClassSet.remove(assignVarEquivalenceClass);
|
||||
log.append("Coalesced " + assignment + " into " + lValEquivalenceClass);
|
||||
getLog().append("Coalesced " + assignment + " into " + lValEquivalenceClass);
|
||||
} else {
|
||||
log.append("Not coalescing " + assignment);
|
||||
getLog().append("Not coalescing " + assignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,20 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.icl.*;
|
||||
|
||||
/**
|
||||
* Coalesces zero page registers where their live ranges do not overlap.
|
||||
* A final step done after all other register optimizations and before ASM generation.
|
||||
*/
|
||||
public class Pass3ZeroPageCoalesce {
|
||||
public class Pass3ZeroPageCoalesce extends Pass2Base {
|
||||
|
||||
private Program program;
|
||||
private CompileLog log;
|
||||
|
||||
public Pass3ZeroPageCoalesce(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
public Pass3ZeroPageCoalesce(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public void allocate() {
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = program.getScope().getLiveRangeEquivalenceClassSet();
|
||||
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = getProgram().getLiveRangeEquivalenceClassSet();
|
||||
|
||||
boolean change;
|
||||
do {
|
||||
@ -38,7 +34,7 @@ public class Pass3ZeroPageCoalesce {
|
||||
for (LiveRangeEquivalenceClass otherEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
|
||||
if (!myEquivalenceClass.equals(otherEquivalenceClass)) {
|
||||
if(canCoalesce(myEquivalenceClass, otherEquivalenceClass)) {
|
||||
log.append("Coalescing zero page register [ "+myEquivalenceClass+" ] with [ "+otherEquivalenceClass+" ]" );
|
||||
getLog().append("Coalescing zero page register [ "+myEquivalenceClass+" ] with [ "+otherEquivalenceClass+" ]" );
|
||||
myEquivalenceClass.addAll(otherEquivalenceClass);
|
||||
liveRangeEquivalenceClassSet.remove(otherEquivalenceClass);
|
||||
return true;
|
||||
@ -51,9 +47,9 @@ public class Pass3ZeroPageCoalesce {
|
||||
|
||||
private boolean canCoalesce(LiveRangeEquivalenceClass myEquivalenceClass, LiveRangeEquivalenceClass otherEquivalenceClass) {
|
||||
VariableRef myVariableRef = myEquivalenceClass.getVariables().get(0);
|
||||
Variable myVariable = program.getScope().getVariable(myVariableRef);
|
||||
Variable myVariable = getProgram().getScope().getVariable(myVariableRef);
|
||||
VariableRef otherVariableRef = otherEquivalenceClass.getVariables().get(0);
|
||||
Variable otherVariable = program.getScope().getVariable(otherVariableRef);
|
||||
Variable otherVariable = getProgram().getScope().getVariable(otherVariableRef);
|
||||
if (myVariable.getType().equals(otherVariable.getType())) {
|
||||
// Types match
|
||||
if (myEquivalenceClass.getRegister().isZp() && otherEquivalenceClass.getRegister().isZp()) {
|
||||
|
@ -10,17 +10,24 @@ import java.util.*;
|
||||
*/
|
||||
public class Pass4CodeGeneration {
|
||||
|
||||
private ControlFlowGraph graph;
|
||||
private ProgramScope symbols;
|
||||
|
||||
private Program program;
|
||||
|
||||
public Pass4CodeGeneration(Program program) {
|
||||
this.graph = program.getGraph();
|
||||
this.symbols = program.getScope();
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
public AsmProgram generate() {
|
||||
ControlFlowGraph getGraph() {
|
||||
return program.getGraph();
|
||||
}
|
||||
|
||||
ProgramScope getScope() {
|
||||
return program.getScope();
|
||||
}
|
||||
|
||||
public void generate() {
|
||||
AsmProgram asm = new AsmProgram();
|
||||
for (ControlFlowBlock block : graph.getAllBlocks()) {
|
||||
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
// Generate entry points (if needed)
|
||||
genBlockEntryPoints(asm, block);
|
||||
// Generate label
|
||||
@ -28,7 +35,7 @@ public class Pass4CodeGeneration {
|
||||
// Generate statements
|
||||
genStatements(asm, block);
|
||||
// Generate exit
|
||||
ControlFlowBlock defaultSuccessor = graph.getDefaultSuccessor(block);
|
||||
ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block);
|
||||
if (defaultSuccessor != null) {
|
||||
if (defaultSuccessor.hasPhiBlock()) {
|
||||
genBlockPhiTransition(asm, block, defaultSuccessor);
|
||||
@ -36,7 +43,7 @@ public class Pass4CodeGeneration {
|
||||
asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getFullName().replace('@', 'B').replace(':', '_'));
|
||||
}
|
||||
}
|
||||
return asm;
|
||||
program.setAsm(asm);
|
||||
}
|
||||
|
||||
private void genStatements(AsmProgram asm, ControlFlowBlock block) {
|
||||
@ -66,8 +73,8 @@ public class Pass4CodeGeneration {
|
||||
throw new RuntimeException("Error! ALU statement must be followed immediately by assignment using the ALU. " + statement);
|
||||
}
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
AsmFragment asmFragment = new AsmFragment(assignment, assignmentAlu, symbols);
|
||||
asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature());
|
||||
AsmFragment asmFragment = new AsmFragment(assignment, assignmentAlu, program);
|
||||
asm.addComment(statement.toString(program) + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
aluState.clear();
|
||||
return;
|
||||
@ -80,8 +87,8 @@ public class Pass4CodeGeneration {
|
||||
boolean isAlu = false;
|
||||
if (lValue instanceof VariableRef) {
|
||||
VariableRef lValueRef = (VariableRef) lValue;
|
||||
Variable lValueVar = symbols.getVariable(lValueRef);
|
||||
RegisterAllocation.Register lValRegister = symbols.getRegister(lValueVar);
|
||||
Variable lValueVar = getScope().getVariable(lValueRef);
|
||||
RegisterAllocation.Register lValRegister = program.getRegister(lValueVar);
|
||||
if (lValRegister.getType().equals(RegisterAllocation.RegisterType.REG_ALU_BYTE)) {
|
||||
asm.addComment(statement + " // ALU");
|
||||
StatementAssignment assignmentAlu = assignment;
|
||||
@ -91,20 +98,20 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
if (!isAlu) {
|
||||
if (assignment.getOperator() == null && assignment.getrValue1() == null && isRegisterCopy(lValue, assignment.getrValue2())) {
|
||||
asm.addComment(lValue.toString(symbols) + " = " + assignment.getrValue2().toString(symbols) + " // register copy " + getRegister(lValue));
|
||||
asm.addComment(lValue.toString(program) + " = " + assignment.getrValue2().toString(program) + " // register copy " + getRegister(lValue));
|
||||
} else {
|
||||
AsmFragment asmFragment = new AsmFragment(assignment, symbols);
|
||||
asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature());
|
||||
AsmFragment asmFragment = new AsmFragment(assignment, program);
|
||||
asm.addComment(statement.toString(program) + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
}
|
||||
}
|
||||
} else if (statement instanceof StatementConditionalJump) {
|
||||
AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, symbols, graph);
|
||||
asm.addComment(statement.toString(symbols) + " // " + asmFragment.getSignature());
|
||||
AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, block, program, getGraph());
|
||||
asm.addComment(statement.toString(program) + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
} else if (statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
ControlFlowBlock callSuccessor = graph.getCallSuccessor(block);
|
||||
ControlFlowBlock callSuccessor = getGraph().getCallSuccessor(block);
|
||||
if (callSuccessor != null && callSuccessor.hasPhiBlock()) {
|
||||
genBlockPhiTransition(asm, block, callSuccessor);
|
||||
}
|
||||
@ -145,7 +152,7 @@ public class Pass4CodeGeneration {
|
||||
|
||||
private void genBlockEntryPoints(AsmProgram asm, ControlFlowBlock block) {
|
||||
if (block.hasPhiBlock()) {
|
||||
List<ControlFlowBlock> predecessors = new ArrayList<>(graph.getPredecessors(block));
|
||||
List<ControlFlowBlock> predecessors = new ArrayList<>(getGraph().getPredecessors(block));
|
||||
Collections.sort(predecessors, new Comparator<ControlFlowBlock>() {
|
||||
@Override
|
||||
public int compare(ControlFlowBlock o1, ControlFlowBlock o2) {
|
||||
@ -188,8 +195,8 @@ public class Pass4CodeGeneration {
|
||||
private RegisterAllocation.Register getRegister(RValue rValue) {
|
||||
if (rValue instanceof VariableRef) {
|
||||
VariableRef rValueRef = (VariableRef) rValue;
|
||||
Variable rValueVar = symbols.getVariable(rValueRef);
|
||||
return symbols.getRegister(rValueVar);
|
||||
Variable rValueVar = getScope().getVariable(rValueRef);
|
||||
return program.getRegister(rValueVar);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -197,10 +204,10 @@ public class Pass4CodeGeneration {
|
||||
|
||||
private void genAsmMove(AsmProgram asm, LValue lValue, RValue rValue) {
|
||||
if (isRegisterCopy(lValue, rValue)) {
|
||||
asm.addComment(lValue.toString(symbols) + " = " + rValue.toString(symbols) + " // register copy " + getRegister(lValue));
|
||||
asm.addComment(lValue.toString(program) + " = " + rValue.toString(program) + " // register copy " + getRegister(lValue));
|
||||
} else {
|
||||
AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols);
|
||||
asm.addComment(lValue.toString(symbols) + " = " + rValue.toString(symbols) + " // " + asmFragment.getSignature());
|
||||
AsmFragment asmFragment = new AsmFragment(lValue, rValue, program);
|
||||
asm.addComment(lValue.toString(program) + " = " + rValue.toString(program) + " // " + asmFragment.getSignature());
|
||||
asmFragment.generate(asm);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.asm.AsmLine;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.icl.Program;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -13,9 +14,9 @@ import java.util.List;
|
||||
public abstract class Pass5AsmOptimization {
|
||||
|
||||
protected CompileLog log;
|
||||
private AsmProgram program;
|
||||
private Program program;
|
||||
|
||||
public Pass5AsmOptimization(AsmProgram program, CompileLog log) {
|
||||
public Pass5AsmOptimization(Program program, CompileLog log) {
|
||||
this.program = program;
|
||||
this.log = log;
|
||||
}
|
||||
@ -27,8 +28,8 @@ public abstract class Pass5AsmOptimization {
|
||||
*/
|
||||
public abstract boolean optimize();
|
||||
|
||||
public AsmProgram getProgram() {
|
||||
return program;
|
||||
public AsmProgram getAsmProgram() {
|
||||
return program.getAsm();
|
||||
}
|
||||
|
||||
public CompileLog getLog() {
|
||||
@ -36,7 +37,7 @@ public abstract class Pass5AsmOptimization {
|
||||
}
|
||||
|
||||
public void remove(List<AsmLine> remove) {
|
||||
for (Iterator<AsmLine> iterator = program.getLines().iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<AsmLine> iterator = getAsmProgram().getLines().iterator(); iterator.hasNext(); ) {
|
||||
AsmLine line = iterator.next();
|
||||
if (remove.contains(line)) {
|
||||
log.append("Removing instruction "+line.getAsm());
|
||||
|
@ -5,6 +5,7 @@ import dk.camelot64.kickc.asm.AsmInstruction;
|
||||
import dk.camelot64.kickc.asm.AsmLabel;
|
||||
import dk.camelot64.kickc.asm.AsmLine;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.icl.Program;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -12,14 +13,14 @@ import java.util.List;
|
||||
/** Optimize assembler code by removing jumps to labels immediately following the jump */
|
||||
public class Pass5NextJumpElimination extends Pass5AsmOptimization {
|
||||
|
||||
public Pass5NextJumpElimination(AsmProgram program, CompileLog log) {
|
||||
public Pass5NextJumpElimination(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
}
|
||||
|
||||
public boolean optimize() {
|
||||
List<AsmLine> removeLines = new ArrayList<>();
|
||||
AsmInstruction candidate = null;
|
||||
for (AsmLine line : getProgram().getLines()) {
|
||||
for (AsmLine line : getAsmProgram().getLines()) {
|
||||
if(candidate!=null) {
|
||||
if(line instanceof AsmLabel) {
|
||||
if(((AsmLabel) line).getLabel().equals(candidate.getParameter())) {
|
||||
|
@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.asm.AsmProgramStaticRegisterValues;
|
||||
import dk.camelot64.kickc.icl.Program;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -10,15 +11,15 @@ import java.util.List;
|
||||
/** Maps out register values entering all instructions. Removes unnecessary loads / clears / sets */
|
||||
public class Pass5UnnecesaryLoadElimination extends Pass5AsmOptimization {
|
||||
|
||||
public Pass5UnnecesaryLoadElimination(AsmProgram program, CompileLog log) {
|
||||
public Pass5UnnecesaryLoadElimination(Program program, CompileLog log) {
|
||||
super(program, log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean optimize() {
|
||||
AsmProgramStaticRegisterValues staticValues = new AsmProgramStaticRegisterValues(getProgram());
|
||||
AsmProgramStaticRegisterValues staticValues = new AsmProgramStaticRegisterValues(getAsmProgram());
|
||||
List<AsmLine> removes = new ArrayList<>();
|
||||
for (AsmLine line : getProgram().getLines()) {
|
||||
for (AsmLine line : getAsmProgram().getLines()) {
|
||||
if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
AsmInstructionType instructionType = instruction.getType();
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.test;
|
||||
|
||||
import dk.camelot64.kickc.Compiler;
|
||||
import dk.camelot64.kickc.icl.Program;
|
||||
import junit.framework.TestCase;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
@ -86,12 +87,12 @@ public class TestCompilationOutput extends TestCase {
|
||||
System.out.println("Testing output for " + inputPath);
|
||||
CharStream input = CharStreams.fromFileName(inputPath);
|
||||
Compiler compiler = new Compiler();
|
||||
Compiler.CompilationResult output = compiler.compile(input);
|
||||
Program program = compiler.compile(input);
|
||||
boolean success = true;
|
||||
success &= helper.testOutput(fileName, ".asm", output.getAsmProgram().toString(false));
|
||||
success &= helper.testOutput(fileName, ".sym", output.getScope().getSymbolTableContents());
|
||||
success &= helper.testOutput(fileName, ".cfg", output.getGraph().toString(output.getScope()));
|
||||
success &= helper.testOutput(fileName, ".log", output.getLog().toString());
|
||||
success &= helper.testOutput(fileName, ".asm", program.getAsm().toString(false));
|
||||
success &= helper.testOutput(fileName, ".sym", program.getScope().getSymbolTableContents(program));
|
||||
success &= helper.testOutput(fileName, ".cfg", program.getGraph().toString(program));
|
||||
success &= helper.testOutput(fileName, ".log", program.getLog().toString());
|
||||
if (!success) {
|
||||
fail("Output does not match reference!");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user