mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-22 03:38:31 +00:00
#815 working on generalizing the control flow graph and control flow block into an interface.
This commit is contained in:
parent
185bd439e4
commit
5a74d14b41
@ -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());
|
||||
|
@ -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 =
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
163
src/main/java/dk/camelot64/kickc/model/Graph.java
Normal file
163
src/main/java/dk/camelot64/kickc/model/Graph.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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<>();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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()) {
|
||||
|
@ -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();
|
||||
|
@ -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())) {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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()))
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
@ -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) {
|
||||
|
@ -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())) {
|
||||
|
@ -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();
|
||||
|
@ -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(); }
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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()) {
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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()) {
|
||||
|
@ -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()) {
|
||||
|
@ -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()) {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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!
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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<>();
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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())) {
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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++);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user