mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-08 17:54:40 +00:00
Added loop depth analysis pass - not implemented yet.
This commit is contained in:
parent
45e64d59f1
commit
d1a13402fe
@ -141,6 +141,11 @@ public class Compiler {
|
|||||||
log.append("NATURAL LOOPS");
|
log.append("NATURAL LOOPS");
|
||||||
log.append(program.getGraph().getLoopSet().toString());
|
log.append(program.getGraph().getLoopSet().toString());
|
||||||
|
|
||||||
|
Pass3LoopDepthAnalysis pass3LoopDepthAnalysis = new Pass3LoopDepthAnalysis(program, log);
|
||||||
|
pass3LoopDepthAnalysis.findLoopDepths();
|
||||||
|
log.append("NATURAL LOOPS WITH DEPTH");
|
||||||
|
log.append(program.getGraph().getLoopSet().toString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pass2OptimizeSSA(Program program, CompileLog log) {
|
public void pass2OptimizeSSA(Program program, CompileLog log) {
|
||||||
|
@ -1,37 +1,70 @@
|
|||||||
package dk.camelot64.kickc.icl;
|
package dk.camelot64.kickc.icl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** The call graph for the entire control flow graph.
|
/**
|
||||||
|
* The call graph for the entire control flow graph.
|
||||||
* Created by {@link dk.camelot64.kickc.passes.Pass3CallGraphAnalysis}
|
* Created by {@link dk.camelot64.kickc.passes.Pass3CallGraphAnalysis}
|
||||||
* */
|
*/
|
||||||
public class CallGraph {
|
public class CallGraph {
|
||||||
|
|
||||||
private List<CallBlock> callBlocks;
|
private List<CallBlock> callBlocks;
|
||||||
|
|
||||||
|
|
||||||
public CallGraph() {
|
public CallGraph() {
|
||||||
this.callBlocks = new ArrayList<>();
|
this.callBlocks = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the call block for a specific scope. Create it if it does not already exist.
|
* Get the call block for a specific scope. Create it if it does not already exist.
|
||||||
|
*
|
||||||
* @param scopeLabel The label for the scope.
|
* @param scopeLabel The label for the scope.
|
||||||
* @return The call block for the scope
|
* @return The call block for the scope
|
||||||
*/
|
*/
|
||||||
public CallBlock getOrCreateCallBlock(LabelRef scopeLabel) {
|
public CallBlock getOrCreateCallBlock(LabelRef scopeLabel) {
|
||||||
for (CallBlock callBlock : callBlocks) {
|
CallBlock callBlock = getCallBlock(scopeLabel);
|
||||||
if(callBlock.getScopeLabel().equals(scopeLabel)) {
|
if (callBlock != null) return callBlock;
|
||||||
return callBlock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Not found - create it
|
// Not found - create it
|
||||||
CallBlock newCallBlock = new CallBlock(scopeLabel);
|
CallBlock newCallBlock = new CallBlock(scopeLabel);
|
||||||
callBlocks.add(newCallBlock);
|
callBlocks.add(newCallBlock);
|
||||||
return newCallBlock;
|
return newCallBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the call block for a specific scope.
|
||||||
|
*
|
||||||
|
* @param scopeLabel The label for the scope.
|
||||||
|
* @return The call block for the scope. Null if the call block does not exist (no calls are made from it).
|
||||||
|
*/
|
||||||
|
private CallBlock getCallBlock(LabelRef scopeLabel) {
|
||||||
|
for (CallBlock callBlock : callBlocks) {
|
||||||
|
if (callBlock.getScopeLabel().equals(scopeLabel)) {
|
||||||
|
return callBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallBlock getFirstCallBlock() {
|
||||||
|
return getOrCreateCallBlock(new LabelRef(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sub call blocks called from a specific call block.
|
||||||
|
* @param block The block to find subs for
|
||||||
|
* @return The sub call blocks called from the passed block
|
||||||
|
*/
|
||||||
|
public Collection<CallBlock> getCalledBlocks(CallBlock block) {
|
||||||
|
Collection<LabelRef> calledLabels = block.getCalledBlocks();
|
||||||
|
LinkedHashSet<CallBlock> called = new LinkedHashSet<>();
|
||||||
|
for (LabelRef calledLabel : calledLabels) {
|
||||||
|
called.add(getOrCreateCallBlock(calledLabel));
|
||||||
|
}
|
||||||
|
return called;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
@ -41,10 +74,14 @@ public class CallGraph {
|
|||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A block in the call graph, matching a scope in the program. */
|
/**
|
||||||
|
* A block in the call graph, matching a scope in the program.
|
||||||
|
*/
|
||||||
public static class CallBlock {
|
public static class CallBlock {
|
||||||
|
|
||||||
/** The label of the scope. (Program scope has label "" and procedure scopes have their respective labels). */
|
/**
|
||||||
|
* The label of the scope. (Program scope has label "" and procedure scopes have their respective labels).
|
||||||
|
*/
|
||||||
private LabelRef scopeLabel;
|
private LabelRef scopeLabel;
|
||||||
|
|
||||||
private List<Call> calls;
|
private List<Call> calls;
|
||||||
@ -62,6 +99,20 @@ public class CallGraph {
|
|||||||
this.calls.add(new Call(procedureLabel, statementCall));
|
this.calls.add(new Call(procedureLabel, statementCall));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all call blocks called from this one.
|
||||||
|
*
|
||||||
|
* @return The scope labels of all call blocks called from this one.
|
||||||
|
*/
|
||||||
|
public Collection<LabelRef> getCalledBlocks() {
|
||||||
|
LinkedHashSet<LabelRef> called = new LinkedHashSet<>();
|
||||||
|
for (Call call : calls) {
|
||||||
|
called.add(call.getProcedure());
|
||||||
|
}
|
||||||
|
return called;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
@ -72,13 +123,19 @@ public class CallGraph {
|
|||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A single call in the call block. */
|
/**
|
||||||
|
* A single call found in the call block.
|
||||||
|
*/
|
||||||
public static class Call {
|
public static class Call {
|
||||||
|
|
||||||
/** Statement index of the call statement, */
|
/**
|
||||||
|
* Statement index of the call statement,
|
||||||
|
*/
|
||||||
private Integer callStatementIdx;
|
private Integer callStatementIdx;
|
||||||
|
|
||||||
/** The label of the called procedure. */
|
/**
|
||||||
|
* The label of the called procedure.
|
||||||
|
*/
|
||||||
private LabelRef procedure;
|
private LabelRef procedure;
|
||||||
|
|
||||||
public Call(LabelRef procedure, StatementCall statementCall) {
|
public Call(LabelRef procedure, StatementCall statementCall) {
|
||||||
@ -86,12 +143,21 @@ public class CallGraph {
|
|||||||
this.procedure = procedure;
|
this.procedure = procedure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LabelRef getProcedure() {
|
||||||
|
return procedure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCallStatementIdx() {
|
||||||
|
return callStatementIdx;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
out.append(callStatementIdx).append(":").append(procedure);
|
out.append(callStatementIdx).append(":").append(procedure);
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,14 @@ public class ControlFlowGraph {
|
|||||||
|
|
||||||
private Map<LabelRef, ControlFlowBlock> blocks;
|
private Map<LabelRef, ControlFlowBlock> blocks;
|
||||||
private LabelRef firstBlockRef;
|
private LabelRef firstBlockRef;
|
||||||
|
|
||||||
|
/** Sequence of blocks used when generating ASM */
|
||||||
private List<LabelRef> sequence;
|
private List<LabelRef> sequence;
|
||||||
|
/** Information about dominators of all blocks*/
|
||||||
private DominatorsGraph dominators;
|
private DominatorsGraph dominators;
|
||||||
|
/** Information about loops. */
|
||||||
private NaturalLoopSet loopSet;
|
private NaturalLoopSet loopSet;
|
||||||
|
/** Information about calls. */
|
||||||
private CallGraph callGraph;
|
private CallGraph callGraph;
|
||||||
|
|
||||||
public ControlFlowGraph(Map<LabelRef, ControlFlowBlock> blocks, LabelRef firstBlockRef) {
|
public ControlFlowGraph(Map<LabelRef, ControlFlowBlock> blocks, LabelRef firstBlockRef) {
|
||||||
|
@ -10,7 +10,7 @@ public class Label implements Symbol {
|
|||||||
/** The name of the label. */
|
/** The name of the label. */
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/** The name of the containing scope */
|
/** The containing scope */
|
||||||
private Scope scope;
|
private Scope scope;
|
||||||
|
|
||||||
private boolean intermediate;
|
private boolean intermediate;
|
||||||
|
@ -26,14 +26,7 @@ public class Pass3CallGraphAnalysis {
|
|||||||
CallGraph callGraph = new CallGraph();
|
CallGraph callGraph = new CallGraph();
|
||||||
|
|
||||||
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
|
||||||
Symbol blockSymbol = program.getScope().getSymbol(block.getLabel());
|
LabelRef scopeRef = getScopeRef(block, program);
|
||||||
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()) {
|
for (Statement statement : block.getStatements()) {
|
||||||
if(statement instanceof StatementCall) {
|
if(statement instanceof StatementCall) {
|
||||||
ProcedureRef procedure = ((StatementCall) statement).getProcedure();
|
ProcedureRef procedure = ((StatementCall) statement).getProcedure();
|
||||||
@ -46,4 +39,22 @@ public class Pass3CallGraphAnalysis {
|
|||||||
program.getGraph().setCallGraph(callGraph);
|
program.getGraph().setCallGraph(callGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a label reference representing the scope of a block
|
||||||
|
*
|
||||||
|
* @param block The block
|
||||||
|
* @return The label of the scope containing the block. The outermost scope has a label containing an empty string.
|
||||||
|
*/
|
||||||
|
public static LabelRef getScopeRef(ControlFlowBlock block, Program program) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
return scopeRef;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,7 @@ public class Pass3LoopAnalysis {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
program.getGraph().setLoops(loopSet);
|
program.getGraph().setLoops(loopSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
47
src/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java
Normal file
47
src/dk/camelot64/kickc/passes/Pass3LoopDepthAnalysis.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package dk.camelot64.kickc.passes;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.CompileLog;
|
||||||
|
import dk.camelot64.kickc.icl.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the depth of loops in the control flow graph.
|
||||||
|
* Uses the call graph and natural loops of the control flow graph.
|
||||||
|
*/
|
||||||
|
public class Pass3LoopDepthAnalysis {
|
||||||
|
|
||||||
|
private Program program;
|
||||||
|
private CompileLog log;
|
||||||
|
|
||||||
|
public Pass3LoopDepthAnalysis(Program program, CompileLog log) {
|
||||||
|
this.program = program;
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Program getProgram() {
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompileLog getLog() {
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the depth of loops in the control flow graph.
|
||||||
|
* Uses the call graph and natural loops of the control flow graph.
|
||||||
|
*/
|
||||||
|
public void findLoopDepths() {
|
||||||
|
CallGraph callGraph = program.getGraph().getCallGraph();
|
||||||
|
NaturalLoopSet loopSet = program.getGraph().getLoopSet();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user