1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-02 00:41:42 +00:00

#815 working on generalizing the control flow graph and control flow block into an interface.

This commit is contained in:
jespergravgaard 2023-04-08 22:52:15 +02:00
parent 185bd439e4
commit 5a74d14b41
122 changed files with 682 additions and 642 deletions

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.fragment;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
@ -41,7 +42,7 @@ public class AsmEncodingHelper {
public static Set<StringEncoding> getEncoding(Value value) {
LinkedHashSet<StringEncoding> encodings = new LinkedHashSet<>();
ProgramValue programValue = new ProgramValue.GenericValue(value);
ProgramValueHandler handler = (ProgramValue pVal, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) -> {
ProgramValueHandler handler = (ProgramValue pVal, Statement currentStmt, ListIterator<Statement> stmtIt, Graph.Block currentBlock) -> {
Value val = pVal.get();
if(val instanceof ConstantChar) {
encodings.add(((ConstantChar) val).getEncoding());

View File

@ -4,10 +4,7 @@ import dk.camelot64.kickc.asm.AsmFormat;
import dk.camelot64.kickc.fragment.signature.AsmFragmentBindings;
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignature;
import dk.camelot64.kickc.fragment.signature.AsmFragmentSignatureExpr;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.ControlFlowGraph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.operators.Operator;
import dk.camelot64.kickc.model.operators.OperatorBinary;
import dk.camelot64.kickc.model.operators.OperatorUnary;
@ -69,7 +66,7 @@ final public class AsmFragmentInstanceSpecBuilder {
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
}
public static AsmFragmentInstanceSpec conditionalJump(StatementConditionalJump conditionalJump, ControlFlowBlock block, Program program) {
public static AsmFragmentInstanceSpec conditionalJump(StatementConditionalJump conditionalJump, Graph.Block block, Program program) {
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
ScopeRef codeScope = program.getStatementInfos().getBlock(conditionalJump).getScope();
AsmFragmentSignature signature = conditionalJumpSignature(bindings, conditionalJump, block, program.getGraph());
@ -162,8 +159,8 @@ final public class AsmFragmentInstanceSpecBuilder {
private static AsmFragmentSignature conditionalJumpSignature(
AsmFragmentBindings bindings,
StatementConditionalJump conditionalJump,
ControlFlowBlock block,
ControlFlowGraph graph) {
Graph.Block block,
Graph graph) {
AsmFragmentSignatureExpr rVal1SignatureExpr = null;
if (conditionalJump.getrValue1() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue1()).getValue() == 0) {
rVal1SignatureExpr = new AsmFragmentSignatureExpr.Number(new ConstantInteger(0L));
@ -189,7 +186,7 @@ final public class AsmFragmentInstanceSpecBuilder {
}
LabelRef destination = conditionalJump.getDestination();
ControlFlowBlock destinationBlock = graph.getBlock(destination);
Graph.Block destinationBlock = graph.getBlock(destination);
String destinationLabel;
if (destinationBlock.hasPhiBlock()) {
destinationLabel =

View File

@ -5,6 +5,7 @@ import dk.camelot64.kickc.model.values.LabelRef;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* A set of blocks
@ -22,14 +23,8 @@ public interface BlockSet {
* @param graph The control flow graph containing the blocks
* @return The blocks of the loop (in the same order as they appear in the control flow graph.)
*/
default List<ControlFlowBlock> getBlocks(ControlFlowGraph graph) {
ArrayList<ControlFlowBlock> controlFlowBlocks = new ArrayList<>();
for(ControlFlowBlock block : graph.getAllBlocks()) {
if(getBlocks().contains(block.getLabel())) {
controlFlowBlocks.add(block);
}
}
return controlFlowBlocks;
default List<Graph.Block> getBlocks(Graph graph) {
return graph.getAllBlocks().stream().filter(block -> getBlocks().contains(block.getLabel())).collect(Collectors.toList());
}
/**

View File

@ -2,8 +2,6 @@ package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.symbols.Symbol;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ScopeRef;
@ -17,7 +15,7 @@ import java.util.ListIterator;
* The connections defines the control flow of the program.
* The block only knows its own successors. To find predecessor blocks access to the entire graph is needed.
*/
public class ControlFlowBlock {
public class ControlFlowBlock implements Graph.Block {
/** The label representing the block. */
private LabelRef label;
@ -139,16 +137,6 @@ public class ControlFlowBlock {
return statements;
}
/**
* Is the block the entry of a procedure, ie. the first block of the code of the procedure.
*
* @return true if this is the entry of a procedure
*/
public boolean isProcedureEntry(Program program) {
Symbol symbol = program.getScope().getSymbol(getLabel());
return (symbol instanceof Procedure);
}
/**
* Is the block the exit of a procedure, ie. the last block of code of the the procedure
*
@ -159,26 +147,11 @@ public class ControlFlowBlock {
return getLabel().isProcExit();
}
/**
* Get the procedure, that the block is part of. Null if the block is not part of a procedure.
*
* @return the procedure, that the block is part of
*/
public Procedure getProcedure(Program program) {
final ScopeRef scopeRef = getScope();
final Scope scope = program.getScope().getScope(scopeRef);
if(scope instanceof Procedure) {
return (Procedure) scope;
} else {
return null;
}
}
public String toString(Program program, ControlFlowGraph graph) {
public String toString(Program program, Graph graph) {
StringBuffer out = new StringBuffer();
if(isProcedureEntry(program)) {
if(program.isProcedureEntry(this)) {
Procedure procedure = (Procedure) program.getScope().getScope(scope);
out.append("\n");
out.append(procedure.toString(program)+"\n");
@ -188,9 +161,9 @@ public class ControlFlowBlock {
out.append(" scope:[" + this.scope.getFullName() + "] ");
out.append(" from");
if(graph != null) {
List<ControlFlowBlock> predecessors = graph.getPredecessors(this);
List<Graph.Block> predecessors = graph.getPredecessors(this);
if(predecessors.size() > 0) {
for(ControlFlowBlock predecessor : predecessors) {
for(Graph.Block predecessor : predecessors) {
out.append(" " + predecessor.getLabel().getFullName());
}
}
@ -206,7 +179,7 @@ public class ControlFlowBlock {
}
if(program.getLog().isVerboseSsaSourceCode()) {
if(statement.getSource()!=null && statement.getSource().getCode()!=null)
out.append(" // " + statement.getSource().getCode()).append("\n");
out.append(" // " + statement.getSource().getCode()).append("\n");
}
out.append(" " + statement.toString(program, program.getLog().isVerboseLiveRanges()) + "\n");
}
@ -269,23 +242,4 @@ public class ControlFlowBlock {
}
/**
* Get all successors of the block
*
* @return All successors
*/
public Collection<LabelRef> getSuccessors() {
List<LabelRef> successors = new ArrayList<>();
if(defaultSuccessor != null) {
successors.add(defaultSuccessor);
}
if(conditionalSuccessor != null) {
successors.add(conditionalSuccessor);
}
if(callSuccessor != null) {
successors.add(callSuccessor);
}
return successors;
}
}

View File

@ -1,15 +1,8 @@
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCalling;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Label;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.passes.utils.ProcedureUtils;
import java.util.*;
@ -17,7 +10,7 @@ import java.util.*;
* The control flow graph of the program.
* The control flow graph is a set of connected basic blocks.
*/
public class ControlFlowGraph {
public class ControlFlowGraph implements Graph {
private List<ControlFlowBlock> blocks;
@ -43,8 +36,8 @@ public class ControlFlowGraph {
blocks.add(block);
}
public List<ControlFlowBlock> getAllBlocks() {
return blocks;
public List<Block> getAllBlocks() {
return Collections.unmodifiableList(blocks);
}
public void setAllBlocks(List<ControlFlowBlock> blocks) {
@ -62,47 +55,6 @@ public class ControlFlowGraph {
}
}
public ControlFlowBlock getDefaultSuccessor(ControlFlowBlock block) {
if(block.getDefaultSuccessor() != null) {
return getBlock(block.getDefaultSuccessor());
} else {
return null;
}
}
public ControlFlowBlock getCallSuccessor(ControlFlowBlock block) {
if(block.getCallSuccessor() != null) {
return getBlock(block.getCallSuccessor());
} else {
return null;
}
}
public ControlFlowBlock getConditionalSuccessor(ControlFlowBlock block) {
if(block.getConditionalSuccessor() != null) {
return getBlock(block.getConditionalSuccessor());
} else {
return null;
}
}
public List<ControlFlowBlock> getPredecessors(ControlFlowBlock block) {
ArrayList<ControlFlowBlock> predecessorBlocks = new ArrayList<>();
for(ControlFlowBlock other : getAllBlocks()) {
if(block.getLabel().equals(other.getDefaultSuccessor())) {
predecessorBlocks.add(other);
}
if(block.getLabel().equals(other.getConditionalSuccessor())) {
predecessorBlocks.add(other);
}
if(block.getLabel().equals(other.getCallSuccessor())) {
predecessorBlocks.add(other);
}
}
Collections.sort(predecessorBlocks, Comparator.comparing(o -> o.getLabel().getFullName()));
return predecessorBlocks;
}
public List<LabelRef> getSequence() {
return sequence;
}
@ -119,78 +71,12 @@ public class ControlFlowGraph {
this.blocks = seqBlocks;
}
public ControlFlowBlock getMainBlock() {
for(ControlFlowBlock block : getAllBlocks()) {
LabelRef label = block.getLabel();
if(label.getFullName().equals(SymbolRef.MAIN_PROC_NAME)) {
return block;
}
}
return null;
}
public ControlFlowBlock getStartBlock() {
for(ControlFlowBlock block : getAllBlocks()) {
LabelRef label = block.getLabel();
if(label.getFullName().equals(SymbolRef.START_PROC_NAME)) {
return block;
}
}
return null;
}
/**
* Get all blocks that are program entry points.
* This is the start-block and any blocks referenced by the address-off operator (&)
*
* @param program The program
* @return All entry-point blocks
*/
public List<ControlFlowBlock> getEntryPointBlocks(Program program) {
List<ControlFlowBlock> entryPointBlocks = new ArrayList<>();
for(Procedure procedure : program.getScope().getAllProcedures(true)) {
if(ProcedureUtils.isEntrypoint(procedure.getRef(), program) || Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention()) || Procedure.CallingConvention.VAR_CALL.equals(procedure.getCallingConvention())) {
// Address-of is used on the procedure
Label procedureLabel = procedure.getLabel();
ControlFlowBlock procedureBlock = getBlock(procedureLabel.getRef());
entryPointBlocks.add(procedureBlock);
}
}
return entryPointBlocks;
}
/**
* Get all called procedures in the graph
*
* @return All called procedures
*/
public Set<ProcedureRef> getAllCalledProcedures() {
Set<ProcedureRef> calledProcedures = new LinkedHashSet<>();
for(ControlFlowBlock block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCalling) {
StatementCalling call = (StatementCalling) statement;
ProcedureRef procedureRef = call.getProcedure();
calledProcedures.add(procedureRef);
}
}
}
return calledProcedures;
}
@Override
public String toString() {
return toString(null);
}
public String toString(Program program) {
StringBuffer out = new StringBuffer();
for(ControlFlowBlock block : getAllBlocks()) {
out.append(block.toString(program, this));
}
return out.toString();
}
@Override
public boolean equals(Object o) {
@ -206,51 +92,17 @@ public class ControlFlowGraph {
return Objects.hash(blocks, sequence);
}
/**
* Get a statement from its statement index
*
* @param statementIdx The statement index
* @return The statement
*/
public Statement getStatementByIndex(int statementIdx) {
for(ControlFlowBlock block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement.getIndex() != null && statementIdx == statement.getIndex()) {
return statement;
}
}
}
return null;
}
/**
* Clear all statement indices,
*/
public void clearStatementIndices() {
for(ControlFlowBlock block : getAllBlocks()) {
for(Graph.Block block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
statement.setIndex(null);
}
}
}
/**
* Get all blocks that are part of the execution of a specific scope. (mostly a procedure)
*
* @param scope The scope to find blocks for
* @return All blocks that are part of the execution of the scope
*/
public List<ControlFlowBlock> getScopeBlocks(ScopeRef scope) {
ArrayList<ControlFlowBlock> scopeBlocks = new ArrayList<>();
for(ControlFlowBlock block : getAllBlocks()) {
if(block.getScope().equals(scope)) {
scopeBlocks.add(block);
}
}
return scopeBlocks;
}
/**
* Get all statements executed between two statements (none of these are included in the result)
*
@ -260,7 +112,7 @@ public class ControlFlowGraph {
*/
public Collection<Statement> getStatementsBetween(Statement from, Statement to, StatementInfos statementInfos) {
Collection<Statement> between = new LinkedHashSet<>();
final ControlFlowBlock block = statementInfos.getBlock(from);
final Graph.Block block = statementInfos.getBlock(from);
populateStatementsBetween(from, to, false, between, block);
return between;
}
@ -273,7 +125,7 @@ public class ControlFlowGraph {
* @param between The between collection
* @param block The block to start from
*/
private void populateStatementsBetween(Statement from, Statement to, boolean isBetween, Collection<Statement> between, ControlFlowBlock block) {
private void populateStatementsBetween(Statement from, Statement to, boolean isBetween, Collection<Statement> between, Graph.Block block) {
for(Statement statement : block.getStatements()) {
if(between.contains(statement))
// Stop infinite recursion

View File

@ -7,15 +7,15 @@ import java.util.Collection;
/** Base visitor for iterating through a control flow graph */
public class ControlFlowGraphBaseVisitor<T> {
public T visitGraph(ControlFlowGraph graph) {
Collection<ControlFlowBlock> blocks = graph.getAllBlocks();
for(ControlFlowBlock block : blocks) {
public T visitGraph(Graph graph) {
Collection<Graph.Block> blocks = graph.getAllBlocks();
for(Graph.Block block : blocks) {
this.visitBlock(block);
}
return null;
}
public T visitBlock(ControlFlowBlock block) {
public T visitBlock(Graph.Block block) {
for(Statement statement : block.getStatements()) {
this.visitStatement(statement);
}

View File

@ -0,0 +1,163 @@
package dk.camelot64.kickc.model;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCalling;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.ScopeRef;
import java.util.*;
/**
* A read-only control flow graph.
*/
public interface Graph {
Block getBlock(LabelRef symbol);
List<Block> getAllBlocks();
default List<Graph.Block> getPredecessors(Graph.Block block) {
ArrayList<Block> predecessorBlocks = new ArrayList<>();
for(Graph.Block other : getAllBlocks()) {
if(block.getLabel().equals(other.getDefaultSuccessor())) {
predecessorBlocks.add(other);
}
if(block.getLabel().equals(other.getConditionalSuccessor())) {
predecessorBlocks.add(other);
}
if(block.getLabel().equals(other.getCallSuccessor())) {
predecessorBlocks.add(other);
}
}
predecessorBlocks.sort(Comparator.comparing(o -> o.getLabel().getFullName()));
return predecessorBlocks;
}
/**
* Get all blocks that are part of the execution of a specific scope. (mostly a procedure)
*
* @param scope The scope to find blocks for
* @return All blocks that are part of the execution of the scope
*/
default List<Graph.Block> getScopeBlocks(ScopeRef scope) {
ArrayList<Graph.Block> scopeBlocks = new ArrayList<>();
for(Graph.Block block : getAllBlocks()) {
if(block.getScope().equals(scope)) {
scopeBlocks.add(block);
}
}
return scopeBlocks;
}
/**
* Get a statement from its statement index
*
* @param statementIdx The statement index
* @return The statement
*/
default Statement getStatementByIndex(int statementIdx) {
for(Graph.Block block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement.getIndex() != null && statementIdx == statement.getIndex()) {
return statement;
}
}
}
return null;
}
default Graph.Block getDefaultSuccessor(Graph.Block block) {
if(block.getDefaultSuccessor() != null) {
return getBlock(block.getDefaultSuccessor());
} else {
return null;
}
}
default Graph.Block getCallSuccessor(Graph.Block block) {
if(block.getCallSuccessor() != null) {
return getBlock(block.getCallSuccessor());
} else {
return null;
}
}
default Graph.Block getConditionalSuccessor(Graph.Block block) {
if(block.getConditionalSuccessor() != null) {
return getBlock(block.getConditionalSuccessor());
} else {
return null;
}
}
/**
* Get all called procedures in the graph
*
* @return All called procedures
*/
default Set<ProcedureRef> getAllCalledProcedures() {
Set<ProcedureRef> calledProcedures = new LinkedHashSet<>();
for(Graph.Block block : getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCalling) {
StatementCalling call = (StatementCalling) statement;
ProcedureRef procedureRef = call.getProcedure();
calledProcedures.add(procedureRef);
}
}
}
return calledProcedures;
}
default String toString(Program program) {
StringBuffer out = new StringBuffer();
for(Graph.Block block : getAllBlocks()) {
out.append(block.toString(program, this));
}
return out.toString();
}
interface Block {
LabelRef getLabel();
ScopeRef getScope();
List<Statement> getStatements();
boolean hasPhiBlock();
StatementPhiBlock getPhiBlock();
LabelRef getDefaultSuccessor();
LabelRef getConditionalSuccessor();
LabelRef getCallSuccessor();
/**
* Get all successors of the block
*
* @return All successors
*/
default Collection<LabelRef> getSuccessors() {
List<LabelRef> successors = new ArrayList<>();
if(getDefaultSuccessor() != null) {
successors.add(getDefaultSuccessor());
}
if(getConditionalSuccessor() != null) {
successors.add(getConditionalSuccessor());
}
if(getCallSuccessor() != null) {
successors.add(getCallSuccessor());
}
return successors;
}
String toString(Program program, Graph graph);
}
}

View File

@ -45,7 +45,7 @@ public class LiveRangeVariablesEffectiveCallPaths implements LiveRangeVariablesE
this.referenceInfo = referenceInfo;
this.blockSuccessorClosure = blockSuccessorClosure;
this.statementLiveVariables = new LinkedHashMap<>();
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(Graph.Block block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
statementLiveVariables.put(statement.getIndex(), liveRangeVariables.getAlive(statement.getIndex()));
}
@ -102,7 +102,7 @@ public class LiveRangeVariablesEffectiveCallPaths implements LiveRangeVariablesE
Collection<VariableRef> aliveAtStmt = statementLiveVariables.get(statement.getIndex());
CallPaths callPaths;
Collection<VariableRef> referencedInProcedure;
ControlFlowBlock block = program.getStatementInfos().getBlock(statement);
Graph.Block block = program.getStatementInfos().getBlock(statement);
ScopeRef scopeRef = block.getScope();
Scope scope = program.getScope().getScope(scopeRef);
if(scope instanceof Procedure) {

View File

@ -19,23 +19,23 @@ public class PhiTransitions {
private Program program;
/** The destination block for the phi transitions */
private ControlFlowBlock toBlock;
private Graph.Block toBlock;
/** The phi-block of the to-block. */
private StatementPhiBlock phiBlock;
/** Maps from-block to the transition from the from-block to the to-block. */
private Map<ControlFlowBlock, PhiTransition> transitions;
private Map<Graph.Block, PhiTransition> transitions;
public PhiTransitions(Program program, ControlFlowBlock toBlock) {
public PhiTransitions(Program program, Graph.Block toBlock) {
this.program = program;
this.toBlock = toBlock;
this.transitions = new LinkedHashMap<>();
if(toBlock.hasPhiBlock()) {
this.phiBlock = toBlock.getPhiBlock();
List<ControlFlowBlock> predecessors = new ArrayList<>(program.getGraph().getPredecessors(toBlock));
List<Graph.Block> predecessors = new ArrayList<>(program.getGraph().getPredecessors(toBlock));
predecessors.sort(Comparator.comparing(o -> o.getLabel().getFullName()));
for(ControlFlowBlock predecessor : predecessors) {
for(Graph.Block predecessor : predecessors) {
PhiTransition transition = findTransition(predecessor);
transitions.put(predecessor, transition);
}
@ -49,7 +49,7 @@ public class PhiTransitions {
* @param fromBlock The block where the transition starts
* @return The transition into the passed block
*/
private PhiTransition findTransition(ControlFlowBlock fromBlock) {
private PhiTransition findTransition(Graph.Block fromBlock) {
PhiTransition transition = new PhiTransition(fromBlock, toBlock, phiBlock, program);
boolean isCallTransition = toBlock.getLabel().equals(fromBlock.getCallSuccessor());
if(!isCallTransition) {
@ -64,7 +64,7 @@ public class PhiTransitions {
return transition;
}
public Collection<ControlFlowBlock> getFromBlocks() {
public Collection<Graph.Block> getFromBlocks() {
return transitions.keySet();
}
@ -74,7 +74,7 @@ public class PhiTransitions {
* @param fromBlock The from-block
* @return The transition from the from-block into the to-block
*/
public PhiTransition getTransition(ControlFlowBlock fromBlock) {
public PhiTransition getTransition(Graph.Block fromBlock) {
return transitions.get(fromBlock);
}
@ -104,20 +104,20 @@ public class PhiTransitions {
private Program program;
/** The block we are entering into. */
private ControlFlowBlock toBlock;
private Graph.Block toBlock;
/** The phi statement of the to-block. */
private StatementPhiBlock phiBlock;
/** The block we are entering from. */
private List<ControlFlowBlock> fromBlocks;
private List<Graph.Block> fromBlocks;
/** The assignments when transitioning between the two blocks. */
private List<PhiTransition.PhiAssignment> assignments;
private int nextIdx;
PhiTransition(ControlFlowBlock fromBlock, ControlFlowBlock toBlock, StatementPhiBlock phiBlock, Program program) {
PhiTransition(Graph.Block fromBlock, Graph.Block toBlock, StatementPhiBlock phiBlock, Program program) {
this.program = program;
this.toBlock = toBlock;
this.phiBlock = phiBlock;
@ -127,7 +127,7 @@ public class PhiTransitions {
initAssignments(fromBlock);
}
private void initAssignments(ControlFlowBlock fromBlock) {
private void initAssignments(Graph.Block fromBlock) {
this.assignments = new ArrayList<>();
if(phiBlock != null) {
List<StatementPhiBlock.PhiVariable> phiVariables = new ArrayList<>(phiBlock.getPhiVariables());
@ -153,7 +153,7 @@ public class PhiTransitions {
StringBuilder id = new StringBuilder();
id.append("phi:");
boolean first = true;
for(ControlFlowBlock fromBlock : fromBlocks) {
for(Graph.Block fromBlock : fromBlocks) {
if(!first) {
id.append("/");
}
@ -168,7 +168,7 @@ public class PhiTransitions {
return assignments;
}
void addFromBlock(ControlFlowBlock fromBlock) {
void addFromBlock(Graph.Block fromBlock) {
fromBlocks.add(fromBlock);
}
@ -208,7 +208,7 @@ public class PhiTransitions {
return true;
}
public List<ControlFlowBlock> getFromBlocks() {
public List<Graph.Block> getFromBlocks() {
return fromBlocks;
}

View File

@ -6,13 +6,16 @@ import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateMasterSynthesizer;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.ProcedureRef;
import dk.camelot64.kickc.model.values.ScopeRef;
import dk.camelot64.kickc.passes.calcs.*;
import dk.camelot64.kickc.passes.utils.ProcedureUtils;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
/** A KickC Intermediate Compiler Language (ICL) Program */
public class Program {
@ -142,6 +145,27 @@ public class Program {
this.registerUpliftProgram = null;
}
/**
* Get a read-only control flow graph for the entire program.
* @return The control flow graph
*/
public Graph getGraph() {
return new Graph() {
@Override
public Block getBlock(LabelRef symbol) {
return getProcedureCompilations().stream().map(ProcedureCompilation::getGraph).map(graph -> graph.getBlock(symbol)).filter(Objects::nonNull).findFirst().orElse(null);
}
@Override
public List<Block> getAllBlocks() {
return getProcedureCompilations().stream().map(ProcedureCompilation::getGraph).map(ControlFlowGraph::getAllBlocks).flatMap(Collection::stream).collect(Collectors.toList());
}
};
}
private Collection<ProcedureCompilation> getProcedureCompilations() {
return procedureCompilations.values();
}
/**
* Pretty-print the entire control flow graph of all procedures.
@ -149,8 +173,7 @@ public class Program {
*/
public String prettyControlFlowGraph() {
StringBuilder graphPretty = new StringBuilder();
for(ProcedureRef procedureRef : procedureCompilations.keySet()) {
final ProcedureCompilation procedureCompilation = procedureCompilations.get(procedureRef);
for(ProcedureCompilation procedureCompilation : getProcedureCompilations()) {
graphPretty.append(procedureCompilation.getGraph().toString(this));
}
return graphPretty.toString();
@ -382,7 +405,7 @@ public class Program {
* Clear index numbers for all statements in the control flow graph.
*/
public void clearStatementIndices() {
procedureCompilations.values().forEach(proc -> proc.getGraph().clearStatementIndices());
getProcedureCompilations().forEach(proc -> proc.getGraph().clearStatementIndices());
}
public SymbolInfos getSymbolInfos() {
@ -493,7 +516,7 @@ public class Program {
StringBuilder sizeInfo = new StringBuilder();
sizeInfo.append(getScope().getSizeInfo());
final List<ControlFlowBlock> allBlocks = procedureCompilations.values().stream().map(ProcedureCompilation::getGraph).map(ControlFlowGraph::getAllBlocks).flatMap(Collection::stream).toList();
final List<Graph.Block> allBlocks = getProcedureCompilations().stream().map(ProcedureCompilation::getGraph).map(ControlFlowGraph::getAllBlocks).flatMap(Collection::stream).toList();
sizeInfo.append("SIZE blocks ").append(allBlocks.size()).append("\n");
int numStmt = allBlocks.stream().mapToInt(block -> block.getStatements().size()).sum();
sizeInfo.append("SIZE statements ").append(numStmt).append("\n");
@ -511,4 +534,50 @@ public class Program {
return sizeInfo.toString();
}
/**
* Get the procedure, that the block is part of. Null if the block is not part of a procedure.
*
* @param block The control flow graph block
* @return the procedure, that the block is part of
*/
public Procedure getProcedure(Graph.Block block) {
final ScopeRef scopeRef = block.getScope();
final Scope scope = getScope().getScope(scopeRef);
if(scope instanceof Procedure) {
return (Procedure) scope;
} else {
return null;
}
}
/**
* Is the block the entry of a procedure, ie. the first block of the code of the procedure.
*
* @param block
* @return true if this is the entry of a procedure
*/
public boolean isProcedureEntry(Graph.Block block) {
Symbol symbol = getScope().getSymbol(block.getLabel());
return (symbol instanceof Procedure);
}
/**
* Get all blocks that are program entry points.
* This is the start-block and any blocks referenced by the address-off operator (&)
*
* @param graph@return All entry-point blocks
*/
public List<Graph.Block> getEntryPointBlocks() {
final Graph graph = getGraph();
List<Graph.Block> entryPointBlocks = new ArrayList<>();
for(Procedure procedure : getScope().getAllProcedures(true)) {
if(ProcedureUtils.isEntrypoint(procedure.getRef(), this) || Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention()) || Procedure.CallingConvention.VAR_CALL.equals(procedure.getCallingConvention())) {
// Address-of is used on the procedure
Label procedureLabel = procedure.getLabel();
Graph.Block procedureBlock = graph.getBlock(procedureLabel.getRef());
entryPointBlocks.add(procedureBlock);
}
}
return entryPointBlocks;
}
}

View File

@ -9,15 +9,15 @@ import java.util.Map;
public class StatementInfos {
/** The control flow graph. */
private ControlFlowGraph graph;
private Graph graph;
/** Maps statement index to block. */
private Map<Integer, ControlFlowBlock> stmtBlocks;
private Map<Integer, Graph.Block> stmtBlocks;
/** Maps statement index to statement. */
private Map<Integer, Statement> stmtIdx;
public StatementInfos(Program program, Map<Integer, ControlFlowBlock> stmtBlocks, Map<Integer, Statement> stmtIdx) {
public StatementInfos(Program program, Map<Integer, Graph.Block> stmtBlocks, Map<Integer, Statement> stmtIdx) {
this.graph = program.getGraph();
this.stmtBlocks = stmtBlocks;
this.stmtIdx = stmtIdx;
@ -49,7 +49,7 @@ public class StatementInfos {
* @param stmt The statement
* @return The containing block
*/
public ControlFlowBlock getBlock(Statement stmt) {
public Graph.Block getBlock(Statement stmt) {
return stmtBlocks.get(stmt.getIndex());
}
@ -59,7 +59,7 @@ public class StatementInfos {
* @param stmtIdx The statement index
* @return The containing block
*/
public ControlFlowBlock getBlock(Integer stmtIdx) {
public Graph.Block getBlock(Integer stmtIdx) {
return graph.getBlock(getBlockRef(stmtIdx));
}

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.model.iterator;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.statements.Statement;
import java.util.ListIterator;
@ -21,6 +22,6 @@ public interface ProgramExpressionHandler {
* @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
* @param currentBlock The current block that the value is a part of
*/
void execute(ProgramExpression programExpression, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
void execute(ProgramExpression programExpression, Statement currentStmt, ListIterator<Statement> stmtIt, Graph.Block currentBlock);
}

View File

@ -41,7 +41,7 @@ public class ProgramExpressionIterator {
ProgramValueIterator.execute(program.getScope(), programValueHandler);
// Iterate all blocks/statements
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement stmt = stmtIt.next();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.model.iterator;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.statements.Statement;
import java.util.ListIterator;
@ -19,6 +20,6 @@ public interface ProgramValueHandler {
* @param stmtIt The statement iterator - just past the current statement. Can be used for modifying the control flow block.
* @param currentBlock The current block that the value is a part of
*/
void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock);
void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, Graph.Block currentBlock);
}

View File

@ -1,7 +1,7 @@
package dk.camelot64.kickc.model.iterator;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.ControlFlowGraph;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Label;
@ -80,8 +80,8 @@ public class ProgramValueIterator {
* @param graph The program control flow graph
* @param handler The handler to execute
*/
public static void execute(ControlFlowGraph graph, ProgramValueHandler handler) {
for(ControlFlowBlock block : graph.getAllBlocks()) {
public static void execute(Graph graph, ProgramValueHandler handler) {
for(Graph.Block block : graph.getAllBlocks()) {
execute(block, handler);
}
}
@ -92,16 +92,17 @@ public class ProgramValueIterator {
* @param block The control flow graph block
* @param handler The handler to execute
*/
public static void execute(ControlFlowBlock block, ProgramValueHandler handler) {
public static void execute(Graph.Block block, ProgramValueHandler handler) {
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
while(statementsIt.hasNext()) {
Statement statement = statementsIt.next();
execute(statement, handler, statementsIt, block);
}
execute(new ProgramValue.BlockLabel(block), handler, null, null, block);
execute(new ProgramValue.BlockDefaultSuccessor(block), handler, null, null, block);
execute(new ProgramValue.BlockConditionalSuccessor(block), handler, null, null, block);
execute(new ProgramValue.BlockCallSuccessor(block), handler, null, null, block);
ControlFlowBlock mutableBlock = (ControlFlowBlock) block;
execute(new ProgramValue.BlockLabel(mutableBlock), handler, null, null, block);
execute(new ProgramValue.BlockDefaultSuccessor(mutableBlock), handler, null, null, block);
execute(new ProgramValue.BlockConditionalSuccessor(mutableBlock), handler, null, null, block);
execute(new ProgramValue.BlockCallSuccessor(mutableBlock), handler, null, null, block);
}
/**
@ -110,14 +111,13 @@ public class ProgramValueIterator {
* @param statement The statement
* @param handler The handler to execute
*/
public static void execute(Statement statement, ProgramValueHandler handler, ListIterator<Statement> statementsIt, ControlFlowBlock block) {
public static void execute(Statement statement, ProgramValueHandler handler, ListIterator<Statement> statementsIt, Graph.Block block) {
if(statement instanceof StatementAssignment) {
// The sequence RValue1, RValue2, LValue is important - as it is essential for {@link dk.camelot64.kickc.passes.Pass1GenerateSingleStaticAssignmentForm} to create the correct SSA
execute(new ProgramValue.RValue1((StatementAssignment) statement), handler, statement, statementsIt, block);
execute(new ProgramValue.RValue2((StatementAssignment) statement), handler, statement, statementsIt, block);
execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block);
} else if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
} else if(statement instanceof StatementCall call) {
if(call.getParameters() != null) {
int size = call.getParameters().size();
for(int i = 0; i < size; i++) {
@ -125,8 +125,7 @@ public class ProgramValueIterator {
}
}
execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block);
} else if(statement instanceof StatementCallPrepare) {
StatementCallPrepare call = (StatementCallPrepare) statement;
} else if(statement instanceof StatementCallPrepare call) {
if(call.getParameters() != null) {
int size = call.getParameters().size();
for(int i = 0; i < size; i++) {
@ -137,8 +136,7 @@ public class ProgramValueIterator {
execute(new ProgramValue.CallExecuteProcedure((StatementCallExecute) statement), handler, statement, statementsIt, block);
} else if(statement instanceof StatementCallFinalize) {
execute(new ProgramValue.ProgramValueLValue((StatementLValue) statement), handler, statement, statementsIt, block);
} else if(statement instanceof StatementCallPointer) {
StatementCallPointer call = (StatementCallPointer) statement;
} else if(statement instanceof StatementCallPointer call) {
execute(new ProgramValue.CallPointerProcedure((StatementCallPointer) statement), handler, statement, statementsIt, block);
if(call.getParameters() != null) {
int size = call.getParameters().size();
@ -162,8 +160,7 @@ public class ProgramValueIterator {
}
execute(new ProgramValue.PhiVariable(phiVariable), handler, statement, statementsIt, block);
}
} else if(statement instanceof StatementKickAsm) {
StatementKickAsm statementKickAsm = (StatementKickAsm) statement;
} else if(statement instanceof StatementKickAsm statementKickAsm) {
RValue bytes = statementKickAsm.getBytes();
if(bytes != null) {
execute(new ProgramValue.ProgramValueKickAsmBytes(statementKickAsm), handler, statement, statementsIt, block);
@ -176,14 +173,12 @@ public class ProgramValueIterator {
for(int i = 0; i < uses.size(); i++) {
execute(new ProgramValue.KickAsmUses(statementKickAsm, i), handler, statement, statementsIt, block);
}
} else if(statement instanceof StatementAsm) {
StatementAsm statementAsm = (StatementAsm) statement;
} else if(statement instanceof StatementAsm statementAsm) {
Map<String, SymbolRef> referenced = statementAsm.getReferenced();
for(String label : referenced.keySet()) {
execute(new ProgramValue.ProgramValueAsmReferenced(statementAsm, label), handler, statement, statementsIt, block);
}
} else if(statement instanceof StatementExprSideEffect) {
StatementExprSideEffect statementExprSideEffect = (StatementExprSideEffect) statement;
} else if(statement instanceof StatementExprSideEffect statementExprSideEffect) {
execute(new ProgramValue.ExprSideEffect(statementExprSideEffect), handler, statement, statementsIt, block);
}
}
@ -194,7 +189,7 @@ public class ProgramValueIterator {
* @param programValue The programValue value
* @param handler The value handler
*/
public static void execute(ProgramValue programValue, ProgramValueHandler handler, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
public static void execute(ProgramValue programValue, ProgramValueHandler handler, Statement currentStmt, ListIterator<Statement> stmtIt, Graph.Block currentBlock) {
handler.execute(programValue, currentStmt, stmtIt, currentBlock);
for(ProgramValue subValue : getSubValues(programValue.get())) {
execute(subValue, handler, currentStmt, stmtIt, currentBlock);
@ -221,20 +216,17 @@ public class ProgramValueIterator {
for(int i = 0; i < size; i++) {
subValues.add(new ProgramValue.ProgramValueStructUnwoundPlaceholderMember((StructUnwoundPlaceholder) value, i));
}
} else if(value instanceof ValueList) {
ValueList valueList = (ValueList) value;
} else if(value instanceof ValueList valueList) {
int size = valueList.getList().size();
for(int i = 0; i < size; i++) {
subValues.add(new ProgramValue.ProgramValueListElement(valueList, i));
}
} else if(value instanceof ConstantArrayList) {
ConstantArrayList constantArrayList = (ConstantArrayList) value;
} else if(value instanceof ConstantArrayList constantArrayList) {
int size = constantArrayList.getElements().size();
for(int i = 0; i < size; i++) {
subValues.add(new ProgramValue.ProgramValueConstantArrayElement(constantArrayList, i));
}
} else if(value instanceof ConstantStructValue) {
ConstantStructValue constantStructValue = (ConstantStructValue) value;
} else if(value instanceof ConstantStructValue constantStructValue) {
for(SymbolVariableRef memberRef : constantStructValue.getMembers()) {
subValues.add(new ProgramValue.ProgramValueConstantStructMember(constantStructValue, memberRef));
}
@ -254,8 +246,7 @@ public class ProgramValueIterator {
subValues.add(new ProgramValue.ProgramValueConstantUnaryValue((ConstantUnary) value));
} else if(value instanceof ConstantArrayFilled) {
subValues.add(new ProgramValue.ProgramValueConstantArrayFilledSize((ConstantArrayFilled) value));
} else if(value instanceof ConstantArrayKickAsm) {
ConstantArrayKickAsm constantArrayKickAsm = (ConstantArrayKickAsm) value;
} else if(value instanceof ConstantArrayKickAsm constantArrayKickAsm) {
List<SymbolRef> uses = constantArrayKickAsm.getUses();
for(int i = 0; i < uses.size(); i++) {
subValues.add(new ProgramValue.ProgramValueConstantArrayKickAsmUses(constantArrayKickAsm, i));

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCalling;
@ -18,7 +19,7 @@ public class Pass1AssertInterrupts extends Pass1Base {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCalling) {
ProcedureRef procedureRef = ((StatementCalling) statement).getProcedure();

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementLValue;
@ -23,7 +24,7 @@ public class Pass1AssertNoLValueIntermediate extends Pass1Base {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementLValue;
@ -19,7 +20,7 @@ public class Pass1AssertNoModifyVars extends Pass1Base {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue statementLValue = (StatementLValue) statement;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCall;
@ -27,7 +28,7 @@ public class Pass1AssertProcedureCallParameters extends Pass1Base {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.statements.*;
@ -35,7 +32,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
getProgram().clearControlFlowBlockSuccessorClosure();
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
ControlFlowBlock startBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.START_PROC_NAME));
Graph.Block startBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.START_PROC_NAME));
final LinkedHashSet<SymbolVariableRef> defined = new LinkedHashSet<>();
// Add all variables with an init-value
for(Variable var : getProgramScope().getAllVars(true)) {
@ -61,7 +58,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
* @param defined Variables already assigned a value at the point of the first execution of the block
* @param visited Blocks already visited
*/
public void assertUsedVars(ControlFlowBlock block, LabelRef predecessor, VariableReferenceInfos referenceInfos, Collection<SymbolVariableRef> defined, Collection<LabelRef> visited) {
public void assertUsedVars(Graph.Block block, LabelRef predecessor, VariableReferenceInfos referenceInfos, Collection<SymbolVariableRef> defined, Collection<LabelRef> visited) {
// If the block has a phi statement it is always examined (to not skip any of the predecessor checks)
assertUsedVarsPhi(block, predecessor, referenceInfos, defined);
// If we have already visited the block - skip it
@ -91,7 +88,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
for(String paramName : procedure.getParameterNames()) {
defined.add(procedure.getLocalVariable(paramName).getRef());
}
ControlFlowBlock procedureStart = getProgram().getGraph().getBlock(call.getProcedure().getLabelRef());
Graph.Block procedureStart = getProgram().getGraph().getBlock(call.getProcedure().getLabelRef());
assertUsedVars(procedureStart, block.getLabel(), referenceInfos, defined, visited);
} else if(statement instanceof StatementCallPrepare) {
StatementCallPrepare call = (StatementCallPrepare) statement;
@ -101,15 +98,15 @@ public class Pass1AssertUsedVars extends Pass1Base {
}
} else if(statement instanceof StatementCallExecute) {
StatementCallExecute call = (StatementCallExecute) statement;
ControlFlowBlock procedureStart = getProgram().getGraph().getBlock(call.getProcedure().getLabelRef());
Graph.Block procedureStart = getProgram().getGraph().getBlock(call.getProcedure().getLabelRef());
assertUsedVars(procedureStart, block.getLabel(), referenceInfos, defined, visited);
} else if(statement instanceof StatementConditionalJump) {
StatementConditionalJump cond = (StatementConditionalJump) statement;
ControlFlowBlock jumpTo = getProgram().getGraph().getBlock(cond.getDestination());
Graph.Block jumpTo = getProgram().getGraph().getBlock(cond.getDestination());
assertUsedVars(jumpTo, block.getLabel(), referenceInfos, defined, visited);
}
}
ControlFlowBlock successor = getProgram().getGraph().getBlock(block.getDefaultSuccessor());
Graph.Block successor = getProgram().getGraph().getBlock(block.getDefaultSuccessor());
if(successor != null) {
assertUsedVars(successor, block.getLabel(), referenceInfos, defined, visited);
}
@ -124,7 +121,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
* @param defined Variables already assigned a value at the point of the first execution of the block
*/
private void assertUsedVarsPhi(ControlFlowBlock block, LabelRef predecessor, VariableReferenceInfos referenceInfos, Collection<SymbolVariableRef> defined) {
private void assertUsedVarsPhi(Graph.Block block, LabelRef predecessor, VariableReferenceInfos referenceInfos, Collection<SymbolVariableRef> defined) {
if(predecessor != null && block.hasPhiBlock()) {
StatementPhiBlock phiBlock = block.getPhiBlock();
ArrayList<SymbolVariableRef> used = new ArrayList<>();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.ProgramScope;
@ -36,6 +37,10 @@ public abstract class Pass1Base implements PassStep {
return program;
}
public Graph getGraph() {
return program.getGraph();
}
public ProgramScope getProgramScope() {
return program.getScope();
}

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.OperatorUnary;
import dk.camelot64.kickc.model.operators.Operators;
@ -43,7 +44,7 @@ public class Pass1ByteXIntrinsicRewrite extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -24,11 +24,11 @@ public class Pass1CallPhiParameters {
private Map<LabelRef, LabelRef> splitBlockMap = new LinkedHashMap<>();
public void execute() {
final List<ControlFlowBlock> todoBlocks = getGraph().getAllBlocks();
List<ControlFlowBlock> doneBlocks = new ArrayList<>();
final List<Graph.Block> todoBlocks = getGraph().getAllBlocks();
List<Graph.Block> doneBlocks = new ArrayList<>();
while(!todoBlocks.isEmpty()) {
final ControlFlowBlock block = todoBlocks.get(0);
final Graph.Block block = todoBlocks.get(0);
todoBlocks.remove(0);
doneBlocks.add(block);
@ -48,7 +48,7 @@ public class Pass1CallPhiParameters {
}
}
if(statement instanceof StatementReturn) {
Procedure procedure = block.getProcedure(program);
Procedure procedure = program.getProcedure(block);
// Handle PHI-calls
if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) {
// Add self-assignments for all variables modified in the procedure
@ -68,7 +68,7 @@ public class Pass1CallPhiParameters {
program.getGraph().setAllBlocks(doneBlocks);
// Fix phi predecessors for any blocks has a split block as predecessor
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(Graph.Block block : getGraph().getAllBlocks()) {
if(block.hasPhiBlock()) {
for(StatementPhiBlock.PhiVariable phiVariable : block.getPhiBlock().getPhiVariables()) {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
@ -86,11 +86,11 @@ public class Pass1CallPhiParameters {
return program.getScope();
}
private ControlFlowGraph getGraph() {
private Graph getGraph() {
return program.getGraph();
}
private ControlFlowBlock handlePhiCall(StatementCall call, Procedure procedure, ListIterator<Statement> stmtIt, ControlFlowBlock block) {
private ControlFlowBlock handlePhiCall(StatementCall call, Procedure procedure, ListIterator<Statement> stmtIt, Graph.Block block) {
List<Variable> parameterDefs = procedure.getParameters();
List<RValue> parameterValues = call.getParameters();
@ -141,7 +141,7 @@ public class Pass1CallPhiParameters {
call.setlValue(procReturnVarRef);
// Create a new block in the program, splitting the current block at the call/return (call finalize)
Scope currentBlockScope = block.getProcedure(program);
Scope currentBlockScope = program.getProcedure(block);
if(currentBlockScope==null) currentBlockScope = getScope().getScope(ScopeRef.ROOT);
LabelRef splitBlockNewLabelRef = currentBlockScope.addLabelIntermediate().getRef();
ControlFlowBlock newBlock = new ControlFlowBlock(splitBlockNewLabelRef, block.getScope());

View File

@ -23,7 +23,7 @@ public class Pass1CallPhiReturn {
}
public void execute() {
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
@ -38,11 +38,11 @@ public class Pass1CallPhiReturn {
}
}
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementReturn) {
StatementReturn statementReturn = (StatementReturn) statement;
Procedure procedure = block.getProcedure(program);
Procedure procedure = program.getProcedure(block);
if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) {
statementReturn.setValue(null);
}
@ -60,12 +60,12 @@ public class Pass1CallPhiReturn {
* @param callBlock The block containing the call
* @param stmtIt Iterator used for adding statements
*/
void handlePhiCall(StatementCall call, Procedure procedure, ControlFlowBlock callBlock, ListIterator<Statement> stmtIt) {
void handlePhiCall(StatementCall call, Procedure procedure, Graph.Block callBlock, ListIterator<Statement> stmtIt) {
// Generate return value assignment (call finalize)
if(!SymbolType.VOID.equals(procedure.getReturnType())) {
// Find return variable final version
Label returnBlockLabel = procedure.getLocalLabel(SymbolRef.PROCEXIT_BLOCK_NAME);
ControlFlowBlock returnBlock = program.getGraph().getBlock(returnBlockLabel.getRef());
Graph.Block returnBlock = program.getGraph().getBlock(returnBlockLabel.getRef());
RValue returnVarFinal = null;
for(Statement statement : returnBlock.getStatements()) {
if(statement instanceof StatementReturn) {
@ -91,7 +91,7 @@ public class Pass1CallPhiReturn {
// Patch versions of rValues in assignments for vars modified in the call (call finalize)
LabelRef successor = callBlock.getDefaultSuccessor();
ControlFlowBlock successorBlock = program.getGraph().getBlock(successor);
Graph.Block successorBlock = program.getGraph().getBlock(successor);
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
for(Statement statement : successorBlock.getStatements()) {
if(statement instanceof StatementPhiBlock) {
@ -115,7 +115,7 @@ public class Pass1CallPhiReturn {
private VariableRef findReturnVersion(Procedure procedure, VariableRef assignedVar) {
String unversionedName = assignedVar.getFullNameUnversioned();
LabelRef returnBlock = new LabelRef(procedure.getRef().getFullName() + "::@return");
ControlFlowBlock block = program.getGraph().getBlock(returnBlock);
Graph.Block block = program.getGraph().getBlock(returnBlock);
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CallingConventionStack;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.*;
@ -72,7 +69,7 @@ public class Pass1CallStack extends Pass2SsaOptimization {
}
// Convert procedure return xxx to stackidx(RETURN) = xxx;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
@ -95,7 +92,7 @@ public class Pass1CallStack extends Pass2SsaOptimization {
}
// Convert xxx = callfinalize to xxx = stackpull(type);
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
@ -125,7 +122,7 @@ public class Pass1CallStack extends Pass2SsaOptimization {
}
// Convert callprepare(xxx,yyy,) to stackpush(type)=xxx, ...;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.types.SymbolType;
@ -24,7 +21,7 @@ public class Pass1CallStackVarConvert extends Pass2SsaOptimization {
public boolean step() {
// Transform STACK_CALL/VAR_CALL calls to call-prepare, call-execute, call-finalize
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.symbols.Procedure;
@ -58,7 +59,7 @@ public class Pass1CallStackVarPrepare extends Pass2SsaOptimization {
for(Procedure procedure : getProgramScope().getAllProcedures(true)) {
if(procedure.isDeclaredIntrinsic()) continue;
if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
final ControlFlowBlock procedureBlock = getGraph().getBlock(procedure.getLabel().getRef());
final Graph.Block procedureBlock = getGraph().getBlock(procedure.getLabel().getRef());
final ArrayList<Variable> params = new ArrayList<>(procedure.getParameters());
Collections.reverse(params);
for(Variable param : params) {

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Procedure;
@ -30,7 +31,7 @@ public class Pass1CallVar extends Pass2SsaOptimization {
public boolean step() {
// Convert procedure return xxx to proc.return = xxx;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
@ -49,7 +50,7 @@ public class Pass1CallVar extends Pass2SsaOptimization {
}
// Convert xxx = callfinalize to xxx = proc.return
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
@ -71,7 +72,7 @@ public class Pass1CallVar extends Pass2SsaOptimization {
}
// Convert callprepare(xxx,yyy,) to proc.param = xxx, ...;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.symbols.Procedure;
@ -29,7 +26,7 @@ public class Pass1CallVoidReturns extends Pass2SsaOptimization {
getProgram().clearControlFlowBlockSuccessorClosure();
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCall) {
final ProcedureRef procedureRef = ((StatementCall) statement).getProcedure();

View File

@ -75,7 +75,7 @@ public class Pass1EarlyConstantIdentification extends Pass1Base {
}
}
// Remove the statements
for(ControlFlowBlock allBlock : getGraph().getAllBlocks()) {
for(var allBlock : getGraph().getAllBlocks()) {
allBlock.getStatements().removeIf(removeStmt::contains);
}
// Replace all variable refs with constant refs

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.ProcedureRef;
@ -49,8 +50,8 @@ public class Pass1EliminateUncalledProcedures extends Pass1Base {
program.getLog().append("Removing unused procedure " + procedureRef);
}
Procedure procedure = program.getScope().getProcedure(procedureRef);
List<ControlFlowBlock> procedureBlocks = program.getGraph().getScopeBlocks(procedureRef);
for(ControlFlowBlock procedureBlock : procedureBlocks) {
List<Graph.Block> procedureBlocks = program.getGraph().getScopeBlocks(procedureRef);
for(var procedureBlock : procedureBlocks) {
program.getGraph().remove(procedureBlock.getLabel());
}
procedure.getScope().remove(procedure);

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableBuilder;
import dk.camelot64.kickc.model.operators.Operator;
@ -36,7 +37,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base {
List<VariableRef> intermediates = new ArrayList<>();
ProgramScope programScope = getProgram().getScope();
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for(var block : getProgram().getGraph().getAllBlocks()) {
List<Statement> statements = block.getStatements();
ListIterator<Statement> statementsIt = statements.listIterator();
while(statementsIt.hasNext()) {

View File

@ -1,9 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.statements.Statement;
@ -51,7 +49,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
* Version all non-versioned non-intermediary being assigned a value.
*/
private void versionAllAssignments() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue statementLValue = (StatementLValue) statement;
@ -93,7 +91,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
* Version all uses of non-versioned non-intermediary variables
*/
private void versionAllUses() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
// Newest version of variables in the block.
Map<Variable, Variable> blockVersions = new LinkedHashMap<>();
// New phi functions introduced in the block to create versions of variables.
@ -192,7 +190,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
private boolean completePhiFunctions() {
Map<LabelRef, Map<Variable, Variable>> newPhis = new LinkedHashMap<>();
Map<LabelRef, Map<Variable, Variable>> symbolMap = buildSymbolMap();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementPhiBlock) {
@ -202,8 +200,8 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
VariableRef phiLValVarRef = phiVariable.getVariable();
Variable versioned = getProgramScope().getVariable(phiLValVarRef);
Variable unversioned = versioned.getPhiMaster();
List<ControlFlowBlock> predecessors = getPhiPredecessors(block, getProgram());
for(ControlFlowBlock predecessor : predecessors) {
List<Graph.Block> predecessors = getPhiPredecessors(block, getProgram());
for(var predecessor : predecessors) {
LabelRef predecessorLabel = predecessor.getLabel();
Map<Variable, Variable> predecessorMap = symbolMap.get(predecessorLabel);
Variable previousSymbol = null;
@ -232,7 +230,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
}
}
// Ads new phi functions to blocks
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
Map<Variable, Variable> blockNewPhis = newPhis.get(block.getLabel());
if(blockNewPhis != null) {
for(Variable symbol : blockNewPhis.keySet()) {
@ -251,16 +249,16 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
* @param block The block to examine
* @return All predecessor blocks
*/
public static List<ControlFlowBlock> getPhiPredecessors(ControlFlowBlock block, Program program) {
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(block);
public static List<Graph.Block> getPhiPredecessors(Graph.Block block, Program program) {
List<Graph.Block> predecessors = program.getGraph().getPredecessors(block);
Symbol symbol = program.getScope().getSymbol(block.getLabel());
if(symbol instanceof Procedure) {
Procedure procedure = (Procedure) symbol;
if(procedure.getInterruptType() != null || Pass2ConstantIdentification.isAddressOfUsed(procedure.getRef(), program)) {
// Find all root-level predecessors to the main block
ControlFlowBlock mainBlock = program.getGraph().getBlock(new LabelRef(SymbolRef.MAIN_PROC_NAME));
List<ControlFlowBlock> mainPredecessors = program.getGraph().getPredecessors(mainBlock);
for(ControlFlowBlock mainPredecessor : mainPredecessors) {
Graph.Block mainBlock = program.getGraph().getBlock(new LabelRef(SymbolRef.MAIN_PROC_NAME));
List<Graph.Block> mainPredecessors = program.getGraph().getPredecessors(mainBlock);
for(var mainPredecessor : mainPredecessors) {
if(mainPredecessor.getScope().equals(ScopeRef.ROOT)) {
predecessors.add(mainPredecessor);
throw new RuntimeException("W");
@ -277,7 +275,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
*/
private Map<LabelRef, Map<Variable, Variable>> buildSymbolMap() {
Map<LabelRef, Map<Variable, Variable>> symbolMap = new LinkedHashMap<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
StatementLValue assignment = (StatementLValue) statement;
@ -293,7 +291,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
return symbolMap;
}
private void addSymbolToMap(LValue lValue, ControlFlowBlock block, Map<LabelRef, Map<Variable, Variable>> symbolMap) {
private void addSymbolToMap(LValue lValue, Graph.Block block, Map<LabelRef, Map<Variable, Variable>> symbolMap) {
if(lValue instanceof VariableRef) {
Variable lValueVar = getProgramScope().getVariable((VariableRef) lValue);
if(lValueVar.isKindPhiVersion()) {

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.ProcedureModifiedVars;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
@ -47,8 +48,8 @@ public class Pass1ModifiedVarsAnalysis extends Pass1Base {
Set<VariableRef> modified = new LinkedHashSet<>();
ScopeRef procScope = procedure.getRef();
List<ControlFlowBlock> procBlocks = getProgram().getGraph().getScopeBlocks(procScope);
for(ControlFlowBlock block : procBlocks) {
List<Graph.Block> procBlocks = getProgram().getGraph().getScopeBlocks(procScope);
for(var block : procBlocks) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();

View File

@ -31,7 +31,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
@ -95,7 +95,7 @@ public class Pass1PointerSizeofFix extends Pass1Base {
* @param assignment The assignment statement
*/
private void fixPointerBinary(ControlFlowBlock block, ListIterator<Statement> stmtIt, StatementAssignment assignment) {
private void fixPointerBinary(Graph.Block block, ListIterator<Statement> stmtIt, StatementAssignment assignment) {
SymbolTypePointer pointerType = getPointerType(assignment.getrValue1());
if(pointerType != null) {
if(SymbolType.VOID.equals(pointerType.getElementType())) {

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.symbols.Procedure;
@ -71,7 +68,7 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
@ -26,10 +23,10 @@ public class Pass1ProcedureInline extends Pass1Base {
@Override
public boolean step() {
List<ControlFlowBlock> allBlocks = getGraph().getAllBlocks();
ListIterator<ControlFlowBlock> blocksIt = allBlocks.listIterator();
List<Graph.Block> allBlocks = getGraph().getAllBlocks();
ListIterator<Graph.Block> blocksIt = allBlocks.listIterator();
while(blocksIt.hasNext()) {
ControlFlowBlock block = blocksIt.next();
Graph.Block block = blocksIt.next();
List<Statement> blockStatements = block.getStatements();
ListIterator<Statement> statementsIt = blockStatements.listIterator();
while(statementsIt.hasNext()) {
@ -62,7 +59,7 @@ public class Pass1ProcedureInline extends Pass1Base {
* @param block The block containing the call
* @param blocksIt The block iterator pointing to the block containing the call
*/
private void inlineProcedureCall(StatementCall call, Procedure procedure, ListIterator<Statement> statementsIt, ControlFlowBlock block, ListIterator<ControlFlowBlock> blocksIt) {
private void inlineProcedureCall(StatementCall call, Procedure procedure, ListIterator<Statement> statementsIt, Graph.Block block, ListIterator<Graph.Block> blocksIt) {
Scope callScope = getProgramScope().getScope(block.getScope());
// Remove call
statementsIt.remove();
@ -75,8 +72,8 @@ public class Pass1ProcedureInline extends Pass1Base {
// Create a new block label for the rest of the calling block
Label restBlockLabel = callScope.addLabelIntermediate();
// Copy all procedure blocks
List<ControlFlowBlock> procedureBlocks = getGraph().getScopeBlocks(procedure.getRef());
for(ControlFlowBlock procedureBlock : procedureBlocks) {
List<Graph.Block> procedureBlocks = getGraph().getScopeBlocks(procedure.getRef());
for(var procedureBlock : procedureBlocks) {
LabelRef procBlockLabelRef = procedureBlock.getLabel();
Symbol procBlockLabel = getProgramScope().getSymbol(procBlockLabelRef);
Label inlinedBlockLabel;
@ -247,7 +244,7 @@ public class Pass1ProcedureInline extends Pass1Base {
}
@Override
public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, Graph.Block currentBlock) {
Value rValue = programValue.get();
if(rValue instanceof VariableRef) {
VariableRef procVarRef = (VariableRef) rValue;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCall;
@ -20,7 +21,7 @@ public class Pass1Procedures extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.statements.Statement;
@ -26,7 +27,7 @@ public class Pass1UnrollConditionVariableSsa extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
final StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Initializers;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
@ -28,7 +29,7 @@ public class Pass1UnwindStructPrepare extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -47,7 +47,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
*/
private boolean unwindStructReferences() {
boolean modified = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();
@ -91,7 +91,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
*
* @param call The call to unwind
*/
private boolean unwindCall(StatementCall call, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
private boolean unwindCall(StatementCall call, ListIterator<Statement> stmtIt, Graph.Block currentBlock) {
final Procedure procedure = getProgramScope().getProcedure(call.getProcedure());
// Unwind struct value return value
@ -166,7 +166,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
* @param currentBlock current block
* @return The unwound ValueList. null if the value is not unwindable.
*/
private RValue unwindValue(ValueSource lValueSource, Statement statement, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
private RValue unwindValue(ValueSource lValueSource, Statement statement, ListIterator<Statement> stmtIt, Graph.Block currentBlock) {
if(lValueSource == null) {
return null;
} else if(lValueSource.isSimple()) {
@ -189,7 +189,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
* @param statementReturn The return to unwind
*/
private boolean unwindReturn(StatementReturn statementReturn, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
private boolean unwindReturn(StatementReturn statementReturn, ListIterator<Statement> stmtIt, Graph.Block currentBlock) {
final RValue returnValue = statementReturn.getValue();
if(returnValue == null)
return false;
@ -247,7 +247,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
* @param stmtIt The statement iterator used for adding/removing statements
* @param currentBlock The current code block
*/
public static boolean unwindAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Program program) {
public static boolean unwindAssignment(StatementAssignment assignment, ListIterator<Statement> stmtIt, Graph.Block currentBlock, Program program) {
LValue lValue = assignment.getlValue();
SymbolType lValueType = SymbolTypeInference.inferType(program.getScope(), lValue);
@ -279,7 +279,7 @@ public class Pass1UnwindStructValues extends Pass1Base {
return false;
}
public static boolean copyValues(ValueSource lValueSource, ValueSource rValueSource, List<RValue> lValueUnwoundList, boolean initialAssignment, Statement currentStmt, ControlFlowBlock currentBlock, ListIterator<Statement> stmtIt, Program program) {
public static boolean copyValues(ValueSource lValueSource, ValueSource rValueSource, List<RValue> lValueUnwoundList, boolean initialAssignment, Statement currentStmt, Graph.Block currentBlock, ListIterator<Statement> stmtIt, Program program) {
if(lValueSource == null || rValueSource == null)
return false;
if(rValueSource instanceof ValueSourceParamValue && lValueSource.equals(((ValueSourceParamValue) rValueSource).getValueSource()))

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.*;
@ -51,7 +52,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
while(aliasSetListIterator.hasNext()) {
AliasSet aliasSet = aliasSetListIterator.next();
boolean removeSet = false;
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
if(block.hasPhiBlock()) {
StatementPhiBlock phi = block.getPhiBlock();
boolean lMatch = false;
@ -119,7 +120,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
*/
private static Aliases findAliasesCandidates(final Program program) {
Aliases aliases = new Aliases();
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
@ -286,7 +287,7 @@ public class Pass2AliasElimination extends Pass2SsaOptimization {
* @param aliases The aliases
*/
private void removeAliasAssignments(Aliases aliases) {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Iterator<Statement> iterator = block.getStatements().iterator(); iterator.hasNext(); ) {
Statement statement = iterator.next();
if(statement instanceof StatementAssignment) {

View File

@ -24,9 +24,9 @@ public class Pass2AssertBlocks extends Pass2SsaAssertion {
blockReferenceFinder.visitGraph(getGraph());
Set<LabelRef> seenBlocks = blockReferenceFinder.getSeenBlocks();
Collection<ControlFlowBlock> allBlocks = getGraph().getAllBlocks();
Collection<Graph.Block> allBlocks = getGraph().getAllBlocks();
for(LabelRef seenBlock : seenBlocks) {
ControlFlowBlock block = getGraph().getBlock(seenBlock);
Graph.Block block = getGraph().getBlock(seenBlock);
if(!allBlocks.contains(block)) {
throw new AssertionFailed("Compilation Process Error! A block in the program is not contained in the allBocks list (probably a block sequence problem). " + seenBlock);
}
@ -36,9 +36,9 @@ public class Pass2AssertBlocks extends Pass2SsaAssertion {
private static class BlockReferenceChecker extends ControlFlowGraphBaseVisitor<Void> {
Set<LabelRef> seenBlocks;
private ControlFlowGraph graph;
private Graph graph;
public BlockReferenceChecker(ControlFlowGraph graph) {
public BlockReferenceChecker(Graph graph) {
this.graph = graph;
this.seenBlocks = new HashSet<>();
}
@ -55,14 +55,14 @@ public class Pass2AssertBlocks extends Pass2SsaAssertion {
return;
}
seenBlocks.add(blockLabel);
ControlFlowBlock block = graph.getBlock(blockLabel);
Graph.Block block = graph.getBlock(blockLabel);
if(block == null) {
throw new AssertionFailed("Compilation Process Error! Block referenced, but not found in program. " + blockLabel);
}
}
@Override
public Void visitBlock(ControlFlowBlock block) {
public Void visitBlock(Graph.Block block) {
assertBlock(block.getDefaultSuccessor());
assertBlock(block.getCallSuccessor());
assertBlock(block.getConditionalSuccessor());

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementReturn;
@ -17,7 +18,7 @@ public class Pass2AssertNoReturnValues extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ScopeRef blockScopeRef = block.getScope();
Scope scope = getScope().getScope(blockScopeRef);
if(scope instanceof Procedure) {

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.values.LabelRef;
@ -18,12 +19,12 @@ public class Pass2AssertPhiPredecessors extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
if(block.hasPhiBlock()) {
StatementPhiBlock phiBlock = block.getPhiBlock();
List<ControlFlowBlock> phiPredecessors = Pass1GenerateSingleStaticAssignmentForm.getPhiPredecessors(block, getProgram());
List<Graph.Block> phiPredecessors = Pass1GenerateSingleStaticAssignmentForm.getPhiPredecessors(block, getProgram());
List<LabelRef> predecessors =
phiPredecessors.stream().map(ControlFlowBlock::getLabel).collect(Collectors.toList());
phiPredecessors.stream().map(Graph.Block::getLabel).toList();
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(!predecessors.contains(phiRValue.getPredecessor())) {

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementLValue;
@ -23,7 +24,7 @@ public class Pass2AssertSingleAssignment extends Pass2SsaAssertion {
Map<VariableRef, Statement> assignments = new LinkedHashMap<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.model.ControlFlowGraph;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.ProgramScope;
@ -26,4 +27,6 @@ public class Pass2Base {
return program;
}
public Graph getGraph() { return program.getGraph(); }
}

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ConstantNotLiteral;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operator;
import dk.camelot64.kickc.model.operators.Operators;
@ -34,7 +35,7 @@ public class Pass2ComparisonOptimization extends Pass2SsaOptimization {
*/
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
@ -56,7 +53,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
*/
private VariableRef findAndRewriteBooleanCondition() {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
StatementConditionalJump conditional = (StatementConditionalJump) statement;
@ -102,7 +99,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
* @param conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable.
*/
private void rewriteLogicAnd(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
private void rewriteLogicAnd(Graph.Block block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
// Found an if with a logical && condition - rewrite to if(c1) if(c2) { xx }
getLog().append("Rewriting && if()-condition to two if()s " + conditionAssignment.toString(getProgram(), false));
ScopeRef currentScopeRef = block.getScope();
@ -123,7 +120,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
conditional.setrValue2(conditionAssignment.getrValue1());
// Replace the phi labels inside the destination block with the new block
ControlFlowBlock destBlock = getGraph().getBlock(destLabel);
Graph.Block destBlock = getGraph().getBlock(destLabel);
LinkedHashMap<LabelRef, LabelRef> replacements = new LinkedHashMap<>();
replacements.put(block.getLabel(), newBlockLabel.getRef());
replaceLabels(destBlock.getPhiBlock(), replacements);
@ -137,7 +134,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
* @param conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable.
*/
private void rewriteLogicOr(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
private void rewriteLogicOr(Graph.Block block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
getLog().append("Rewriting || if()-condition to two if()s " + conditionAssignment.toString(getProgram(), false));
ScopeRef currentScopeRef = block.getScope();
Scope currentScope = getProgramScope().getScope(currentScopeRef);
@ -158,7 +155,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
conditional.setDeclaredUnroll(false);
// Update the default destination PHI block to reflect the last of the conditions
ControlFlowBlock defaultDestBlock = getGraph().getBlock(newBlock.getDefaultSuccessor());
Graph.Block defaultDestBlock = getGraph().getBlock(newBlock.getDefaultSuccessor());
if(defaultDestBlock.hasPhiBlock()) {
StatementPhiBlock defaultDestPhiBlock = defaultDestBlock.getPhiBlock();
for(StatementPhiBlock.PhiVariable phiVariable : defaultDestPhiBlock.getPhiVariables()) {
@ -171,7 +168,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
}
}
ControlFlowBlock conditionalDestBlock = getGraph().getBlock(conditional.getDestination());
Graph.Block conditionalDestBlock = getGraph().getBlock(conditional.getDestination());
if(conditionalDestBlock.hasPhiBlock()) {
StatementPhiBlock conditionalDestPhiBlock = conditionalDestBlock.getPhiBlock();
for(StatementPhiBlock.PhiVariable phiVariable : conditionalDestPhiBlock.getPhiVariables()) {
@ -194,7 +191,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
* @param conditional The if()-statement
* @param conditionAssignment The assignment defining the condition variable.
*/
private void rewriteLogicNot(ControlFlowBlock block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
private void rewriteLogicNot(Graph.Block block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
getLog().append("Rewriting ! if()-condition to reversed if() " + conditionAssignment.toString(getProgram(), false));
// Rewrite the conditional to use only the first part of the && condition expression
LabelRef defaultSuccessor = block.getDefaultSuccessor();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operator;
import dk.camelot64.kickc.model.operators.Operators;
@ -19,9 +20,9 @@ public class Pass2ConditionalJumpSequenceImprovement extends Pass2SsaOptimizatio
@Override
public boolean step() {
boolean modified = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
ControlFlowBlock conditionalSuccessor = getGraph().getConditionalSuccessor(block);
ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block);
for(var block : getGraph().getAllBlocks()) {
Graph.Block conditionalSuccessor = getGraph().getConditionalSuccessor(block);
Graph.Block defaultSuccessor = getGraph().getDefaultSuccessor(block);
if(conditionalSuccessor != null && defaultSuccessor != null) {
if(conditionalSuccessor.getDefaultSuccessor().equals(defaultSuccessor.getLabel())) {
if(conditionalSuccessor.equals(block)) continue;
@ -35,7 +36,7 @@ public class Pass2ConditionalJumpSequenceImprovement extends Pass2SsaOptimizatio
return modified;
}
private boolean negateCondition(ControlFlowBlock block) {
private boolean negateCondition(Graph.Block block) {
LabelRef defaultSuccessor = block.getDefaultSuccessor();
LabelRef conditionalSuccessor = block.getConditionalSuccessor();
for(Statement statement : block.getStatements()) {

View File

@ -65,7 +65,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
private List<SimpleCondition> getSimpleConditionTodos() {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
List<SimpleCondition> todos = new ArrayList<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
StatementConditionalJump conditionalJump = (StatementConditionalJump) statement;
@ -127,7 +127,7 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization {
// A referenced load/store-variable is modified in a statement between the assignment and the condition!
getLog().append("Condition not simple " + simpleCondition.conditionVar.toString(getProgram()) + " " + simpleCondition.conditionalJump.toString(getProgram(), false));
// Create an intermediate variable copy of the load/store-variable at the position of the condition-variable to preserve the value
final ControlFlowBlock conditionDefineBlock = statementInfos.getBlock(simpleCondition.conditionAssignment);
final Graph.Block conditionDefineBlock = statementInfos.getBlock(simpleCondition.conditionAssignment);
final ScopeRef conditionDefineScopeRef = conditionDefineBlock.getScope();
final Scope conditionDefineScope = getProgramScope().getScope(conditionDefineScopeRef);
SymbolType typeQualified = referencedLoadStoreVariable.getType().getQualified(false, referencedLoadStoreVariable.getType().isNomodify());

View File

@ -55,7 +55,7 @@ public class Pass2ConstantAdditionElimination extends Pass2SsaOptimization {
});
// Examine all assignments - performing constant consolidation for +/-
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCallExecute;
@ -24,7 +25,7 @@ public class Pass2ConstantCallPointerIdentification extends Pass2SsaOptimization
@Override
public boolean step() {
boolean optimized = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
while(statementsIt.hasNext()) {
Statement statement = statementsIt.next();
@ -63,7 +64,7 @@ public class Pass2ConstantCallPointerIdentification extends Pass2SsaOptimization
* @param constProcedureRef The constant procedure pointed to
* @param block The block containing the call
*/
private void replacePointerCall(StatementCallExecute callPointer, ProcedureRef constProcedureRef, ControlFlowBlock block) {
private void replacePointerCall(StatementCallExecute callPointer, ProcedureRef constProcedureRef, Graph.Block block) {
callPointer.setProcedure(constProcedureRef);
if(block.getCallSuccessor()!=null)
throw new CompileError("Internal error! Block has two calls!", callPointer);

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ConstantNotLiteral;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.OperatorBinary;
@ -134,7 +131,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
final Map<VariableRef, ConstantVariableValue> constants = new LinkedHashMap<>();
// Look for constants among versions, intermediates & declared constants
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
@ -304,7 +301,7 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
}
// Examine all statements
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ConstantNotLiteral;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operator;
import dk.camelot64.kickc.model.operators.OperatorBinary;
@ -34,7 +35,7 @@ public class Pass2ConstantIfs extends Pass2SsaOptimization {
public boolean step() {
boolean modified = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
@ -28,7 +29,7 @@ public class Pass2ConstantIntrinsics extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.OperatorBinary;
import dk.camelot64.kickc.model.operators.OperatorUnary;
@ -32,7 +33,7 @@ public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
@Override
public boolean step() {
boolean modified = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.DominatorsBlock;
import dk.camelot64.kickc.model.DominatorsGraph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueHandler;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
@ -17,6 +14,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.values.*;
import java.lang.InternalError;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
@ -39,7 +37,7 @@ public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization {
// All RValues in the program
Set<AssignmentWithRValue> rValues = new HashSet<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment thisAssignment = (StatementAssignment) statement;
@ -148,13 +146,13 @@ public class Pass2DuplicateRValueIdentification extends Pass2SsaOptimization {
* Represents an RValue of an assignment.
*/
private class AssignmentWithRValue {
private ControlFlowBlock block;
private Graph.Block block;
private StatementAssignment assignment;
private RValue rValue1;
private Operator operator;
private RValue rValue2;
public AssignmentWithRValue(StatementAssignment assignment, ControlFlowBlock block) {
public AssignmentWithRValue(StatementAssignment assignment, Graph.Block block) {
this.block = block;
this.assignment = assignment;
this.rValue1 = assignment.getrValue1();

View File

@ -3,6 +3,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Label;
@ -24,7 +25,7 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
public boolean step() {
Set<LabelRef> referencedBlocks = getReferencedBlocks();
Set<LabelRef> unusedBlocks = new LinkedHashSet<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
if(!referencedBlocks.contains(block.getLabel())) {
unusedBlocks.add(block.getLabel());
for(Statement stmt : block.getStatements()) {
@ -84,8 +85,8 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
public static void removeProcedure(ProcedureRef procedureRef, Set<LabelRef> removedBlocks, Program program) {
program.getLog().append("Removing unused procedure " + procedureRef);
Procedure unusedProcedure = program.getScope().getProcedure(procedureRef);
List<ControlFlowBlock> procedureBlocks = program.getGraph().getScopeBlocks(procedureRef);
for(ControlFlowBlock procedureBlock : procedureBlocks) {
List<Graph.Block> procedureBlocks = program.getGraph().getScopeBlocks(procedureRef);
for(var procedureBlock : procedureBlocks) {
LabelRef blockLabelRef = procedureBlock.getLabel();
program.getLog().append("Removing unused procedure block " + blockLabelRef);
program.getGraph().remove(blockLabelRef);
@ -102,7 +103,7 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
*/
private Set<LabelRef> getReferencedBlocks() {
Set<LabelRef> referencedBlocks = new LinkedHashSet<>();
List<ControlFlowBlock> entryPointBlocks = getGraph().getEntryPointBlocks(getProgram());
List<ControlFlowBlock> entryPointBlocks = getProgram().getEntryPointBlocks();
for(ControlFlowBlock entryPointBlock : entryPointBlocks) {
findReferencedBlocks(entryPointBlock, referencedBlocks);
}
@ -116,7 +117,7 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
* @param removeBlock The block to remove from PHI RValues
*/
private static void removePhiRValues(LabelRef removeBlock, Program program) {
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
removePhiRValues(removeBlock, block, program.getLog());
}
}
@ -127,7 +128,7 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
* @param removeBlock The block to remove from PHI RValues
* @param block The block to modify
*/
public static void removePhiRValues(LabelRef removeBlock, ControlFlowBlock block, CompileLog log) {
public static void removePhiRValues(LabelRef removeBlock, Graph.Block block, CompileLog log) {
if(block.hasPhiBlock()) {
for(StatementPhiBlock.PhiVariable phiVariable : block.getPhiBlock().getPhiVariables()) {
ListIterator<StatementPhiBlock.PhiRValue> phiRValueIt = phiVariable.getValues().listIterator();
@ -148,7 +149,7 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
* @param block The block to add (inc. all blocks that this block calls or jumps to)
* @param used The blocks already discovered (not examined again)
*/
private void findReferencedBlocks(ControlFlowBlock block, Set<LabelRef> used) {
private void findReferencedBlocks(Graph.Block block, Set<LabelRef> used) {
if(block == null) {
return;
}

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
@ -26,7 +27,7 @@ public class Pass2IdenticalPhiElimination extends Pass2SsaOptimization {
@Override
public boolean step() {
Map<VariableRef, RValue> phiIdentical = new LinkedHashMap<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementPhiBlock) {
StatementPhiBlock statementPhi = (StatementPhiBlock) statement;

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.OperatorCast;
import dk.camelot64.kickc.model.statements.Statement;
@ -18,7 +19,7 @@ public class Pass2InlineCast extends Pass2SsaOptimization {
@Override
public boolean step() {
boolean optimized = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -33,7 +33,7 @@ public class Pass2LoopHeadConstantIdentification extends Pass2SsaOptimization {
NaturalLoopSet loopSet = getProgram().getLoopSet();
for(NaturalLoop loop : loopSet.getLoops()) {
LabelRef loopHeadRef = loop.getHead();
ControlFlowBlock loopHeadBlock = getGraph().getBlock(loopHeadRef);
Graph.Block loopHeadBlock = getGraph().getBlock(loopHeadRef);
boolean modified = optimizeLoopHead(loopHeadBlock, loop, variableReferenceInfos);
if(modified) {
getProgram().clearVariableReferenceInfos();
@ -49,7 +49,7 @@ public class Pass2LoopHeadConstantIdentification extends Pass2SsaOptimization {
return false;
}
private boolean optimizeLoopHead(ControlFlowBlock loopHeadBlock, NaturalLoop loop, VariableReferenceInfos variableReferenceInfos) {
private boolean optimizeLoopHead(Graph.Block loopHeadBlock, NaturalLoop loop, VariableReferenceInfos variableReferenceInfos) {
if(loopHeadBlock.getConditionalSuccessor() != null && loopHeadBlock.hasPhiBlock()) {
// Find the variables used in the continue/end condition
StatementConditionalJump condition = null;

View File

@ -57,7 +57,7 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
* @param unroll The (original) blocks being unrolled
*/
private static void markOriginalUnrolled(BlockSet unroll, Program program) {
for(ControlFlowBlock block : unroll.getBlocks(program.getGraph())) {
for(var block : unroll.getBlocks(program.getGraph())) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
// - Remove the "unroll" directive on the condition in the old loop (as it is already unrolled).
@ -106,7 +106,7 @@ public class Pass2LoopUnroll extends Pass2SsaOptimization {
private static List<NaturalLoop> findUnrollLoops(Program program) {
NaturalLoopSet loops = program.getLoopSet();
List<NaturalLoop> unrollLoopCandidates = new ArrayList<>();
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
if(((StatementConditionalJump) statement).isDeclaredUnroll()) {

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
@ -19,7 +20,7 @@ public class Pass2LoopUnrollAssertComplete extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementConditionalJump) {
if(((StatementConditionalJump) statement).isWasUnrolled()) {

View File

@ -22,7 +22,7 @@ public class Pass2MultiplyToShiftRewriting extends Pass2SsaOptimization {
@Override
public boolean step() {
boolean optimized = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
Scope scope = getProgramScope().getScope(block.getScope());
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
@ -40,7 +41,7 @@ public class Pass2NopCastInlining extends Pass2SsaOptimization {
Mode mode = null;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement stmt = stmtIt.next();

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.model.ControlFlowGraph;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.ProgramScope;
@ -14,7 +15,7 @@ public abstract class Pass2SsaAssertion {
this.program = program;
}
public ControlFlowGraph getGraph() {
public Graph getGraph() {
return program.getGraph();
}

View File

@ -56,7 +56,7 @@ public abstract class Pass2SsaOptimization extends Pass1Base implements PassStep
*
* @param replacements Variables that have alias values.
*/
public void replaceLabels(ControlFlowBlock block, final Map<LabelRef, LabelRef> replacements) {
public void replaceLabels(Graph.Block block, final Map<LabelRef, LabelRef> replacements) {
ControlFlowGraphBaseVisitor<Void> visitor = getLabelReplaceVisitor(replacements);
visitor.visitBlock(block);
}
@ -110,8 +110,8 @@ public abstract class Pass2SsaOptimization extends Pass1Base implements PassStep
*
* @param variables The variables to eliminate
*/
public static void removeAssignments(ControlFlowGraph graph, Collection<? extends LValue> variables) {
for(ControlFlowBlock block : graph.getAllBlocks()) {
public static void removeAssignments(Graph graph, Collection<? extends LValue> variables) {
for(var block : graph.getAllBlocks()) {
for(Iterator<Statement> iterator = block.getStatements().iterator(); iterator.hasNext(); ) {
Statement statement = iterator.next();
if(statement instanceof StatementAssignment) {

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.operators.Operators;
@ -41,7 +42,7 @@ public class Pass2UnaryNotSimplification extends Pass2SsaOptimization {
private List<VariableRef> optimizeUnaryNots() {
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
final List<VariableRef> unused = new ArrayList<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -7,6 +7,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCalling;
@ -24,7 +25,7 @@ public class Pass3AddNopBeforeCallOns extends Pass2Base {
* Create index numbers for all statements in the control flow graph.
*/
public void generate() {
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for(var block : getProgram().getGraph().getAllBlocks()) {
List<Statement> statements = block.getStatements();
if(statements.size() == 0) {
statements.add(0, new StatementPhiBlock(Comment.NO_COMMENTS));

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAsm;
@ -33,7 +34,7 @@ public class Pass3AssertConstants extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementKickAsm) {
RValue bytes = ((StatementKickAsm) statement).getBytes();

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
@ -18,7 +19,7 @@ public class Pass3AssertNoMulDivMod extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(Graph.Block block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.InternalError;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
@ -22,7 +23,7 @@ public class Pass3AssertNoNumbers extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
checkValue(((StatementAssignment) statement).getlValue(), statement);

View File

@ -30,8 +30,8 @@ public class Pass3LoopDepthAnalysis extends Pass2Base {
Deque<ScopeRef> todo = new ArrayDeque<>();
Set<ScopeRef> done = new LinkedHashSet<>();
List<ControlFlowBlock> entryPointBlocks = getGraph().getEntryPointBlocks(getProgram());
for(ControlFlowBlock entryPointBlock : entryPointBlocks)
List<Graph.Block> entryPointBlocks = getProgram().getEntryPointBlocks();
for(var entryPointBlock : entryPointBlocks)
todo.push(entryPointBlock.getScope());
while(!todo.isEmpty()) {
@ -66,7 +66,7 @@ public class Pass3LoopDepthAnalysis extends Pass2Base {
for(CallGraph.CallBlock.Call call : calls) {
// First look for loops containing the call
int callStatementIdx = call.getCallStatementIdx();
ControlFlowBlock callingControlBlock = getProgram().getStatementInfos().getBlock(callStatementIdx);
Graph.Block callingControlBlock = getProgram().getStatementInfos().getBlock(callStatementIdx);
Collection<NaturalLoop> callingLoops = loopSet.getLoopsContainingBlock(callingControlBlock.getLabel());
for(NaturalLoop callingLoop : callingLoops) {
Integer depth = callingLoop.getDepth();
@ -95,7 +95,7 @@ public class Pass3LoopDepthAnalysis extends Pass2Base {
List<NaturalLoop> currentScopeLoops = new ArrayList<>();
for(NaturalLoop loop : loopSet.getLoops()) {
LabelRef loopHead = loop.getHead();
ControlFlowBlock loopHeadBlock = getGraph().getBlock(loopHead);
Graph.Block loopHeadBlock = getGraph().getBlock(loopHead);
ScopeRef scopeRef = PassNCalcCallGraph.getScopeRef(loopHeadBlock, getProgram());
if(scopeRef.equals(currentScope)) {
// Loop is inside current scope block!

View File

@ -31,12 +31,12 @@ public class Pass3PhiLifting {
}
public void perform() {
ControlFlowGraph graph = program.getGraph();
Graph graph = program.getGraph();
ProgramScope programScope = program.getScope();
List<ControlFlowBlock> blocks = graph.getAllBlocks();
ListIterator<ControlFlowBlock> blocksIt = blocks.listIterator();
List<Graph.Block> blocks = graph.getAllBlocks();
ListIterator<Graph.Block> blocksIt = blocks.listIterator();
while(blocksIt.hasNext()) {
ControlFlowBlock block = blocksIt.next();
Graph.Block block = blocksIt.next();
// Maps old predecessors to new blocks created
Map<LabelRef, LabelRef> newBlocks = new HashMap<>();
if(block.hasPhiBlock()) {
@ -45,7 +45,7 @@ public class Pass3PhiLifting {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(!(phiRValue.getrValue() instanceof ConstantValue)) {
LabelRef predecessorRef = phiRValue.getPredecessor();
ControlFlowBlock predecessorBlock = graph.getBlock(predecessorRef);
Graph.Block predecessorBlock = graph.getBlock(predecessorRef);
//VariableRef rValVarRef = (VariableRef) phiRValue.getrValue();
Variable newVar;
if(phiVariable.getVariable().isVersion()) {
@ -66,7 +66,7 @@ public class Pass3PhiLifting {
StatementAssignment newAssignment = new StatementAssignment((LValue) newVar.getRef(), phiRValue.getrValue(), false, phiBlock.getSource(), Comment.NO_COMMENTS);
if(lastPredecessorStatement instanceof StatementConditionalJump) {
// Use or Create a new block between the predecessor and this one - replace labels where appropriate
ControlFlowBlock newBlock;
Graph.Block newBlock;
LabelRef newBlockRef = newBlocks.get(predecessorRef);
if(newBlockRef == null) {
// Create new block

View File

@ -82,7 +82,7 @@ public class Pass4AssertNoCpuClobber extends Pass2Base {
if(statement instanceof StatementPhiBlock && asmChunk.getSubStatementId() != null && asmChunk.getSubStatementIdx() != null) {
String phiTransitionId = asmChunk.getSubStatementId();
int transitionAssignmentIdx = asmChunk.getSubStatementIdx();
ControlFlowBlock statementBlock = getProgram().getStatementInfos().getBlock(statementIdx);
Graph.Block statementBlock = getProgram().getStatementInfos().getBlock(statementIdx);
Map<LabelRef, PhiTransitions> programPhiTransitions = getProgram().getPhiTransitions();
PhiTransitions phiTransitions = programPhiTransitions.get(statementBlock.getLabel());
PhiTransitions.PhiTransition phiTransition = phiTransitions.getTransition(phiTransitionId);

View File

@ -72,7 +72,7 @@ public class Pass4CodeGeneration {
this.warnFragmentMissing = warnFragmentMissing;
}
ControlFlowGraph getGraph() {
Graph getGraph() {
return program.getGraph();
}
@ -108,20 +108,20 @@ public class Pass4CodeGeneration {
// Generate global ZP labels
asm.startChunk(currentScope, null, "Global Constants & labels");
addConstantsAndLabels(asm, currentScope);
for (ControlFlowBlock block : getGraph().getAllBlocks()) {
for (Graph.Block block : getGraph().getAllBlocks()) {
if (!block.getScope().equals(currentScope)) {
// The current block is in a different scope. End the old scope.
generateScopeEnding(asm, currentScope);
currentScope = block.getScope();
if (block.isProcedureEntry(program)) {
Procedure procedure = block.getProcedure(program);
if (program.isProcedureEntry(block)) {
Procedure procedure = program.getProcedure(block);
currentCodeSegmentName = procedure.getCodeSegment();
}
setCurrentSegment(currentCodeSegmentName, asm);
asm.startChunk(currentScope, null, block.getLabel().getFullName());
// Add any procedure comments
if (block.isProcedureEntry(program)) {
Procedure procedure = block.getProcedure(program);
if (program.isProcedureEntry(block)) {
Procedure procedure = program.getProcedure(block);
generateComments(asm, procedure.getComments());
// Generate parameter information
generateSignatureComments(asm, procedure);
@ -136,9 +136,9 @@ public class Pass4CodeGeneration {
// Generate entry points (if needed)
genBlockEntryPoints(asm, block);
if (block.isProcedureEntry(program)) {
if (program.isProcedureEntry(block)) {
// Generate interrupt entry if needed
Procedure procedure = block.getProcedure(program);
Procedure procedure = program.getProcedure(block);
if (procedure != null && procedure.getInterruptType() != null) {
generateInterruptEntry(asm, procedure);
}
@ -150,7 +150,7 @@ public class Pass4CodeGeneration {
// Generate statements
genStatements(asm, block);
// Generate exit
ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block);
Graph.Block defaultSuccessor = getGraph().getDefaultSuccessor(block);
if (defaultSuccessor != null) {
if (defaultSuccessor.hasPhiBlock()) {
PhiTransitions.PhiTransition transition = getTransitions(defaultSuccessor).getTransition(block);
@ -333,7 +333,7 @@ public class Pass4CodeGeneration {
found = true;
// Found the constant
LabelRef pred = phiRValue.getPredecessor();
ControlFlowBlock predBlock = program.getGraph().getBlock(pred);
Graph.Block predBlock = program.getGraph().getBlock(pred);
ScopeRef predScope = predBlock.getScope();
if (!predScope.equals(scopeRef)) {
// Scopes in PHI RValue differs from const scope - generate label
@ -797,7 +797,7 @@ public class Pass4CodeGeneration {
}
}
private void genStatements(AsmProgram asm, ControlFlowBlock block) {
private void genStatements(AsmProgram asm, Graph.Block block) {
Iterator<Statement> statementsIt = block.getStatements().iterator();
while (statementsIt.hasNext()) {
Statement statement = statementsIt.next();
@ -830,7 +830,7 @@ public class Pass4CodeGeneration {
* @param block The block containing the statement
* @param statement The statement to generate ASM code for
*/
void generateStatementAsm(AsmProgram asm, ControlFlowBlock block, Statement statement, boolean genCallPhiEntry) {
void generateStatementAsm(AsmProgram asm, Graph.Block block, Statement statement, boolean genCallPhiEntry) {
asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo));
generateComments(asm, statement.getComments());
if (!(statement instanceof StatementPhiBlock)) {
@ -863,7 +863,7 @@ public class Pass4CodeGeneration {
} else if (Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) {
// Generate PHI transition
if (genCallPhiEntry) {
ControlFlowBlock callSuccessor = getGraph().getCallSuccessor(block);
Graph.Block callSuccessor = getGraph().getCallSuccessor(block);
if (callSuccessor != null && callSuccessor.hasPhiBlock()) {
PhiTransitions.PhiTransition transition = getTransitions(callSuccessor).getTransition(block);
if (transitionIsGenerated(transition)) {
@ -1000,9 +1000,9 @@ public class Pass4CodeGeneration {
* @param asm The ASM program to generate into
* @param toBlock The block to generate remaining entry points for.
*/
private void genBlockEntryPoints(AsmProgram asm, ControlFlowBlock toBlock) {
private void genBlockEntryPoints(AsmProgram asm, Graph.Block toBlock) {
PhiTransitions transitions = getTransitions(toBlock);
for (ControlFlowBlock fromBlock : transitions.getFromBlocks()) {
for (var fromBlock : transitions.getFromBlocks()) {
PhiTransitions.PhiTransition transition = transitions.getTransition(fromBlock);
if (!transitionIsGenerated(transition) && toBlock.getLabel().equals(fromBlock.getConditionalSuccessor())) {
genBlockPhiTransition(asm, fromBlock, toBlock, toBlock.getScope());
@ -1023,19 +1023,19 @@ public class Pass4CodeGeneration {
* If the transition code is inserted in the to-block, this is the scope of the to-block.
* If the transition code is inserted in the from-block this is the scope of the from-block.
*/
private void genBlockPhiTransition(AsmProgram asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock, ScopeRef scope) {
private void genBlockPhiTransition(AsmProgram asm, Graph.Block fromBlock, Graph.Block toBlock, ScopeRef scope) {
PhiTransitions transitions = getTransitions(toBlock);
PhiTransitions.PhiTransition transition = transitions.getTransition(fromBlock);
if (!transitionIsGenerated(transition)) {
Statement toFirstStatement = toBlock.getStatements().get(0);
String chunkSrc = "[" + toFirstStatement.getIndex() + "] phi from ";
for (ControlFlowBlock fBlock : transition.getFromBlocks()) {
for (var fBlock : transition.getFromBlocks()) {
chunkSrc += fBlock.getLabel().getFullName() + " ";
}
chunkSrc += "to " + toBlock.getLabel().getFullName();
asm.startChunk(scope, toFirstStatement.getIndex(), chunkSrc);
asm.getCurrentChunk().setSubStatementId(transition.getTransitionId());
for (ControlFlowBlock fBlock : transition.getFromBlocks()) {
for (var fBlock : transition.getFromBlocks()) {
asm.addLabel(AsmFormat.asmFix(toBlock.getLabel().getLocalName() + "_from_" + fBlock.getLabel().getLocalName()));
}
List<PhiTransitions.PhiTransition.PhiAssignment> assignments = transition.getAssignments();
@ -1065,7 +1065,7 @@ public class Pass4CodeGeneration {
* @param toBlock The block
* @return The transitions into the block
*/
private PhiTransitions getTransitions(ControlFlowBlock toBlock) {
private PhiTransitions getTransitions(Graph.Block toBlock) {
return program.getPhiTransitions().get(toBlock.getLabel());
}

View File

@ -55,7 +55,7 @@ public class Pass4MemoryCoalesceAssignment extends Pass2Base {
public CoalesceVarScores(Program program) {
this.scores = new LinkedHashMap<>();
VariableReferenceInfos variableReferenceInfos = program.getVariableReferenceInfos();
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
Collection<VariableRef> definedVars = variableReferenceInfos.getDefinedVars(statement);
Collection<VariableRef> usedVars = variableReferenceInfos.getUsedVars(statement);

View File

@ -154,7 +154,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
Integer statementIdx = asmChunk.getStatementIdx();
int maxLoopDepth = 1;
if(statementIdx != null) {
ControlFlowBlock block = program.getStatementInfos().getBlock(statementIdx);
Graph.Block block = program.getStatementInfos().getBlock(statementIdx);
maxLoopDepth = loopSet.getMaxLoopDepth(block.getLabel());
}
score += asmChunkCycles * Math.pow(10, maxLoopDepth);
@ -170,7 +170,7 @@ public class Pass4RegisterUpliftCombinations extends Pass2Base {
* @return true if the register allocation contains an overlapping allocation. false otherwise.
*/
public static boolean isAllocationOverlapping(Program program) {
for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
for(var block : program.getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(isStatementAllocationOverlapping(program, statement)) {
return true;

View File

@ -70,7 +70,7 @@ public class Pass4RegisterUpliftPotentialRegisterAnalysis extends Pass2Base {
RegisterPotentials registerPotentials = getProgram().getRegisterPotentials();
VariableReferenceInfos referenceInfo = getProgram().getVariableReferenceInfos();
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
// Find all variables referenced/assigned in the statement
@ -144,7 +144,7 @@ public class Pass4RegisterUpliftPotentialRegisterAnalysis extends Pass2Base {
* @param combinations The regsiter combinations to test
* @return A set with registers that are clobbered by all different register assignments in the combination
*/
private Set<Registers.Register> findAlwaysClobberedRegisters(ControlFlowBlock block, Statement statement, RegisterCombinationIterator combinations) {
private Set<Registers.Register> findAlwaysClobberedRegisters(Graph.Block block, Statement statement, RegisterCombinationIterator combinations) {
// Initially assume all registers are always clobbered
Set<Registers.Register> alwaysClobbered = new LinkedHashSet<>();

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableBuilder;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
import dk.camelot64.kickc.model.operators.Operators;
@ -33,7 +30,7 @@ public class PassNAddBooleanCasts extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock currentBlock : getGraph().getAllBlocks()) {
for(var currentBlock : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = currentBlock.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement currentStmt = stmtIt.next();
@ -74,7 +71,7 @@ public class PassNAddBooleanCasts extends Pass2SsaOptimization {
return false;
}
private Variable addBooleanCast(RValue rValue, SymbolType rValueType, Statement currentStmt, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock) {
private Variable addBooleanCast(RValue rValue, SymbolType rValueType, Statement currentStmt, ListIterator<Statement> stmtIt, Graph.Block currentBlock) {
Scope currentScope = getProgramScope().getScope(currentBlock.getScope());
stmtIt.previous();
Variable tmpVar = VariableBuilder.createIntermediate(currentScope, SymbolType.BOOLEAN, getProgram());

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
@ -70,7 +71,7 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
});
// Add dereference to call to pointer to function
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCallPointer) {
RValue procedure = ((StatementCallPointer) statement).getProcedure();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operators;
import dk.camelot64.kickc.model.statements.Statement;
@ -23,7 +24,7 @@ public class PassNArrayElementAddressOfRewriting extends Pass2SsaOptimization {
public boolean step() {
AtomicBoolean modified = new AtomicBoolean(false);
// Examine all statements
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementLValue;
@ -24,7 +25,7 @@ public class PassNAssertConstantModification extends Pass2SsaOptimization {
@Override
public boolean step() {
Set<VariableRef> assigned = new HashSet<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementLValue) {
LValue lValue = ((StatementLValue) statement).getlValue();

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
@ -23,7 +24,7 @@ public class PassNAssertTypeMatch extends Pass2SsaAssertion {
@Override
public void check() throws AssertionFailed {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
checkAssignment((StatementAssignment) statement);

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.values.LabelRef;
@ -19,7 +20,7 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
@Override
public boolean step() {
List<ControlFlowBlock> entryPointBlocks = getGraph().getEntryPointBlocks(getProgram());
List<ControlFlowBlock> entryPointBlocks = getProgram().getEntryPointBlocks();
for(ControlFlowBlock entryPointBlock : entryPointBlocks) {
pushTodo(entryPointBlock);
@ -27,7 +28,7 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
List<LabelRef> sequence = new ArrayList<>();
while(hasTodo()) {
ControlFlowBlock block = popTodo();
Graph.Block block = popTodo();
if(block == null) {
break;
}
@ -39,8 +40,8 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
if(block.getCallSuccessor() != null) {
pushCallTodo(getGraph().getCallSuccessor(block));
}
ControlFlowBlock conditionalSuccessor = getGraph().getConditionalSuccessor(block);
ControlFlowBlock defaultSuccessor = getGraph().getDefaultSuccessor(block);
Graph.Block conditionalSuccessor = getGraph().getConditionalSuccessor(block);
Graph.Block defaultSuccessor = getGraph().getDefaultSuccessor(block);
if(conditionalSuccessor != null && defaultSuccessor != null) {
// Both conditional and default successor
if(conditionalSuccessor.getDefaultSuccessor().equals(defaultSuccessor.getLabel())) {
@ -77,7 +78,7 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
}
void pushTodo(ControlFlowBlock block) {
void pushTodo(Graph.Block block) {
LabelRef blockRef = block.getLabel();
Scope blockScope = getProgramScope().getSymbol(blockRef).getScope();
for(ScopeTodo todoScope : todoScopes) {
@ -91,7 +92,7 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
newScopeTodo.pushTodo(block);
}
void pushCallTodo(ControlFlowBlock block) {
void pushCallTodo(Graph.Block block) {
LabelRef blockRef = block.getLabel();
Scope blockScope = getProgramScope().getSymbol(blockRef).getScope();
for(ScopeTodo todoScope : todoScopes) {
@ -115,9 +116,9 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
return !todoScopes.isEmpty();
}
ControlFlowBlock popTodo() {
Graph.Block popTodo() {
ScopeTodo scopeTodo = todoScopes.peek();
ControlFlowBlock block = scopeTodo.todo.pop();
Graph.Block block = scopeTodo.todo.pop();
if(scopeTodo.todo.isEmpty()) {
todoScopes.pop();
}
@ -128,18 +129,18 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
Scope scope;
Deque<ControlFlowBlock> todo;
Deque<Graph.Block> todo;
public ScopeTodo(Scope scope) {
this.scope = scope;
this.todo = new LinkedList<>();
}
public void pushTodo(ControlFlowBlock block) {
public void pushTodo(Graph.Block block) {
todo.addFirst(block);
}
public void addTodo(ControlFlowBlock block) {
public void addTodo(Graph.Block block) {
todo.addLast(block);
}

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.ControlFlowGraphBaseVisitor;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Label;
@ -25,30 +26,30 @@ public class PassNCullEmptyBlocks extends Pass2SsaOptimization {
@Override
public boolean step() {
final List<ControlFlowBlock> remove = new ArrayList<>();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
final List<Graph.Block> remove = new ArrayList<>();
for(var block : getGraph().getAllBlocks()) {
if(block.getStatements().isEmpty() && block.getLabel().isIntermediate()) {
remove.add(block);
}
}
List<ControlFlowBlock> dontRemove = new ArrayList<>();
List<Graph.Block> dontRemove = new ArrayList<>();
for(final ControlFlowBlock removeBlock : remove) {
ControlFlowBlock successor = getGraph().getDefaultSuccessor(removeBlock);
for(final Graph.Block removeBlock : remove) {
Graph.Block successor = getGraph().getDefaultSuccessor(removeBlock);
if(successor==null) {
dontRemove.add(removeBlock);
continue;
}
LabelRef successorRef = successor.getLabel();
// Replace all jumps (default/conditional/call) to @removeBlock with a jump to the default successor
final List<ControlFlowBlock> predecessors = getGraph().getPredecessors(removeBlock);
final List<Graph.Block> predecessors = getGraph().getPredecessors(removeBlock);
// If a candidate remove block has a predecessor that has the same successor as the remove block:
// Do not remove it - because this will result in problems in distinguishing the default successor and
// the conditional successor when generating the phi-block of the successor
boolean dontCull = false;
for(ControlFlowBlock predecessor : predecessors) {
for(var predecessor : predecessors) {
if(successorRef.equals(predecessor.getConditionalSuccessor()) || successorRef.equals(predecessor.getDefaultSuccessor())) {
if(getLog().isVerboseNonOptimization()) {
getLog().append("Not culling empty block because it shares successor with its predecessor. " + removeBlock.getLabel().toString(getProgram()));
@ -69,7 +70,7 @@ public class PassNCullEmptyBlocks extends Pass2SsaOptimization {
if(phiRValue.getPredecessor().equals(removeBlock.getLabel())) {
// Found a phi function referencing the remove block - add copies for each predecessor
RValue previousRValue = phiRValue.getrValue();
for(ControlFlowBlock predecessor : predecessors) {
for(var predecessor : predecessors) {
if(phiRValue != null) {
phiRValue.setPredecessor(predecessor.getLabel());
phiRValue = null;
@ -86,7 +87,7 @@ public class PassNCullEmptyBlocks extends Pass2SsaOptimization {
};
phiFixVisitor.visitBlock(successor);
for(ControlFlowBlock predecessor : predecessors) {
for(var predecessor : predecessors) {
Map<LabelRef, LabelRef> replace = new LinkedHashMap<>();
replace.put(removeBlock.getLabel(), successorRef);
if(removeBlock.getLabel().equals(predecessor.getDefaultSuccessor())) {

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableBuilder;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
import dk.camelot64.kickc.model.iterator.ProgramValue;
@ -47,7 +44,7 @@ public class PassNDeInlineCastValues extends Pass2SsaOptimization {
return false;
}
private void deInlineCastValue(ProgramValue castProgramValue, ListIterator<Statement> stmtIt, ControlFlowBlock currentBlock, Statement currentStmt) {
private void deInlineCastValue(ProgramValue castProgramValue, ListIterator<Statement> stmtIt, Graph.Block currentBlock, Statement currentStmt) {
final CastValue castValue = (CastValue) castProgramValue.get();
if(!pass1)
getLog().append("De-inlining cast " + castValue.toString());

View File

@ -1,10 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.StatementInfos;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
@ -66,8 +63,8 @@ public class PassNEliminateEmptyProcedure extends Pass2SsaOptimization {
for(VariableReferenceInfos.ReferenceToSymbolVar use : uses) {
if(use instanceof VariableReferenceInfos.ReferenceInStatement) {
final Integer statementIdx = ((VariableReferenceInfos.ReferenceInStatement) use).getStatementIdx();
final ControlFlowBlock block = statementInfos.getBlock(statementIdx);
final Procedure useProcedure = block.getProcedure(program);
final Graph.Block block = statementInfos.getBlock(statementIdx);
final Procedure useProcedure = program.getProcedure(block);
if(!procedureRef.equals(useProcedure.getRef())) {
// Usage in a another procedure
return true;
@ -94,9 +91,9 @@ public class PassNEliminateEmptyProcedure extends Pass2SsaOptimization {
* @return true if the procedure body is empty.
*/
private boolean hasEmptyBody(ProcedureRef procedureRef) {
final List<ControlFlowBlock> procedureBlocks = getGraph().getScopeBlocks(procedureRef);
final List<Graph.Block> procedureBlocks = getGraph().getScopeBlocks(procedureRef);
// The single no-args no-return call of the procedure (if found)
for(ControlFlowBlock block : procedureBlocks) {
for(var block : procedureBlocks) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementReturn && ((StatementReturn) statement).getValue() == null) {
// An empty return is OK
@ -115,8 +112,8 @@ public class PassNEliminateEmptyProcedure extends Pass2SsaOptimization {
* @param removeProcRef The procedure to remove calls for
* @param blocks The blocks to remove the calls from
*/
public static void removeAllCalls(ProcedureRef removeProcRef, List<ControlFlowBlock> blocks, CompileLog log) {
for(ControlFlowBlock block : blocks) {
public static void removeAllCalls(ProcedureRef removeProcRef, List<Graph.Block> blocks, CompileLog log) {
for(var block : blocks) {
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCall;
@ -42,10 +43,10 @@ public class PassNEliminateEmptyStart extends Pass2SsaOptimization {
* @return The single no-args no-return call
*/
private StatementCall getSingleCall(ProcedureRef procedureRef) {
final List<ControlFlowBlock> startBlocks = getGraph().getScopeBlocks(procedureRef);
final List<Graph.Block> startBlocks = getGraph().getScopeBlocks(procedureRef);
// The single no-args no-return call of the procedure (if found)
StatementCall singleCall = null;
for(ControlFlowBlock block : startBlocks) {
for(var block : startBlocks) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCall) {
if(singleCall != null)

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCalling;
@ -30,8 +31,8 @@ public class PassNEliminateUnusedConstructors extends Pass2SsaOptimization {
if(startProc != null) {
// find all constructor-calls in __init() pointing to unused constructors
List<ProcedureRef> unusedConstructors = new ArrayList<>();
final List<ControlFlowBlock> startProcBlocks = getGraph().getScopeBlocks(startProc.getRef());
for(ControlFlowBlock block : startProcBlocks) {
final List<Graph.Block> startProcBlocks = getGraph().getScopeBlocks(startProc.getRef());
for(var block : startProcBlocks) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCalling) {
final ProcedureRef procedureRef = ((StatementCalling) statement).getProcedure();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.statements.*;
@ -34,7 +35,7 @@ public class PassNEliminateUnusedVars extends Pass2SsaOptimization {
getProgram().clearControlFlowBlockSuccessorClosure();
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
boolean modified = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ConstantNotLiteral;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.operators.Operators;
@ -30,7 +27,7 @@ public class PassNSizeOfSimplification extends Pass2SsaOptimization {
public boolean step() {
AtomicBoolean modified = new AtomicBoolean(false);
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;

View File

@ -5,6 +5,7 @@ package dk.camelot64.kickc.passes;
*/
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
@ -21,7 +22,7 @@ public class PassNStatementIndices extends Pass2SsaOptimization {
@Override
public boolean step() {
int currentIdx = 0;
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for(var block : getProgram().getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
statement.setIndex(currentIdx++);
}

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
@ -25,7 +26,7 @@ public class PassNStructUnwoundPlaceholderRemoval extends Pass2SsaOptimization {
AtomicBoolean modified = new AtomicBoolean(false);
// Remove all StructUnwoundPlaceholder assignments for C-classic structs
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -22,7 +22,7 @@ public class PassNTypeInference extends Pass2SsaOptimization {
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
try {
if(statement instanceof StatementLValue) {

View File

@ -1,9 +1,6 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.values.LValue;
@ -22,7 +19,7 @@ public class PassNUnwindLValueLists extends Pass2SsaOptimization {
@Override
public boolean step() {
boolean modified = false;
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ListIterator<Statement> stmtIt = block.getStatements().listIterator();
while(stmtIt.hasNext()) {
Statement statement = stmtIt.next();

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes.calcs;
import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.model.ControlFlowGraph;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.symbols.ProgramScope;
@ -30,7 +31,7 @@ public abstract class PassNCalcBase<Data> {
return program.getLog();
}
public ControlFlowGraph getGraph() {
public Graph getGraph() {
return program.getGraph();
}

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes.calcs;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.ControlFlowBlockSuccessorClosure;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCallExecute;
@ -23,7 +24,7 @@ public class PassNCalcBlockSuccessorClosure extends PassNCalcBase<ControlFlowBlo
@Override
public ControlFlowBlockSuccessorClosure calculate() {
LinkedHashMap<LabelRef, Collection<LabelRef>> blockSuccessors = new LinkedHashMap<>();
for(ControlFlowBlock block : getProgram().getGraph().getAllBlocks()) {
for(var block : getProgram().getGraph().getAllBlocks()) {
LabelRef blockLabel = block.getLabel();
LinkedHashSet<LabelRef> successorClosure = new LinkedHashSet<>();
findSuccessorClosure(block.getLabel(), successorClosure, new ArrayList<>());
@ -43,7 +44,7 @@ public class PassNCalcBlockSuccessorClosure extends PassNCalcBase<ControlFlowBlo
if(labelRef == null || visited.contains(labelRef))
return;
visited.add(labelRef);
ControlFlowBlock block = getProgram().getGraph().getBlock(labelRef);
Graph.Block block = getProgram().getGraph().getBlock(labelRef);
if(block == null)
return;
successorClosure.add(labelRef);

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.passes.calcs;
import dk.camelot64.kickc.model.CallGraph;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Graph;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCalling;
@ -20,7 +21,7 @@ public class PassNCalcCallGraph extends PassNCalcBase<CallGraph> {
public CallGraph calculate() {
CallGraph callGraph = new CallGraph();
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(var block : getGraph().getAllBlocks()) {
ScopeRef scopeRef = getScopeRef(block, getProgram());
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementCalling) {
@ -39,7 +40,7 @@ public class PassNCalcCallGraph extends PassNCalcBase<CallGraph> {
* @param block The block
* @return The scope containing the block. The outermost scope has a label containing an empty string.
*/
public static ScopeRef getScopeRef(ControlFlowBlock block, Program program) {
public static ScopeRef getScopeRef(Graph.Block block, Program program) {
Symbol blockSymbol = program.getScope().getSymbol(block.getLabel());
if(blockSymbol instanceof Procedure) {
return ((Procedure) blockSymbol).getRef();

Some files were not shown because too many files have changed in this diff Show More