mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-27 19:50:10 +00:00
Refactored call-graph to be calculated on demand.
This commit is contained in:
parent
bc1dd78bd8
commit
1f39ab8c37
@ -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();
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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<Number> 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) {
|
||||
|
@ -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);
|
||||
|
38
src/main/java/dk/camelot64/kickc/passes/PassNCalcBase.java
Normal file
38
src/main/java/dk/camelot64/kickc/passes/PassNCalcBase.java
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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<CallGraph> {
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
Loading…
Reference in New Issue
Block a user