1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-24 14:31:15 +00:00

Refactored call-graph to be calculated on demand.

This commit is contained in:
jespergravgaard 2019-08-01 23:52:05 +02:00
parent bc1dd78bd8
commit 1f39ab8c37
6 changed files with 68 additions and 21 deletions

View File

@ -200,7 +200,7 @@ public class Compiler {
} }
new Pass1ProcedureInline(program).execute(); new Pass1ProcedureInline(program).execute();
new PassNStatementIndices(program).step(); new PassNStatementIndices(program).step();
new PassNCallGraphAnalysis(program).step(); program.clearCallGraph();
new Pass1AssertNoRecursion(program).execute(); new Pass1AssertNoRecursion(program).execute();
new Pass1AssertInterrupts(program).execute(); new Pass1AssertInterrupts(program).execute();
@ -422,7 +422,7 @@ public class Compiler {
new PassNStatementIndices(program).execute(); new PassNStatementIndices(program).execute();
getLog().append("CALL GRAPH"); getLog().append("CALL GRAPH");
new PassNCallGraphAnalysis(program).step(); program.clearCallGraph();
getLog().append(program.getCallGraph().toString()); getLog().append(program.getCallGraph().toString());
//getLog().setVerboseLiveRanges(true); //getLog().setVerboseLiveRanges(true);
@ -443,7 +443,7 @@ public class Compiler {
new PassNBlockSequencePlanner(program).step(); new PassNBlockSequencePlanner(program).step();
new Pass3AddNopBeforeCallOns(program).generate(); new Pass3AddNopBeforeCallOns(program).generate();
new PassNStatementIndices(program).execute(); new PassNStatementIndices(program).execute();
new PassNCallGraphAnalysis(program).step(); program.clearCallGraph();
new PassNStatementInfos(program).execute(); new PassNStatementInfos(program).execute();
new PassNVariableReferenceInfos(program).execute(); new PassNVariableReferenceInfos(program).execute();
new Pass3SymbolInfos(program).generateSymbolInfos(); new Pass3SymbolInfos(program).generateSymbolInfos();

View File

@ -3,13 +3,13 @@ package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.statements.StatementCall; import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.values.ProcedureRef; import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.ScopeRef; import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.passes.PassNCallGraphAnalysis; import dk.camelot64.kickc.passes.PassNCalcCallGraph;
import java.util.*; import java.util.*;
/** /**
* The call graph for the entire control flow graph. * The call graph for the entire control flow graph.
* Created by {@link PassNCallGraphAnalysis} * Created by {@link PassNCalcCallGraph}
*/ */
public class CallGraph { public class CallGraph {

View File

@ -6,6 +6,7 @@ import dk.camelot64.kickc.model.statements.StatementInfos;
import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.values.LabelRef; import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.VariableRef; import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.passes.PassNCalcCallGraph;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
@ -55,7 +56,7 @@ public class Program {
/** The 6502 ASM program. PASS 4-5 (DYNAMIC) */ /** The 6502 ASM program. PASS 4-5 (DYNAMIC) */
private AsmProgram asm; 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; private ProgramSnapshot snapshot;
/** Cached information about calls. PASS 1-4 (CACHED) */ /** 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. */ /** Save a snapshot of the dynamic parts of the program. */
public void saveSnapshot() { public void snapshotCreate() {
if(this.snapshot!=null) if(this.snapshot != null)
throw new InternalError("Snapshot already saved!"); throw new InternalError("Snapshot already saved!");
if(this.liveRangeEquivalenceClassSet!=null) if(this.liveRangeEquivalenceClassSet != null)
throw new InternalError("Compiler Program Snapshot does not support liveRangeEquivalenceClassSet!"); throw new InternalError("Compiler Program Snapshot does not support liveRangeEquivalenceClassSet!");
this.snapshot = new ProgramSnapshot(scope, graph); this.snapshot = new ProgramSnapshot(scope, graph);
} }
/** Restore the snapshot of the dynamic parts of the program. Clear all cached data and the snapshot. */ /** 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.scope = snapshot.getScope();
this.graph = snapshot.getGraph(); this.graph = snapshot.getGraph();
this.snapshot = null; this.snapshot = null;
@ -239,12 +240,21 @@ public class Program {
this.asm = asm; 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() { public CallGraph getCallGraph() {
if(callGraph == null)
this.callGraph = new PassNCalcCallGraph(this).calculate();
return callGraph; 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() { 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. * Adds a bunch of reserved zero-page addresses that the compiler is not allowed to use.
*
* @param reservedZp addresses to reserve * @param reservedZp addresses to reserve
*/ */
public void addReservedZps(List<Number> reservedZp) { public void addReservedZps(List<Number> reservedZp) {
@ -370,6 +381,7 @@ public class Program {
/** /**
* Set the absolute position of the program code * Set the absolute position of the program code
*
* @param programPc The address * @param programPc The address
*/ */
public void setProgramPc(Number programPc) { public void setProgramPc(Number programPc) {

View File

@ -97,7 +97,7 @@ public class Pass3LoopDepthAnalysis extends Pass2Base {
for(NaturalLoop loop : loopSet.getLoops()) { for(NaturalLoop loop : loopSet.getLoops()) {
LabelRef loopHead = loop.getHead(); LabelRef loopHead = loop.getHead();
ControlFlowBlock loopHeadBlock = getGraph().getBlock(loopHead); ControlFlowBlock loopHeadBlock = getGraph().getBlock(loopHead);
ScopeRef scopeRef = PassNCallGraphAnalysis.getScopeRef(loopHeadBlock, getProgram()); ScopeRef scopeRef = PassNCalcCallGraph.getScopeRef(loopHeadBlock, getProgram());
if(scopeRef.equals(currentScope)) { if(scopeRef.equals(currentScope)) {
// Loop is inside current scope block! // Loop is inside current scope block!
currentScopeLoops.add(loop); currentScopeLoops.add(loop);

View File

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

View File

@ -12,15 +12,13 @@ import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.ScopeRef; 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. */ /** 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<CallGraph> {
public PassNCalcCallGraph(Program program) {
public PassNCallGraphAnalysis(Program program) {
super(program); super(program);
} }
@Override public CallGraph calculate() {
public boolean step() {
CallGraph callGraph = new CallGraph(); CallGraph callGraph = new CallGraph();
for(ControlFlowBlock block : getGraph().getAllBlocks()) { for(ControlFlowBlock block : getGraph().getAllBlocks()) {
ScopeRef scopeRef = getScopeRef(block, getProgram()); ScopeRef scopeRef = getScopeRef(block, getProgram());
@ -32,8 +30,7 @@ public class PassNCallGraphAnalysis extends Pass2SsaOptimization {
} }
} }
} }
getProgram().setCallGraph(callGraph); return callGraph;
return false;
} }
/** /**