1
0
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:
jespergravgaard 2017-07-28 01:23:20 +02:00
parent 45e64d59f1
commit d1a13402fe
7 changed files with 157 additions and 22 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -95,6 +95,7 @@ public class Pass3LoopAnalysis {
} }
} }
} }
program.getGraph().setLoops(loopSet); program.getGraph().setLoops(loopSet);
} }

View 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();
}
}