diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index d852f2416..ae14aaa0c 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -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 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 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 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; } diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java b/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java index c02462017..bae73224e 100644 --- a/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/main/java/dk/camelot64/kickc/asm/AsmFragment.java @@ -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()); diff --git a/src/main/java/dk/camelot64/kickc/icl/ConstantBool.java b/src/main/java/dk/camelot64/kickc/icl/ConstantBool.java index 6ef05be42..3d53a2c22 100644 --- a/src/main/java/dk/camelot64/kickc/icl/ConstantBool.java +++ b/src/main/java/dk/camelot64/kickc/icl/ConstantBool.java @@ -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()+") "+ diff --git a/src/main/java/dk/camelot64/kickc/icl/ConstantDouble.java b/src/main/java/dk/camelot64/kickc/icl/ConstantDouble.java index d0a8ca331..fda54e3e0 100644 --- a/src/main/java/dk/camelot64/kickc/icl/ConstantDouble.java +++ b/src/main/java/dk/camelot64/kickc/icl/ConstantDouble.java @@ -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); diff --git a/src/main/java/dk/camelot64/kickc/icl/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/icl/ConstantInteger.java index 6e3c72a8b..28a12b6e9 100644 --- a/src/main/java/dk/camelot64/kickc/icl/ConstantInteger.java +++ b/src/main/java/dk/camelot64/kickc/icl/ConstantInteger.java @@ -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); diff --git a/src/main/java/dk/camelot64/kickc/icl/ConstantString.java b/src/main/java/dk/camelot64/kickc/icl/ConstantString.java index b1cea6f0d..2776c98d7 100644 --- a/src/main/java/dk/camelot64/kickc/icl/ConstantString.java +++ b/src/main/java/dk/camelot64/kickc/icl/ConstantString.java @@ -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 + "\\"; diff --git a/src/main/java/dk/camelot64/kickc/icl/ControlFlowBlock.java b/src/main/java/dk/camelot64/kickc/icl/ControlFlowBlock.java index 524e4c493..97aa0ea38 100644 --- a/src/main/java/dk/camelot64/kickc/icl/ControlFlowBlock.java +++ b/src/main/java/dk/camelot64/kickc/icl/ControlFlowBlock.java @@ -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:"); diff --git a/src/main/java/dk/camelot64/kickc/icl/ControlFlowGraph.java b/src/main/java/dk/camelot64/kickc/icl/ControlFlowGraph.java index a744247a3..dbd3f1e1a 100644 --- a/src/main/java/dk/camelot64/kickc/icl/ControlFlowGraph.java +++ b/src/main/java/dk/camelot64/kickc/icl/ControlFlowGraph.java @@ -15,12 +15,6 @@ public class ControlFlowGraph { /** Sequence of blocks used when generating ASM */ private List 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 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(); } diff --git a/src/main/java/dk/camelot64/kickc/icl/Label.java b/src/main/java/dk/camelot64/kickc/icl/Label.java index 511a0fdd9..4d9ebe691 100644 --- a/src/main/java/dk/camelot64/kickc/icl/Label.java +++ b/src/main/java/dk/camelot64/kickc/icl/Label.java @@ -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(); diff --git a/src/main/java/dk/camelot64/kickc/icl/LiveRangeEquivalenceClass.java b/src/main/java/dk/camelot64/kickc/icl/LiveRangeEquivalenceClass.java index 557326a65..a835bcfda 100644 --- a/src/main/java/dk/camelot64/kickc/icl/LiveRangeEquivalenceClass.java +++ b/src/main/java/dk/camelot64/kickc/icl/LiveRangeEquivalenceClass.java @@ -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); diff --git a/src/main/java/dk/camelot64/kickc/icl/PointerDereferenceIndexed.java b/src/main/java/dk/camelot64/kickc/icl/PointerDereferenceIndexed.java index 21ce6d965..96c9aac2d 100644 --- a/src/main/java/dk/camelot64/kickc/icl/PointerDereferenceIndexed.java +++ b/src/main/java/dk/camelot64/kickc/icl/PointerDereferenceIndexed.java @@ -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) + ')'; } } diff --git a/src/main/java/dk/camelot64/kickc/icl/PointerDereferenceSimple.java b/src/main/java/dk/camelot64/kickc/icl/PointerDereferenceSimple.java index 6558cd549..64a966b17 100644 --- a/src/main/java/dk/camelot64/kickc/icl/PointerDereferenceSimple.java +++ b/src/main/java/dk/camelot64/kickc/icl/PointerDereferenceSimple.java @@ -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) + ')'; } } diff --git a/src/main/java/dk/camelot64/kickc/icl/Procedure.java b/src/main/java/dk/camelot64/kickc/icl/Procedure.java index 2c3eb2202..cf66eea25 100644 --- a/src/main/java/dk/camelot64/kickc/icl/Procedure.java +++ b/src/main/java/dk/camelot64/kickc/icl/Procedure.java @@ -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(")"); diff --git a/src/main/java/dk/camelot64/kickc/icl/Program.java b/src/main/java/dk/camelot64/kickc/icl/Program.java index 9fdf323e8..934b23d65 100644 --- a/src/main/java/dk/camelot64/kickc/icl/Program.java +++ b/src/main/java/dk/camelot64/kickc/icl/Program.java @@ -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; } + } diff --git a/src/main/java/dk/camelot64/kickc/icl/ProgramScope.java b/src/main/java/dk/camelot64/kickc/icl/ProgramScope.java index e3606b264..1e230ea67 100644 --- a/src/main/java/dk/camelot64/kickc/icl/ProgramScope.java +++ b/src/main/java/dk/camelot64/kickc/icl/ProgramScope.java @@ -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 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; - } } diff --git a/src/main/java/dk/camelot64/kickc/icl/RegisterAllocation.java b/src/main/java/dk/camelot64/kickc/icl/RegisterAllocation.java index 958d2db61..bb0b7599b 100644 --- a/src/main/java/dk/camelot64/kickc/icl/RegisterAllocation.java +++ b/src/main/java/dk/camelot64/kickc/icl/RegisterAllocation.java @@ -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(); } diff --git a/src/main/java/dk/camelot64/kickc/icl/Scope.java b/src/main/java/dk/camelot64/kickc/icl/Scope.java index 72d182d96..3c8cb839a 100644 --- a/src/main/java/dk/camelot64/kickc/icl/Scope.java +++ b/src/main/java/dk/camelot64/kickc/icl/Scope.java @@ -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 names = symbols.keySet(); List 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) { diff --git a/src/main/java/dk/camelot64/kickc/icl/Statement.java b/src/main/java/dk/camelot64/kickc/icl/Statement.java index 662ebd64f..eb48c09d7 100644 --- a/src/main/java/dk/camelot64/kickc/icl/Statement.java +++ b/src/main/java/dk/camelot64/kickc/icl/Statement.java @@ -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); diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementAssignment.java b/src/main/java/dk/camelot64/kickc/icl/StatementAssignment.java index 9d21a4b44..191839ed2 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementAssignment.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementAssignment.java @@ -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 diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementBase.java b/src/main/java/dk/camelot64/kickc/icl/StatementBase.java index 3b4205071..c3b15ef6f 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementBase.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementBase.java @@ -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 alive = liveRanges.getAlive(this); StringBuilder str = new StringBuilder(); str.append(" [ "); diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementCall.java b/src/main/java/dk/camelot64/kickc/icl/StatementCall.java index 2830157e7..3068e2cb5 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementCall.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementCall.java @@ -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(); } diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementConditionalJump.java b/src/main/java/dk/camelot64/kickc/icl/StatementConditionalJump.java index 623668077..29c1c5e81 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementConditionalJump.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementConditionalJump.java @@ -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(); } diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementJump.java b/src/main/java/dk/camelot64/kickc/icl/StatementJump.java index 74f3a11b7..073aec6d5 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementJump.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementJump.java @@ -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); } } diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementLabel.java b/src/main/java/dk/camelot64/kickc/icl/StatementLabel.java index 56789d7a1..e283c7907 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementLabel.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementLabel.java @@ -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); } } diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementPhiBlock.java b/src/main/java/dk/camelot64/kickc/icl/StatementPhiBlock.java index 2ee21ac7a..4ae1467e7 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementPhiBlock.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementPhiBlock.java @@ -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 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) { diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementProcedureBegin.java b/src/main/java/dk/camelot64/kickc/icl/StatementProcedureBegin.java index 5760d88ca..97927d7f5 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementProcedureBegin.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementProcedureBegin.java @@ -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); } } diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementProcedureEnd.java b/src/main/java/dk/camelot64/kickc/icl/StatementProcedureEnd.java index 2b7e8fa12..1ba7ff23d 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementProcedureEnd.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementProcedureEnd.java @@ -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); } } diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementReturn.java b/src/main/java/dk/camelot64/kickc/icl/StatementReturn.java index 25c6c06de..6b46169c0 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementReturn.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementReturn.java @@ -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 diff --git a/src/main/java/dk/camelot64/kickc/icl/StatementSequence.java b/src/main/java/dk/camelot64/kickc/icl/StatementSequence.java index e2132c195..3cee80914 100644 --- a/src/main/java/dk/camelot64/kickc/icl/StatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/icl/StatementSequence.java @@ -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(); } diff --git a/src/main/java/dk/camelot64/kickc/icl/SymbolRef.java b/src/main/java/dk/camelot64/kickc/icl/SymbolRef.java index 9dd7ae44b..2d8b4e3f9 100644 --- a/src/main/java/dk/camelot64/kickc/icl/SymbolRef.java +++ b/src/main/java/dk/camelot64/kickc/icl/SymbolRef.java @@ -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); } } diff --git a/src/main/java/dk/camelot64/kickc/icl/Value.java b/src/main/java/dk/camelot64/kickc/icl/Value.java index ecd179cbe..1004436c7 100644 --- a/src/main/java/dk/camelot64/kickc/icl/Value.java +++ b/src/main/java/dk/camelot64/kickc/icl/Value.java @@ -24,6 +24,6 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; }) public interface Value { - String toString(ProgramScope scope); + String toString(Program program); } diff --git a/src/main/java/dk/camelot64/kickc/icl/Variable.java b/src/main/java/dk/camelot64/kickc/icl/Variable.java index 825667059..e0b7b1231 100644 --- a/src/main/java/dk/camelot64/kickc/icl/Variable.java +++ b/src/main/java/dk/camelot64/kickc/icl/Variable.java @@ -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(); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java b/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java index b393f6383..e4642372c 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1EliminateEmptyBlocks.java @@ -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 blocks = graph.getAllBlocks(); List removeList = new ArrayList<>(); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java index 129bcd061..ff51f84c0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java @@ -17,21 +17,19 @@ import java.util.Stack; */ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { - private CompileLog log; - private ProgramScope programScope; + private Program program; private Stack 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 { @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 { @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 { 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)); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java index f9e2190ed..d18e96635 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2AliasElimination.java @@ -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); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2Base.java b/src/main/java/dk/camelot64/kickc/passes/Pass2Base.java new file mode 100644 index 000000000..bb5ee9cc5 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2Base.java @@ -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; + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java index d8c76b8a7..0c5c8f6a1 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java @@ -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: } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java index 2b7ff4621..6289d9dc3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantAdditionElimination.java @@ -19,8 +19,8 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization { private Map 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); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantPropagation.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantPropagation.java index d76cb7988..bb88f5589 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantPropagation.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantPropagation.java @@ -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 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()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java b/src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java index 772951196..eac30c43b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java @@ -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; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java index caa16ddd3..89c5bab16 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2RedundantPhiElimination.java @@ -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; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2SelfPhiElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass2SelfPhiElimination.java index 36a51fb38..98226e1ee 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2SelfPhiElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2SelfPhiElimination.java @@ -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())); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2SsaOptimization.java b/src/main/java/dk/camelot64/kickc/passes/Pass2SsaOptimization.java index 97f3e9a60..09ee9799e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2SsaOptimization.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2SsaOptimization.java @@ -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"; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoCpuClobber.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoCpuClobber.java index 2c50a2f37..2fe909992 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoCpuClobber.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertNoCpuClobber.java @@ -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; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3BlockSequencePlanner.java b/src/main/java/dk/camelot64/kickc/passes/Pass3BlockSequencePlanner.java index 0462b3ebe..a27826088 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3BlockSequencePlanner.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3BlockSequencePlanner.java @@ -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 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); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3CallGraphAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3CallGraphAnalysis.java index edea2d0a3..ced91a775 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3CallGraphAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3CallGraphAnalysis.java @@ -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); } /** diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3CustomRegisters.java b/src/main/java/dk/camelot64/kickc/passes/Pass3CustomRegisters.java index 0014463e2..d469fa1c1 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3CustomRegisters.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3CustomRegisters.java @@ -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()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3DominatorsAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3DominatorsAnalysis.java index 406ea7782..31f4d5b37 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3DominatorsAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3DominatorsAnalysis.java @@ -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 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 predecessors = program.getGraph().getPredecessors(block); + List 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); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesAnalysis.java index b7fe15516..2120a9ff9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3LiveRangesAnalysis.java @@ -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); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java index 03d7f0e12..0df530fb6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3LoopAnalysis.java @@ -11,22 +11,10 @@ import java.util.*; *

* 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 blocks = program.getGraph().getAllBlocks(); + DominatorsGraph dominators = getProgram().getDominators(); + Collection 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 predecessors = program.getGraph().getPredecessors(controlFlowBlock); + ControlFlowBlock controlFlowBlock = getGraph().getBlock(block); + List 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); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java index 6dc0dbabf..78c3ef04e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java @@ -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 todo = new ArrayDeque<>(); Set done = new LinkedHashSet<>(); @@ -57,7 +44,7 @@ public class Pass3LoopDepthAnalysis { Collection 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 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 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 diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiLifting.java b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiLifting.java index 516ff1d15..b2ec33a7f 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiLifting.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiLifting.java @@ -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); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java index eb7d4292f..0b31aa1de 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3PhiMemCoalesce.java @@ -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); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java b/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java index 9b9547557..cf25b687a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3RegisterUplifting.java @@ -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 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."); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java b/src/main/java/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java index cd0747c4a..5f2e18d1c 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3RegistersFinalize.java @@ -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()); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3VariableRegisterWeightAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3VariableRegisterWeightAnalysis.java index c0edc983b..f85a22690 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3VariableRegisterWeightAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3VariableRegisterWeightAnalysis.java @@ -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.*; *

* 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); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageAllocation.java b/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageAllocation.java index 1058d59aa..48dd37e15 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageAllocation.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageAllocation.java @@ -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 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 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); } } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageCoalesce.java b/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageCoalesce.java index 03d3451bb..b2033461a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageCoalesce.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3ZeroPageCoalesce.java @@ -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()) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index b79d6cff2..fbe4bdbd0 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -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 predecessors = new ArrayList<>(graph.getPredecessors(block)); + List predecessors = new ArrayList<>(getGraph().getPredecessors(block)); Collections.sort(predecessors, new Comparator() { @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); } } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass5AsmOptimization.java b/src/main/java/dk/camelot64/kickc/passes/Pass5AsmOptimization.java index 2e210e073..699c9a3e6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass5AsmOptimization.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass5AsmOptimization.java @@ -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 remove) { - for (Iterator iterator = program.getLines().iterator(); iterator.hasNext(); ) { + for (Iterator iterator = getAsmProgram().getLines().iterator(); iterator.hasNext(); ) { AsmLine line = iterator.next(); if (remove.contains(line)) { log.append("Removing instruction "+line.getAsm()); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass5NextJumpElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass5NextJumpElimination.java index 04804a17a..1f2eaad79 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass5NextJumpElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass5NextJumpElimination.java @@ -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 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())) { diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass5UnnecesaryLoadElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass5UnnecesaryLoadElimination.java index fc80a828d..b8941239b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass5UnnecesaryLoadElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass5UnnecesaryLoadElimination.java @@ -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 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(); diff --git a/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java b/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java index 4e3a11f28..4d87244e6 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java +++ b/src/main/java/dk/camelot64/kickc/test/TestCompilationOutput.java @@ -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!"); }