1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-23 23:32:55 +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 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();

View File

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

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.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) {
@ -387,6 +399,6 @@ public class Program {
public void setLog(CompileLog log) {
this.log = log;
}
}

View File

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

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