1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Gathered all pass results in Program.

This commit is contained in:
jespergravgaard 2017-07-31 23:41:10 +02:00
parent 5d21c6aa97
commit 64d9ff3f23
63 changed files with 573 additions and 683 deletions

View File

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

View File

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

View File

@ -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()+") "+

View File

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

View File

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

View File

@ -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 + "\\";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,6 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
})
public interface Value {
String toString(ProgramScope scope);
String toString(Program program);
}

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()) {

View File

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

View File

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

View File

@ -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())) {

View File

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

View File

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