From 1f39ab8c377d161cceb4757e092ef075db7bea94 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Thu, 1 Aug 2019 23:52:05 +0200 Subject: [PATCH] Refactored call-graph to be calculated on demand. --- .../java/dk/camelot64/kickc/Compiler.java | 6 +-- .../dk/camelot64/kickc/model/CallGraph.java | 4 +- .../dk/camelot64/kickc/model/Program.java | 28 ++++++++++---- .../kickc/passes/Pass3LoopDepthAnalysis.java | 2 +- .../camelot64/kickc/passes/PassNCalcBase.java | 38 +++++++++++++++++++ ...hAnalysis.java => PassNCalcCallGraph.java} | 11 ++---- 6 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/PassNCalcBase.java rename src/main/java/dk/camelot64/kickc/passes/{PassNCallGraphAnalysis.java => PassNCalcCallGraph.java} (89%) diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index e3dfd5f45..5e916cf9c 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -200,7 +200,7 @@ public class Compiler { } new Pass1ProcedureInline(program).execute(); new PassNStatementIndices(program).step(); - new PassNCallGraphAnalysis(program).step(); + program.clearCallGraph(); new Pass1AssertNoRecursion(program).execute(); new Pass1AssertInterrupts(program).execute(); @@ -422,7 +422,7 @@ public class Compiler { new PassNStatementIndices(program).execute(); getLog().append("CALL GRAPH"); - new PassNCallGraphAnalysis(program).step(); + program.clearCallGraph(); getLog().append(program.getCallGraph().toString()); //getLog().setVerboseLiveRanges(true); @@ -443,7 +443,7 @@ public class Compiler { new PassNBlockSequencePlanner(program).step(); new Pass3AddNopBeforeCallOns(program).generate(); new PassNStatementIndices(program).execute(); - new PassNCallGraphAnalysis(program).step(); + program.clearCallGraph(); new PassNStatementInfos(program).execute(); new PassNVariableReferenceInfos(program).execute(); new Pass3SymbolInfos(program).generateSymbolInfos(); diff --git a/src/main/java/dk/camelot64/kickc/model/CallGraph.java b/src/main/java/dk/camelot64/kickc/model/CallGraph.java index 87dd0aa93..96c360655 100644 --- a/src/main/java/dk/camelot64/kickc/model/CallGraph.java +++ b/src/main/java/dk/camelot64/kickc/model/CallGraph.java @@ -3,13 +3,13 @@ package dk.camelot64.kickc.model; import dk.camelot64.kickc.model.statements.StatementCall; import dk.camelot64.kickc.model.values.ProcedureRef; import dk.camelot64.kickc.model.values.ScopeRef; -import dk.camelot64.kickc.passes.PassNCallGraphAnalysis; +import dk.camelot64.kickc.passes.PassNCalcCallGraph; import java.util.*; /** * The call graph for the entire control flow graph. - * Created by {@link PassNCallGraphAnalysis} + * Created by {@link PassNCalcCallGraph} */ public class CallGraph { diff --git a/src/main/java/dk/camelot64/kickc/model/Program.java b/src/main/java/dk/camelot64/kickc/model/Program.java index c8f3f59e0..df1073bf0 100644 --- a/src/main/java/dk/camelot64/kickc/model/Program.java +++ b/src/main/java/dk/camelot64/kickc/model/Program.java @@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.statements.StatementInfos; import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.values.LabelRef; import dk.camelot64.kickc.model.values.VariableRef; +import dk.camelot64.kickc.passes.PassNCalcCallGraph; import java.nio.file.Path; import java.util.ArrayList; @@ -55,7 +56,7 @@ public class Program { /** The 6502 ASM program. PASS 4-5 (DYNAMIC) */ private AsmProgram asm; - /** A saved program snapshot that can be rolled back. Used to store the (DYNAMIC) state of the program while trying out a potential optimization. PASS 2 (DYNAMIC)*/ + /** A saved program snapshot that can be rolled back. Used to store the (DYNAMIC) state of the program while trying out a potential optimization. PASS 2 (DYNAMIC) */ private ProgramSnapshot snapshot; /** Cached information about calls. PASS 1-4 (CACHED) */ @@ -123,16 +124,16 @@ public class Program { } /** Save a snapshot of the dynamic parts of the program. */ - public void saveSnapshot() { - if(this.snapshot!=null) + public void snapshotCreate() { + if(this.snapshot != null) throw new InternalError("Snapshot already saved!"); - if(this.liveRangeEquivalenceClassSet!=null) + if(this.liveRangeEquivalenceClassSet != null) throw new InternalError("Compiler Program Snapshot does not support liveRangeEquivalenceClassSet!"); this.snapshot = new ProgramSnapshot(scope, graph); } /** Restore the snapshot of the dynamic parts of the program. Clear all cached data and the snapshot. */ - public void restoreSnapshot() { + public void snapshotRestore() { this.scope = snapshot.getScope(); this.graph = snapshot.getGraph(); this.snapshot = null; @@ -239,12 +240,21 @@ public class Program { this.asm = asm; } + /** + * Get the call-graph for the program. Calculates the call-graph if it has not already been calculated. + * @return The call-graph + */ public CallGraph getCallGraph() { + if(callGraph == null) + this.callGraph = new PassNCalcCallGraph(this).calculate(); return callGraph; } - public void setCallGraph(CallGraph callGraph) { - this.callGraph = callGraph; + /** + * Clears the call-graph ensuring it will be re-calculated if used. + */ + public void clearCallGraph() { + this.callGraph = null; } public DominatorsGraph getDominators() { @@ -354,6 +364,7 @@ public class Program { /** * Adds a bunch of reserved zero-page addresses that the compiler is not allowed to use. + * * @param reservedZp addresses to reserve */ public void addReservedZps(List reservedZp) { @@ -370,6 +381,7 @@ public class Program { /** * Set the absolute position of the program code + * * @param programPc The address */ public void setProgramPc(Number programPc) { @@ -387,6 +399,6 @@ public class Program { public void setLog(CompileLog log) { this.log = log; } - + } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java index d0247f3fc..8ff6d174c 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java @@ -97,7 +97,7 @@ public class Pass3LoopDepthAnalysis extends Pass2Base { for(NaturalLoop loop : loopSet.getLoops()) { LabelRef loopHead = loop.getHead(); ControlFlowBlock loopHeadBlock = getGraph().getBlock(loopHead); - ScopeRef scopeRef = PassNCallGraphAnalysis.getScopeRef(loopHeadBlock, getProgram()); + ScopeRef scopeRef = PassNCalcCallGraph.getScopeRef(loopHeadBlock, getProgram()); if(scopeRef.equals(currentScope)) { // Loop is inside current scope block! currentScopeLoops.add(loop); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNCalcBase.java b/src/main/java/dk/camelot64/kickc/passes/PassNCalcBase.java new file mode 100644 index 000000000..62d3d7787 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNCalcBase.java @@ -0,0 +1,38 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.CompileLog; +import dk.camelot64.kickc.model.ControlFlowGraph; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.symbols.ProgramScope; + +/** + * Pass N Calculation base class + */ +public abstract class PassNCalcBase { + + private Program program; + + public PassNCalcBase(Program program) { + this.program = program; + } + + public abstract Data calculate(); + + public Program getProgram() { + return program; + } + + public ProgramScope getScope() { + return program.getScope(); + } + + public CompileLog getLog() { + return program.getLog(); + } + + public ControlFlowGraph getGraph() { + return program.getGraph(); + } + + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNCallGraphAnalysis.java b/src/main/java/dk/camelot64/kickc/passes/PassNCalcCallGraph.java similarity index 89% rename from src/main/java/dk/camelot64/kickc/passes/PassNCallGraphAnalysis.java rename to src/main/java/dk/camelot64/kickc/passes/PassNCalcCallGraph.java index 08aee974f..beec015c2 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNCallGraphAnalysis.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNCalcCallGraph.java @@ -12,15 +12,13 @@ import dk.camelot64.kickc.model.values.ProcedureRef; import dk.camelot64.kickc.model.values.ScopeRef; /** Finds the call graph for the control flow graph - identifies all calls in all scopes and creates a graph from these. */ -public class PassNCallGraphAnalysis extends Pass2SsaOptimization { +public class PassNCalcCallGraph extends PassNCalcBase { - - public PassNCallGraphAnalysis(Program program) { + public PassNCalcCallGraph(Program program) { super(program); } - @Override - public boolean step() { + public CallGraph calculate() { CallGraph callGraph = new CallGraph(); for(ControlFlowBlock block : getGraph().getAllBlocks()) { ScopeRef scopeRef = getScopeRef(block, getProgram()); @@ -32,8 +30,7 @@ public class PassNCallGraphAnalysis extends Pass2SsaOptimization { } } } - getProgram().setCallGraph(callGraph); - return false; + return callGraph; } /**