mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-20 07:30:00 +00:00
Implemented call graph analysis.
This commit is contained in:
parent
e7ea5fb4ea
commit
d501534561
@ -126,6 +126,11 @@ public class Compiler {
|
|||||||
log.append(program.getGraph().toString(program.getScope()));
|
log.append(program.getGraph().toString(program.getScope()));
|
||||||
pass2AssertSSA(program, log);
|
pass2AssertSSA(program, log);
|
||||||
|
|
||||||
|
Pass3CallGraphAnalysis pass3CallGraphAnalysis = new Pass3CallGraphAnalysis(program, log);
|
||||||
|
pass3CallGraphAnalysis.findCallGraph();
|
||||||
|
log.append("CALL GRAPH");
|
||||||
|
log.append(program.getGraph().getCallGraph().toString());
|
||||||
|
|
||||||
Pass3DominatorsAnalysis pass3DominatorsAnalysis = new Pass3DominatorsAnalysis(program, log);
|
Pass3DominatorsAnalysis pass3DominatorsAnalysis = new Pass3DominatorsAnalysis(program, log);
|
||||||
pass3DominatorsAnalysis.findDominators();
|
pass3DominatorsAnalysis.findDominators();
|
||||||
log.append("DOMINATORS");
|
log.append("DOMINATORS");
|
||||||
|
96
src/dk/camelot64/kickc/icl/CallGraph.java
Normal file
96
src/dk/camelot64/kickc/icl/CallGraph.java
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package dk.camelot64.kickc.icl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** The call graph for the entire control flow graph, */
|
||||||
|
public class CallGraph {
|
||||||
|
|
||||||
|
private List<CallBlock> callBlocks;
|
||||||
|
|
||||||
|
|
||||||
|
public CallGraph() {
|
||||||
|
this.callBlocks = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the call block for a specific scope. Create it if it does not already exist.
|
||||||
|
* @param scopeLabel The label for the scope.
|
||||||
|
* @return The call block for the scope
|
||||||
|
*/
|
||||||
|
public CallBlock getOrCreateCallBlock(LabelRef scopeLabel) {
|
||||||
|
for (CallBlock callBlock : callBlocks) {
|
||||||
|
if(callBlock.getScopeLabel().equals(scopeLabel)) {
|
||||||
|
return callBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not found - create it
|
||||||
|
CallBlock newCallBlock = new CallBlock(scopeLabel);
|
||||||
|
callBlocks.add(newCallBlock);
|
||||||
|
return newCallBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
for (CallBlock callBlock : callBlocks) {
|
||||||
|
out.append(callBlock.toString()).append("\n");
|
||||||
|
}
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A block in the call graph, matching a scope in the program. */
|
||||||
|
public static class CallBlock {
|
||||||
|
|
||||||
|
/** The label of the scope. (Program scope has label "" and procedure scopes have their respective labels). */
|
||||||
|
private LabelRef scopeLabel;
|
||||||
|
|
||||||
|
private List<Call> calls;
|
||||||
|
|
||||||
|
public CallBlock(LabelRef scopeLabel) {
|
||||||
|
this.scopeLabel = scopeLabel;
|
||||||
|
this.calls = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LabelRef getScopeLabel() {
|
||||||
|
return scopeLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCall(LabelRef procedureLabel, StatementCall statementCall) {
|
||||||
|
this.calls.add(new Call(procedureLabel, statementCall));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
out.append("Calls in [").append(scopeLabel.toString()).append("] to ");
|
||||||
|
for (Call call : calls) {
|
||||||
|
out.append(call.toString()).append(" ");
|
||||||
|
}
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A single call in the call block. */
|
||||||
|
public static class Call {
|
||||||
|
|
||||||
|
/** Statement index of the call statement, */
|
||||||
|
private Integer callStatementIdx;
|
||||||
|
|
||||||
|
/** The label of the called procedure. */
|
||||||
|
private LabelRef procedure;
|
||||||
|
|
||||||
|
public Call(LabelRef procedure, StatementCall statementCall) {
|
||||||
|
this.callStatementIdx = statementCall.getIndex();
|
||||||
|
this.procedure = procedure;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
out.append(callStatementIdx).append(":").append(procedure);
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ public class ControlFlowGraph {
|
|||||||
private List<LabelRef> sequence;
|
private List<LabelRef> sequence;
|
||||||
private DominatorsGraph dominators;
|
private DominatorsGraph dominators;
|
||||||
private NaturalLoopSet loopSet;
|
private NaturalLoopSet loopSet;
|
||||||
|
private CallGraph callGraph;
|
||||||
|
|
||||||
public ControlFlowGraph(Map<LabelRef, ControlFlowBlock> blocks, LabelRef firstBlockRef) {
|
public ControlFlowGraph(Map<LabelRef, ControlFlowBlock> blocks, LabelRef firstBlockRef) {
|
||||||
this.blocks = blocks;
|
this.blocks = blocks;
|
||||||
@ -193,4 +194,12 @@ public class ControlFlowGraph {
|
|||||||
return loopSet;
|
return loopSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CallGraph getCallGraph() {
|
||||||
|
return callGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallGraph(CallGraph callGraph) {
|
||||||
|
this.callGraph = callGraph;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
49
src/dk/camelot64/kickc/passes/Pass3CallGraphAnalysis.java
Normal file
49
src/dk/camelot64/kickc/passes/Pass3CallGraphAnalysis.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package dk.camelot64.kickc.passes;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
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 void findCallGraph() {
|
||||||
|
CallGraph callGraph = new CallGraph();
|
||||||
|
|
||||||
|
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||||
|
Symbol blockSymbol = program.getScope().getSymbol(block.getLabel());
|
||||||
|
LabelRef scopeRef;
|
||||||
|
if(blockSymbol instanceof Procedure) {
|
||||||
|
scopeRef = ((Procedure) blockSymbol).getRef().getLabelRef();
|
||||||
|
} else {
|
||||||
|
Scope blockScope = blockSymbol.getScope();
|
||||||
|
scopeRef = new LabelRef(blockScope.getFullName());
|
||||||
|
}
|
||||||
|
for (Statement statement : block.getStatements()) {
|
||||||
|
if(statement instanceof StatementCall) {
|
||||||
|
ProcedureRef procedure = ((StatementCall) statement).getProcedure();
|
||||||
|
LabelRef procedureLabel = procedure.getLabelRef();
|
||||||
|
CallGraph.CallBlock callBlock = callGraph.getOrCreateCallBlock(scopeRef);
|
||||||
|
callBlock.addCall(procedureLabel, (StatementCall) statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
program.getGraph().setCallGraph(callGraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -985,6 +985,8 @@ CONTROL FLOW GRAPH - PHI MEM COALESCED
|
|||||||
[10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ]
|
[10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ]
|
||||||
to:@3
|
to:@3
|
||||||
|
|
||||||
|
CALL GRAPH
|
||||||
|
|
||||||
DOMINATORS
|
DOMINATORS
|
||||||
@BEGIN dominated by @BEGIN
|
@BEGIN dominated by @BEGIN
|
||||||
@1 dominated by @1 @BEGIN
|
@1 dominated by @1 @BEGIN
|
||||||
|
@ -3733,6 +3733,10 @@ prepare::@return: from prepare::@1
|
|||||||
[45] return [ ]
|
[45] return [ ]
|
||||||
to:@RETURN
|
to:@RETURN
|
||||||
|
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [] to 0:main
|
||||||
|
Calls in [main] to 1:prepare 9:flip 10:plot
|
||||||
|
|
||||||
DOMINATORS
|
DOMINATORS
|
||||||
@BEGIN dominated by @BEGIN
|
@BEGIN dominated by @BEGIN
|
||||||
@END dominated by @BEGIN @END
|
@END dominated by @BEGIN @END
|
||||||
|
@ -341,6 +341,8 @@ CONTROL FLOW GRAPH - PHI MEM COALESCED
|
|||||||
[5] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ]
|
[5] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ]
|
||||||
to:@3
|
to:@3
|
||||||
|
|
||||||
|
CALL GRAPH
|
||||||
|
|
||||||
DOMINATORS
|
DOMINATORS
|
||||||
@BEGIN dominated by @BEGIN
|
@BEGIN dominated by @BEGIN
|
||||||
@1 dominated by @1 @BEGIN
|
@1 dominated by @1 @BEGIN
|
||||||
|
@ -361,6 +361,8 @@ CONTROL FLOW GRAPH - PHI MEM COALESCED
|
|||||||
[5] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ]
|
[5] (byte) s#1 ← ++ (byte) s#3 [ i#1 s#1 ]
|
||||||
to:@1
|
to:@1
|
||||||
|
|
||||||
|
CALL GRAPH
|
||||||
|
|
||||||
DOMINATORS
|
DOMINATORS
|
||||||
@BEGIN dominated by @BEGIN
|
@BEGIN dominated by @BEGIN
|
||||||
@1 dominated by @1 @BEGIN
|
@1 dominated by @1 @BEGIN
|
||||||
|
@ -263,6 +263,8 @@ CONTROL FLOW GRAPH - PHI MEM COALESCED
|
|||||||
to:@END
|
to:@END
|
||||||
@END: from @1
|
@END: from @1
|
||||||
|
|
||||||
|
CALL GRAPH
|
||||||
|
|
||||||
DOMINATORS
|
DOMINATORS
|
||||||
@BEGIN dominated by @BEGIN
|
@BEGIN dominated by @BEGIN
|
||||||
@1 dominated by @1 @BEGIN
|
@1 dominated by @1 @BEGIN
|
||||||
|
@ -298,6 +298,9 @@ sum::@return: from sum
|
|||||||
[4] return (byte) s1#0 [ ]
|
[4] return (byte) s1#0 [ ]
|
||||||
to:@RETURN
|
to:@RETURN
|
||||||
|
|
||||||
|
CALL GRAPH
|
||||||
|
Calls in [] to 0:sum 1:sum
|
||||||
|
|
||||||
DOMINATORS
|
DOMINATORS
|
||||||
@BEGIN dominated by @BEGIN
|
@BEGIN dominated by @BEGIN
|
||||||
@2 dominated by @BEGIN @2
|
@2 dominated by @BEGIN @2
|
||||||
|
Loading…
Reference in New Issue
Block a user