mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-02 22:49:37 +00:00
#815 working on moving control flow graphs into procedure compilation.
This commit is contained in:
parent
5905c1d5b6
commit
1fad48f8bc
@ -11,19 +11,19 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class ControlFlowGraph implements Graph {
|
public class ControlFlowGraph implements Graph {
|
||||||
|
|
||||||
private List<ControlFlowBlock> blocks;
|
private List<Graph.Block> blocks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sequence of blocks used when generating ASM
|
* Sequence of blocks used when generating ASM
|
||||||
*/
|
*/
|
||||||
private List<LabelRef> sequence;
|
private List<LabelRef> sequence;
|
||||||
|
|
||||||
public ControlFlowGraph(List<ControlFlowBlock> blocks) {
|
public ControlFlowGraph(List<Graph.Block> blocks) {
|
||||||
this.blocks = blocks;
|
this.blocks = blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ControlFlowBlock getBlock(LabelRef symbol) {
|
public Graph.Block getBlock(LabelRef symbol) {
|
||||||
for(ControlFlowBlock block : blocks) {
|
for(var block : blocks) {
|
||||||
if(block.getLabel().equals(symbol)) {
|
if(block.getLabel().equals(symbol)) {
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
@ -31,7 +31,7 @@ public class ControlFlowGraph implements Graph {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBlock(ControlFlowBlock block) {
|
public void addBlock(Graph.Block block) {
|
||||||
blocks.add(block);
|
blocks.add(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,14 +39,10 @@ public class ControlFlowGraph implements Graph {
|
|||||||
return Collections.unmodifiableList(blocks);
|
return Collections.unmodifiableList(blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllBlocks(List<ControlFlowBlock> blocks) {
|
|
||||||
this.blocks = blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(LabelRef label) {
|
public void remove(LabelRef label) {
|
||||||
ListIterator<ControlFlowBlock> blocksIt = blocks.listIterator();
|
ListIterator<Graph.Block> blocksIt = blocks.listIterator();
|
||||||
while(blocksIt.hasNext()) {
|
while(blocksIt.hasNext()) {
|
||||||
ControlFlowBlock block = blocksIt.next();
|
var block = blocksIt.next();
|
||||||
if(block.getLabel().equals(label)) {
|
if(block.getLabel().equals(label)) {
|
||||||
blocksIt.remove();
|
blocksIt.remove();
|
||||||
return;
|
return;
|
||||||
@ -54,23 +50,6 @@ public class ControlFlowGraph implements Graph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LabelRef> getSequence() {
|
|
||||||
return sequence;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSequence(List<LabelRef> sequence) {
|
|
||||||
if(sequence.size() != blocks.size()) {
|
|
||||||
throw new CompileError("ERROR! Sequence does not contain all blocks from the program. Sequence: " + sequence.size() + " Blocks: " + blocks.size());
|
|
||||||
}
|
|
||||||
this.sequence = sequence;
|
|
||||||
ArrayList<ControlFlowBlock> seqBlocks = new ArrayList<>();
|
|
||||||
for(LabelRef labelRef : sequence) {
|
|
||||||
seqBlocks.add(getBlock(labelRef));
|
|
||||||
}
|
|
||||||
this.blocks = seqBlocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toString(null);
|
return toString(null);
|
||||||
@ -95,7 +74,7 @@ public class ControlFlowGraph implements Graph {
|
|||||||
* Clear all statement indices,
|
* Clear all statement indices,
|
||||||
*/
|
*/
|
||||||
public void clearStatementIndices() {
|
public void clearStatementIndices() {
|
||||||
for(Graph.Block block : getAllBlocks()) {
|
for(var block : getAllBlocks()) {
|
||||||
for(Statement statement : block.getStatements()) {
|
for(Statement statement : block.getStatements()) {
|
||||||
statement.setIndex(null);
|
statement.setIndex(null);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ public interface Graph {
|
|||||||
|
|
||||||
List<Block> getAllBlocks();
|
List<Block> getAllBlocks();
|
||||||
|
|
||||||
|
void addBlock(Graph.Block block);
|
||||||
|
|
||||||
default List<Graph.Block> getPredecessors(Graph.Block block) {
|
default List<Graph.Block> getPredecessors(Graph.Block block) {
|
||||||
ArrayList<Block> predecessorBlocks = new ArrayList<>();
|
ArrayList<Block> predecessorBlocks = new ArrayList<>();
|
||||||
for(Graph.Block other : getAllBlocks()) {
|
for(Graph.Block other : getAllBlocks()) {
|
||||||
|
@ -4,7 +4,6 @@ import dk.camelot64.kickc.CompileLog;
|
|||||||
import dk.camelot64.kickc.OutputFileManager;
|
import dk.camelot64.kickc.OutputFileManager;
|
||||||
import dk.camelot64.kickc.asm.AsmProgram;
|
import dk.camelot64.kickc.asm.AsmProgram;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateMasterSynthesizer;
|
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.statements.StatementPhiBlock;
|
||||||
import dk.camelot64.kickc.model.symbols.*;
|
import dk.camelot64.kickc.model.symbols.*;
|
||||||
import dk.camelot64.kickc.model.values.LabelRef;
|
import dk.camelot64.kickc.model.values.LabelRef;
|
||||||
@ -158,12 +157,17 @@ public class Program {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Block> getAllBlocks() {
|
public List<Block> getAllBlocks() {
|
||||||
return getProcedureCompilations().stream().map(ProcedureCompilation::getGraph).map(ControlFlowGraph::getAllBlocks).flatMap(Collection::stream).collect(Collectors.toList());
|
return getProcedureCompilations().stream().map(ProcedureCompilation::getGraph).map(ControlFlowGraph::getAllBlocks).flatMap(Collection::stream).collect(Collectors.toUnmodifiableList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBlock(Block block) {
|
||||||
|
throw new CompileError("Internal Error! Cannot add blocks to the read-only total control flow graph!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<ProcedureCompilation> getProcedureCompilations() {
|
public Collection<ProcedureCompilation> getProcedureCompilations() {
|
||||||
return procedureCompilations.values();
|
return procedureCompilations.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,19 @@ public abstract class Scope implements Symbol {
|
|||||||
setFullName();
|
setFullName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the containing procedure.
|
||||||
|
* @return The procedure containing the scope. Null if the scope is not contained in a procedure.
|
||||||
|
*/
|
||||||
|
public Procedure getProcedure() {
|
||||||
|
if(this instanceof Procedure)
|
||||||
|
return (Procedure) this;
|
||||||
|
else if(this instanceof ProgramScope)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return this.getScope().getProcedure();
|
||||||
|
}
|
||||||
|
|
||||||
private void setFullName() {
|
private void setFullName() {
|
||||||
String scopeName = (parentScope == null) ? "" : parentScope.getFullName();
|
String scopeName = (parentScope == null) ? "" : parentScope.getFullName();
|
||||||
fullName = (scopeName.length() > 0) ? scopeName + "::" + name : name;
|
fullName = (scopeName.length() > 0) ? scopeName + "::" + name : name;
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package dk.camelot64.kickc.passes;
|
package dk.camelot64.kickc.passes;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.*;
|
||||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
|
||||||
import dk.camelot64.kickc.model.ProcedureCompilation;
|
|
||||||
import dk.camelot64.kickc.model.Program;
|
|
||||||
import dk.camelot64.kickc.model.symbols.Label;
|
import dk.camelot64.kickc.model.symbols.Label;
|
||||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||||
|
|
||||||
@ -29,7 +26,7 @@ public class Pass1AssertProcedureDefined extends Pass1Base {
|
|||||||
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
|
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
|
||||||
if(procedureCompilation == null)
|
if(procedureCompilation == null)
|
||||||
throw new CompileError("Error! Function body is never defined: " + procedure.getFullName());
|
throw new CompileError("Error! Function body is never defined: " + procedure.getFullName());
|
||||||
final ControlFlowBlock procedureBlock = procedureCompilation.getGraph().getBlock(procedureLabel.getRef());
|
final Graph.Block procedureBlock = procedureCompilation.getGraph().getBlock(procedureLabel.getRef());
|
||||||
if(procedureBlock == null)
|
if(procedureBlock == null)
|
||||||
throw new CompileError("Error! Function body is never defined: " + procedure.getFullName());
|
throw new CompileError("Error! Function body is never defined: " + procedure.getFullName());
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public class Pass1AssertReturn extends Pass1Base {
|
|||||||
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
|
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
|
||||||
final ControlFlowGraph graph = procedureCompilation.getGraph();
|
final ControlFlowGraph graph = procedureCompilation.getGraph();
|
||||||
LabelRef entryLabel = procedure.getRef().getLabelRef();
|
LabelRef entryLabel = procedure.getRef().getLabelRef();
|
||||||
ControlFlowBlock entryBlock = graph.getBlock(entryLabel);
|
Graph.Block entryBlock = graph.getBlock(entryLabel);
|
||||||
assertReturn(graph, entryBlock, new LinkedHashSet<>());
|
assertReturn(graph, entryBlock, new LinkedHashSet<>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,25 +45,23 @@ public class Pass1AssertReturn extends Pass1Base {
|
|||||||
* @param block The block to examine
|
* @param block The block to examine
|
||||||
* @param visited Blocks already visited
|
* @param visited Blocks already visited
|
||||||
*/
|
*/
|
||||||
public void assertReturn(ControlFlowGraph graph, ControlFlowBlock block, Collection<LabelRef> visited) {
|
public void assertReturn(ControlFlowGraph graph, Graph.Block block, Collection<LabelRef> visited) {
|
||||||
if(visited.contains(block.getLabel())) {
|
if(visited.contains(block.getLabel())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
visited.add(block.getLabel());
|
visited.add(block.getLabel());
|
||||||
for(Statement statement : block.getStatements()) {
|
for(Statement statement : block.getStatements()) {
|
||||||
if(statement instanceof StatementAssignment) {
|
if(statement instanceof StatementAssignment assignment) {
|
||||||
StatementAssignment assignment = (StatementAssignment) statement;
|
|
||||||
if(assignment.getlValue() instanceof VariableRef && ((VariableRef) assignment.getlValue()).getLocalName().equals("return")) {
|
if(assignment.getlValue() instanceof VariableRef && ((VariableRef) assignment.getlValue()).getLocalName().equals("return")) {
|
||||||
// Happy days - return found!
|
// Happy days - return found!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if(statement instanceof StatementConditionalJump) {
|
} else if(statement instanceof StatementConditionalJump cond) {
|
||||||
StatementConditionalJump cond = (StatementConditionalJump) statement;
|
Graph.Block jumpTo = graph.getBlock(cond.getDestination());
|
||||||
ControlFlowBlock jumpTo = graph.getBlock(cond.getDestination());
|
|
||||||
assertReturn(graph, jumpTo, visited);
|
assertReturn(graph, jumpTo, visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ControlFlowBlock successor = graph.getBlock(block.getDefaultSuccessor());
|
Graph.Block successor = graph.getBlock(block.getDefaultSuccessor());
|
||||||
if(successor == null || successor.getLabel().getLocalName().equals(SymbolRef.PROCEXIT_BLOCK_NAME)) {
|
if(successor == null || successor.getLabel().getLocalName().equals(SymbolRef.PROCEXIT_BLOCK_NAME)) {
|
||||||
throw new CompileError("Error! Method must end with a return statement. " + block.getScope().toString(getProgram()));
|
throw new CompileError("Error! Method must end with a return statement. " + block.getScope().toString(getProgram()));
|
||||||
} else {
|
} else {
|
||||||
|
@ -15,18 +15,28 @@ import java.util.*;
|
|||||||
/** Handle calling convention {@link Procedure.CallingConvention#PHI_CALL} by passing parameters through variables */
|
/** Handle calling convention {@link Procedure.CallingConvention#PHI_CALL} by passing parameters through variables */
|
||||||
public class Pass1CallPhiParameters {
|
public class Pass1CallPhiParameters {
|
||||||
|
|
||||||
private Program program;
|
private final Program program;
|
||||||
|
|
||||||
public Pass1CallPhiParameters(Program program) {
|
public Pass1CallPhiParameters(Program program) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<LabelRef, LabelRef> splitBlockMap = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
public void execute() {
|
public void execute() {
|
||||||
final List<Graph.Block> todoBlocks = getGraph().getAllBlocks();
|
for(ProcedureCompilation procedureCompilation : this.program.getProcedureCompilations()) {
|
||||||
|
handleProcedure(procedureCompilation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleProcedure(ProcedureCompilation procedureCompilation) {
|
||||||
|
|
||||||
|
final Graph graph = procedureCompilation.getGraph();
|
||||||
|
|
||||||
|
final List<Graph.Block> todoBlocks = new ArrayList<>(graph.getAllBlocks());
|
||||||
List<Graph.Block> doneBlocks = new ArrayList<>();
|
List<Graph.Block> doneBlocks = new ArrayList<>();
|
||||||
|
|
||||||
|
Map<LabelRef, LabelRef> splitBlockMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
while(!todoBlocks.isEmpty()) {
|
while(!todoBlocks.isEmpty()) {
|
||||||
final Graph.Block block = todoBlocks.get(0);
|
final Graph.Block block = todoBlocks.get(0);
|
||||||
todoBlocks.remove(0);
|
todoBlocks.remove(0);
|
||||||
@ -35,14 +45,13 @@ public class Pass1CallPhiParameters {
|
|||||||
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
|
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
|
||||||
while(stmtIt.hasNext()) {
|
while(stmtIt.hasNext()) {
|
||||||
Statement statement = stmtIt.next();
|
Statement statement = stmtIt.next();
|
||||||
if(statement instanceof StatementCall) {
|
if(statement instanceof StatementCall call) {
|
||||||
StatementCall call = (StatementCall) statement;
|
|
||||||
// Generate parameter passing assignments
|
// Generate parameter passing assignments
|
||||||
ProcedureRef procedureRef = call.getProcedure();
|
ProcedureRef procedureRef = call.getProcedure();
|
||||||
Procedure procedure = getScope().getProcedure(procedureRef);
|
Procedure procedure = getScope().getProcedure(procedureRef);
|
||||||
// Handle PHI-calls
|
// Handle PHI-calls
|
||||||
if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) {
|
if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) {
|
||||||
final ControlFlowBlock newBlock = handlePhiCall(call, procedure, stmtIt, block);
|
final ControlFlowBlock newBlock = handlePhiCall(call, procedure, stmtIt, block, splitBlockMap);
|
||||||
// The current block was split into two blocks - add the new block at the front of the todoBlocks
|
// The current block was split into two blocks - add the new block at the front of the todoBlocks
|
||||||
todoBlocks.add(0, newBlock);
|
todoBlocks.add(0, newBlock);
|
||||||
}
|
}
|
||||||
@ -57,18 +66,19 @@ public class Pass1CallPhiParameters {
|
|||||||
for(VariableRef modifiedVar : modifiedVars) {
|
for(VariableRef modifiedVar : modifiedVars) {
|
||||||
if(getScope().getVariable(modifiedVar).isKindLoadStore())
|
if(getScope().getVariable(modifiedVar).isKindLoadStore())
|
||||||
continue;
|
continue;
|
||||||
stmtIt.add(new StatementAssignment(modifiedVar, modifiedVar, false, ((StatementReturn) statement).getSource(), Comment.NO_COMMENTS));
|
stmtIt.add(new StatementAssignment(modifiedVar, modifiedVar, false, statement.getSource(), Comment.NO_COMMENTS));
|
||||||
}
|
}
|
||||||
stmtIt.next();
|
stmtIt.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update graph blocks to include the new blocks added
|
// Update graph blocks to include the new blocks added
|
||||||
program.getGraph().setAllBlocks(doneBlocks);
|
procedureCompilation.setGraph(new ControlFlowGraph(doneBlocks));
|
||||||
|
|
||||||
// Fix phi predecessors for any blocks has a split block as predecessor
|
// Fix phi predecessors for any blocks has a split block as predecessor
|
||||||
for(Graph.Block block : getGraph().getAllBlocks()) {
|
for(var block : procedureCompilation.getGraph().getAllBlocks()) {
|
||||||
if(block.hasPhiBlock()) {
|
if(block.hasPhiBlock()) {
|
||||||
for(StatementPhiBlock.PhiVariable phiVariable : block.getPhiBlock().getPhiVariables()) {
|
for(StatementPhiBlock.PhiVariable phiVariable : block.getPhiBlock().getPhiVariables()) {
|
||||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||||
@ -86,11 +96,7 @@ public class Pass1CallPhiParameters {
|
|||||||
return program.getScope();
|
return program.getScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Graph getGraph() {
|
private ControlFlowBlock handlePhiCall(StatementCall call, Procedure procedure, ListIterator<Statement> stmtIt, Graph.Block block, Map<LabelRef, LabelRef> splitBlockMap) {
|
||||||
return program.getGraph();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ControlFlowBlock handlePhiCall(StatementCall call, Procedure procedure, ListIterator<Statement> stmtIt, Graph.Block block) {
|
|
||||||
|
|
||||||
List<Variable> parameterDefs = procedure.getParameters();
|
List<Variable> parameterDefs = procedure.getParameters();
|
||||||
List<RValue> parameterValues = call.getParameters();
|
List<RValue> parameterValues = call.getParameters();
|
||||||
|
@ -32,10 +32,10 @@ public class Pass1GenerateControlFlowGraph extends Pass1Base {
|
|||||||
// Empty procedures should not produce any blocks
|
// Empty procedures should not produce any blocks
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
List<ControlFlowBlock> blocks = new ArrayList<>();
|
List<Graph.Block> blocks = new ArrayList<>();
|
||||||
|
|
||||||
ControlFlowBlock currentBlock = null;
|
Graph.Block currentBlock;
|
||||||
ControlFlowBlock procBlock = getOrCreateBlock(procedure.getLabel().getRef(), procedure.getRef(), blocks);
|
Graph.Block procBlock = getOrCreateBlock(procedure.getLabel().getRef(), procedure.getRef(), blocks);
|
||||||
currentBlock = procBlock;
|
currentBlock = procBlock;
|
||||||
for(Statement statement : sequence.getStatements()) {
|
for(Statement statement : sequence.getStatements()) {
|
||||||
Symbol currentBlockLabel = getProgram().getScope().getSymbol(currentBlock.getLabel());
|
Symbol currentBlockLabel = getProgram().getScope().getSymbol(currentBlock.getLabel());
|
||||||
@ -50,29 +50,25 @@ public class Pass1GenerateControlFlowGraph extends Pass1Base {
|
|||||||
} else if(statement instanceof StatementProcedureEnd) {
|
} else if(statement instanceof StatementProcedureEnd) {
|
||||||
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
||||||
currentBlock.setDefaultSuccessor(new Label(SymbolRef.PROCEXIT_BLOCK_NAME, programScope, false).getRef());
|
currentBlock.setDefaultSuccessor(new Label(SymbolRef.PROCEXIT_BLOCK_NAME, programScope, false).getRef());
|
||||||
} else if(statement instanceof StatementLabel) {
|
} else if(statement instanceof StatementLabel statementLabel) {
|
||||||
StatementLabel statementLabel = (StatementLabel) statement;
|
Graph.Block nextBlock = getOrCreateBlock(statementLabel.getLabel(), currentBlock.getScope(), blocks);
|
||||||
ControlFlowBlock nextBlock = getOrCreateBlock(statementLabel.getLabel(), currentBlock.getScope(), blocks);
|
|
||||||
nextBlock.setComments(statementLabel.getComments());
|
nextBlock.setComments(statementLabel.getComments());
|
||||||
currentBlock.setDefaultSuccessor(nextBlock.getLabel());
|
currentBlock.setDefaultSuccessor(nextBlock.getLabel());
|
||||||
currentBlock = nextBlock;
|
currentBlock = nextBlock;
|
||||||
} else if(statement instanceof StatementJump) {
|
} else if(statement instanceof StatementJump statementJump) {
|
||||||
StatementJump statementJump = (StatementJump) statement;
|
Graph.Block jmpBlock = getOrCreateBlock(statementJump.getDestination(), currentBlock.getScope(), blocks);
|
||||||
ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination(), currentBlock.getScope(), blocks);
|
|
||||||
currentBlock.setDefaultSuccessor(jmpBlock.getLabel());
|
currentBlock.setDefaultSuccessor(jmpBlock.getLabel());
|
||||||
ControlFlowBlock nextBlock = getOrCreateBlock(currentBlockScope.addLabelIntermediate().getRef(), currentBlock.getScope(), blocks);
|
Graph.Block nextBlock = getOrCreateBlock(currentBlockScope.addLabelIntermediate().getRef(), currentBlock.getScope(), blocks);
|
||||||
currentBlock = nextBlock;
|
currentBlock = nextBlock;
|
||||||
} else if(statement instanceof StatementConditionalJump) {
|
} else if(statement instanceof StatementConditionalJump statementConditionalJump) {
|
||||||
currentBlock.addStatement(statement);
|
currentBlock.addStatement(statement);
|
||||||
StatementConditionalJump statementConditionalJump = (StatementConditionalJump) statement;
|
Graph.Block jmpBlock = getOrCreateBlock(statementConditionalJump.getDestination(), currentBlock.getScope(), blocks);
|
||||||
ControlFlowBlock jmpBlock = getOrCreateBlock(statementConditionalJump.getDestination(), currentBlock.getScope(), blocks);
|
Graph.Block nextBlock = getOrCreateBlock(currentBlockScope.addLabelIntermediate().getRef(), currentBlock.getScope(), blocks);
|
||||||
ControlFlowBlock nextBlock = getOrCreateBlock(currentBlockScope.addLabelIntermediate().getRef(), currentBlock.getScope(), blocks);
|
|
||||||
currentBlock.setDefaultSuccessor(nextBlock.getLabel());
|
currentBlock.setDefaultSuccessor(nextBlock.getLabel());
|
||||||
currentBlock.setConditionalSuccessor(jmpBlock.getLabel());
|
currentBlock.setConditionalSuccessor(jmpBlock.getLabel());
|
||||||
currentBlock = nextBlock;
|
currentBlock = nextBlock;
|
||||||
} else if(statement instanceof StatementReturn) {
|
} else if(statement instanceof StatementReturn aReturn) {
|
||||||
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
||||||
StatementReturn aReturn = (StatementReturn) statement;
|
|
||||||
currentBlock.addStatement(aReturn);
|
currentBlock.addStatement(aReturn);
|
||||||
} else {
|
} else {
|
||||||
currentBlock.addStatement(statement);
|
currentBlock.addStatement(statement);
|
||||||
@ -85,13 +81,13 @@ public class Pass1GenerateControlFlowGraph extends Pass1Base {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControlFlowBlock getOrCreateBlock(LabelRef label, ScopeRef scope, List<ControlFlowBlock> blocks) {
|
private Graph.Block getOrCreateBlock(LabelRef label, ScopeRef scope, List<Graph.Block> blocks) {
|
||||||
for(ControlFlowBlock block : blocks) {
|
for(var block : blocks) {
|
||||||
if(block.getLabel().equals(label)) {
|
if(block.getLabel().equals(label)) {
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ControlFlowBlock block = new ControlFlowBlock(label, scope);
|
Graph.Block block = new ControlFlowBlock(label, scope);
|
||||||
blocks.add(block);
|
blocks.add(block);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
@ -23,16 +23,23 @@ public class Pass1ProcedureInline extends Pass1Base {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean step() {
|
public boolean step() {
|
||||||
List<Graph.Block> allBlocks = getGraph().getAllBlocks();
|
for(var procedureCompilation : getProgram().getProcedureCompilations())
|
||||||
ListIterator<Graph.Block> blocksIt = allBlocks.listIterator();
|
if(inlineProcedure(procedureCompilation))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean inlineProcedure(ProcedureCompilation procedureCompilation) {
|
||||||
|
final ControlFlowGraph procedureGraph = procedureCompilation.getGraph();
|
||||||
|
final List<Graph.Block> procedureBlocks = new ArrayList<>(procedureGraph.getAllBlocks());
|
||||||
|
ListIterator<Graph.Block> blocksIt = procedureBlocks.listIterator();
|
||||||
while(blocksIt.hasNext()) {
|
while(blocksIt.hasNext()) {
|
||||||
Graph.Block block = blocksIt.next();
|
Graph.Block block = blocksIt.next();
|
||||||
List<Statement> blockStatements = block.getStatements();
|
List<Statement> blockStatements = block.getStatements();
|
||||||
ListIterator<Statement> statementsIt = blockStatements.listIterator();
|
ListIterator<Statement> statementsIt = blockStatements.listIterator();
|
||||||
while(statementsIt.hasNext()) {
|
while(statementsIt.hasNext()) {
|
||||||
Statement statement = statementsIt.next();
|
Statement statement = statementsIt.next();
|
||||||
if(statement instanceof StatementCall) {
|
if(statement instanceof StatementCall call) {
|
||||||
StatementCall call = (StatementCall) statement;
|
|
||||||
ProcedureRef procedureRef = call.getProcedure();
|
ProcedureRef procedureRef = call.getProcedure();
|
||||||
Procedure procedure = getProgramScope().getProcedure(procedureRef);
|
Procedure procedure = getProgramScope().getProcedure(procedureRef);
|
||||||
if(procedure.isDeclaredInline()) {
|
if(procedure.isDeclaredInline()) {
|
||||||
@ -41,6 +48,8 @@ public class Pass1ProcedureInline extends Pass1Base {
|
|||||||
throw new CompileError("Error! Interrupts cannot be inlined. "+procedure.getRef().toString());
|
throw new CompileError("Error! Interrupts cannot be inlined. "+procedure.getRef().toString());
|
||||||
}
|
}
|
||||||
inlineProcedureCall(call, procedure, statementsIt, block, blocksIt);
|
inlineProcedureCall(call, procedure, statementsIt, block, blocksIt);
|
||||||
|
// Update the procedure graph
|
||||||
|
procedureCompilation.setGraph(new ControlFlowGraph(procedureBlocks));
|
||||||
// Exit and restart
|
// Exit and restart
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -184,24 +193,17 @@ public class Pass1ProcedureInline extends Pass1Base {
|
|||||||
*/
|
*/
|
||||||
private Statement inlineStatement(Statement procStatement, Procedure procedure, Scope callScope, int serial) {
|
private Statement inlineStatement(Statement procStatement, Procedure procedure, Scope callScope, int serial) {
|
||||||
Statement inlinedStatement;
|
Statement inlinedStatement;
|
||||||
if(procStatement instanceof StatementAssignment) {
|
if(procStatement instanceof StatementAssignment procAssignment) {
|
||||||
StatementAssignment procAssignment = (StatementAssignment) procStatement;
|
|
||||||
inlinedStatement = new StatementAssignment(procAssignment.getlValue(), procAssignment.getrValue1(), procAssignment.getOperator(), procAssignment.getrValue2(), procAssignment.isInitialAssignment(), procAssignment.getSource(), Comment.NO_COMMENTS);
|
inlinedStatement = new StatementAssignment(procAssignment.getlValue(), procAssignment.getrValue1(), procAssignment.getOperator(), procAssignment.getrValue2(), procAssignment.isInitialAssignment(), procAssignment.getSource(), Comment.NO_COMMENTS);
|
||||||
} else if(procStatement instanceof StatementCall) {
|
} else if(procStatement instanceof StatementCall procCall) {
|
||||||
StatementCall procCall = (StatementCall) procStatement;
|
|
||||||
StatementCall inlinedCall = new StatementCall(procCall.getlValue(), procCall.getProcedureName(), new ArrayList<>(procCall.getParameters()), procCall.getSource(), procCall.getComments());
|
StatementCall inlinedCall = new StatementCall(procCall.getlValue(), procCall.getProcedureName(), new ArrayList<>(procCall.getParameters()), procCall.getSource(), procCall.getComments());
|
||||||
inlinedCall.setProcedure(procCall.getProcedure());
|
inlinedCall.setProcedure(procCall.getProcedure());
|
||||||
inlinedStatement = inlinedCall;
|
inlinedStatement = inlinedCall;
|
||||||
} else if(procStatement instanceof StatementAsm) {
|
} else if(procStatement instanceof StatementAsm procAsm) {
|
||||||
StatementAsm procAsm = (StatementAsm) procStatement;
|
inlinedStatement = new StatementAsm(procAsm.getAsmLines(), new LinkedHashMap<>(procAsm.getReferenced()), procAsm.getDeclaredClobber(), procAsm.getSource(), Comment.NO_COMMENTS);
|
||||||
StatementAsm inlinedAsm = new StatementAsm(procAsm.getAsmLines(), new LinkedHashMap<>(procAsm.getReferenced()), procAsm.getDeclaredClobber(), procAsm.getSource(), Comment.NO_COMMENTS);
|
} else if(procStatement instanceof StatementKickAsm procKasm) {
|
||||||
inlinedStatement = inlinedAsm;
|
inlinedStatement = new StatementKickAsm(procKasm.getKickAsmCode(), procKasm.getBytes(), procKasm.getCycles(), procKasm.getUses(), procKasm.getDeclaredClobber(), procKasm.getSource(), Comment.NO_COMMENTS);
|
||||||
} else if(procStatement instanceof StatementKickAsm) {
|
} else if(procStatement instanceof StatementConditionalJump procConditional) {
|
||||||
StatementKickAsm procKasm = (StatementKickAsm) procStatement;
|
|
||||||
StatementKickAsm inlinedAsm = new StatementKickAsm(procKasm.getKickAsmCode(), procKasm.getBytes(), procKasm.getCycles(), procKasm.getUses(), procKasm.getDeclaredClobber(), procKasm.getSource(), Comment.NO_COMMENTS);
|
|
||||||
inlinedStatement = inlinedAsm;
|
|
||||||
} else if(procStatement instanceof StatementConditionalJump) {
|
|
||||||
StatementConditionalJump procConditional = (StatementConditionalJump) procStatement;
|
|
||||||
LabelRef procDestinationRef = procConditional.getDestination();
|
LabelRef procDestinationRef = procConditional.getDestination();
|
||||||
Label procDestination = getProgramScope().getLabel(procDestinationRef);
|
Label procDestination = getProgramScope().getLabel(procDestinationRef);
|
||||||
Label inlinedDest = procDestination;
|
Label inlinedDest = procDestination;
|
||||||
@ -218,9 +220,7 @@ public class Pass1ProcedureInline extends Pass1Base {
|
|||||||
} else {
|
} else {
|
||||||
throw new CompileError("Statement type of Inline function not handled " + procStatement, procStatement.getSource());
|
throw new CompileError("Statement type of Inline function not handled " + procStatement, procStatement.getSource());
|
||||||
}
|
}
|
||||||
if(inlinedStatement!=null) {
|
ProgramValueIterator.execute(inlinedStatement, new RValueInliner(procedure, serial, callScope), null, null);
|
||||||
ProgramValueIterator.execute(inlinedStatement, new RValueInliner(procedure, serial, callScope), null, null);
|
|
||||||
}
|
|
||||||
return inlinedStatement;
|
return inlinedStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,8 +246,7 @@ public class Pass1ProcedureInline extends Pass1Base {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, Graph.Block currentBlock) {
|
public void execute(ProgramValue programValue, Statement currentStmt, ListIterator<Statement> stmtIt, Graph.Block currentBlock) {
|
||||||
Value rValue = programValue.get();
|
Value rValue = programValue.get();
|
||||||
if(rValue instanceof VariableRef) {
|
if(rValue instanceof VariableRef procVarRef) {
|
||||||
VariableRef procVarRef = (VariableRef) rValue;
|
|
||||||
Variable procVar = Pass1ProcedureInline.this.getProgramScope().getVariable(procVarRef);
|
Variable procVar = Pass1ProcedureInline.this.getProgramScope().getVariable(procVarRef);
|
||||||
if(procVar.getScope().equals(procedure)) {
|
if(procVar.getScope().equals(procedure)) {
|
||||||
String inlineSymbolName = Pass1ProcedureInline.this.getInlineSymbolName(procedure, procVar, serial);
|
String inlineSymbolName = Pass1ProcedureInline.this.getInlineSymbolName(procedure, procVar, serial);
|
||||||
@ -299,8 +298,7 @@ public class Pass1ProcedureInline extends Pass1Base {
|
|||||||
callScope.addLabel(procedure.getLocalName() + serial);
|
callScope.addLabel(procedure.getLocalName() + serial);
|
||||||
// And copy all procedure symbols
|
// And copy all procedure symbols
|
||||||
for(Symbol procSymbol : procedure.getAllSymbols()) {
|
for(Symbol procSymbol : procedure.getAllSymbols()) {
|
||||||
if(procSymbol instanceof Variable) {
|
if(procSymbol instanceof Variable procVar) {
|
||||||
Variable procVar = (Variable) procSymbol;
|
|
||||||
String inlineVarName = getInlineSymbolName(procedure, procSymbol, serial);
|
String inlineVarName = getInlineSymbolName(procedure, procSymbol, serial);
|
||||||
Variable inlineVar = Variable.createCopy(inlineVarName, callScope, procVar);
|
Variable inlineVar = Variable.createCopy(inlineVarName, callScope, procVar);
|
||||||
callScope.add(inlineVar);
|
callScope.add(inlineVar);
|
||||||
|
@ -28,14 +28,22 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean step() {
|
public boolean step() {
|
||||||
|
boolean modified = false;
|
||||||
|
for(ProcedureCompilation procedureCompilation : getProgram().getProcedureCompilations()) {
|
||||||
|
modified |= findAndRewriteBooleanConditions(procedureCompilation.getGraph());
|
||||||
|
}
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean findAndRewriteBooleanConditions(Graph graph) {
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
while(!done) {
|
while(!done) {
|
||||||
VariableRef obsoleteConditionVar = findAndRewriteBooleanCondition();
|
VariableRef obsoleteConditionVar = findAndRewriteBooleanCondition(graph);
|
||||||
if(obsoleteConditionVar != null) {
|
if(obsoleteConditionVar != null) {
|
||||||
Collection<VariableRef> obsoleteVars = new ArrayList<>();
|
Collection<VariableRef> obsoleteVars = new ArrayList<>();
|
||||||
obsoleteVars.add(obsoleteConditionVar);
|
obsoleteVars.add(obsoleteConditionVar);
|
||||||
removeAssignments(getGraph(), obsoleteVars);
|
removeAssignments(graph, obsoleteVars);
|
||||||
deleteSymbols(getProgramScope(), obsoleteVars);
|
deleteSymbols(getProgramScope(), obsoleteVars);
|
||||||
modified = true;
|
modified = true;
|
||||||
} else {
|
} else {
|
||||||
@ -46,17 +54,17 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look through the entire program looking for an if() condition that uses &&, || or !.
|
* Look through a control flow graph looking for an if() condition that uses &&, || or !.
|
||||||
* When found rewrite it (adding blocks)
|
* When found rewrite it (adding blocks)
|
||||||
*
|
*
|
||||||
* @return Null if no condition was found to rewrite. The now obsolete variable containing the && / || / ! to be removed.
|
* @return Null if no condition was found to rewrite. The now obsolete variable containing the && / || / ! to be removed.
|
||||||
|
* @param graph The control flow graph to modify
|
||||||
*/
|
*/
|
||||||
private VariableRef findAndRewriteBooleanCondition() {
|
private VariableRef findAndRewriteBooleanCondition(Graph graph) {
|
||||||
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
|
final VariableReferenceInfos variableReferenceInfos = getProgram().getVariableReferenceInfos();
|
||||||
for(var block : getGraph().getAllBlocks()) {
|
for(var block : graph.getAllBlocks()) {
|
||||||
for(Statement statement : block.getStatements()) {
|
for(Statement statement : block.getStatements()) {
|
||||||
if(statement instanceof StatementConditionalJump) {
|
if(statement instanceof StatementConditionalJump conditional) {
|
||||||
StatementConditionalJump conditional = (StatementConditionalJump) statement;
|
|
||||||
if(conditional.getrValue1() == null && conditional.getOperator() == null) {
|
if(conditional.getrValue1() == null && conditional.getOperator() == null) {
|
||||||
RValue conditionRValue = conditional.getrValue2();
|
RValue conditionRValue = conditional.getrValue2();
|
||||||
if(conditionRValue instanceof VariableRef) {
|
if(conditionRValue instanceof VariableRef) {
|
||||||
@ -65,16 +73,15 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
VariableRef conditionVar = (VariableRef) conditionRValue;
|
VariableRef conditionVar = (VariableRef) conditionRValue;
|
||||||
final Integer conditionDefineStatementIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
|
final Integer conditionDefineStatementIdx = variableReferenceInfos.getVarDefineStatement(conditionVar);
|
||||||
if(conditionDefineStatementIdx != null) {
|
if(conditionDefineStatementIdx != null) {
|
||||||
final Statement conditionDefineStatement = getGraph().getStatementByIndex(conditionDefineStatementIdx);
|
final Statement conditionDefineStatement = graph.getStatementByIndex(conditionDefineStatementIdx);
|
||||||
if(conditionDefineStatement instanceof StatementAssignment) {
|
if(conditionDefineStatement instanceof StatementAssignment conditionAssignment) {
|
||||||
StatementAssignment conditionAssignment = (StatementAssignment) conditionDefineStatement;
|
|
||||||
if(Operators.LOGIC_AND.equals(conditionAssignment.getOperator())) {
|
if(Operators.LOGIC_AND.equals(conditionAssignment.getOperator())) {
|
||||||
// Found if() with logical && condition - rewrite to if(c1) if(c2) { xx }
|
// Found if() with logical && condition - rewrite to if(c1) if(c2) { xx }
|
||||||
rewriteLogicAnd(block, conditional, conditionAssignment);
|
rewriteLogicAnd(block, conditional, conditionAssignment, getGraph());
|
||||||
return conditionVar;
|
return conditionVar;
|
||||||
} else if(Operators.LOGIC_OR.equals(conditionAssignment.getOperator())) {
|
} else if(Operators.LOGIC_OR.equals(conditionAssignment.getOperator())) {
|
||||||
// Found if() with logical || condition - rewrite to if(c1) goto x else if(c2) goto x else goto end, x:{ xx } end:
|
// Found if() with logical || condition - rewrite to if(c1) goto x else if(c2) goto x else goto end, x:{ xx } end:
|
||||||
rewriteLogicOr(block, conditional, conditionAssignment);
|
rewriteLogicOr(block, conditional, conditionAssignment, getGraph());
|
||||||
return conditionVar;
|
return conditionVar;
|
||||||
} else if(Operators.LOGIC_NOT.equals(conditionAssignment.getOperator())) {
|
} else if(Operators.LOGIC_NOT.equals(conditionAssignment.getOperator())) {
|
||||||
// Found if() with logical ! condition - rewrite to if(!c1) goto x else goto end, x:{ xx } end:
|
// Found if() with logical ! condition - rewrite to if(!c1) goto x else goto end, x:{ xx } end:
|
||||||
@ -98,8 +105,9 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
* @param block The block containing the current if()
|
* @param block The block containing the current if()
|
||||||
* @param conditional The if()-statement
|
* @param conditional The if()-statement
|
||||||
* @param conditionAssignment The assignment defining the condition variable.
|
* @param conditionAssignment The assignment defining the condition variable.
|
||||||
|
* @param graph The control flow graph to modify
|
||||||
*/
|
*/
|
||||||
private void rewriteLogicAnd(Graph.Block block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
|
private void rewriteLogicAnd(Graph.Block block, StatementConditionalJump conditional, StatementAssignment conditionAssignment, Graph graph) {
|
||||||
// Found an if with a logical && condition - rewrite to if(c1) if(c2) { xx }
|
// 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));
|
getLog().append("Rewriting && if()-condition to two if()s " + conditionAssignment.toString(getProgram(), false));
|
||||||
ScopeRef currentScopeRef = block.getScope();
|
ScopeRef currentScopeRef = block.getScope();
|
||||||
@ -107,7 +115,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
// Add a new block containing the second part of the && condition expression
|
// Add a new block containing the second part of the && condition expression
|
||||||
Label newBlockLabel = currentScope.addLabelIntermediate();
|
Label newBlockLabel = currentScope.addLabelIntermediate();
|
||||||
ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef);
|
ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef);
|
||||||
getGraph().addBlock(newBlock);
|
graph.addBlock(newBlock);
|
||||||
LabelRef destLabel = conditional.getDestination();
|
LabelRef destLabel = conditional.getDestination();
|
||||||
StatementConditionalJump newConditional = new StatementConditionalJump(conditionAssignment.getrValue2(), destLabel, conditional.getSource(), Comment.NO_COMMENTS);
|
StatementConditionalJump newConditional = new StatementConditionalJump(conditionAssignment.getrValue2(), destLabel, conditional.getSource(), Comment.NO_COMMENTS);
|
||||||
newConditional.setDeclaredUnroll(conditional.isDeclaredUnroll());
|
newConditional.setDeclaredUnroll(conditional.isDeclaredUnroll());
|
||||||
@ -120,7 +128,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
conditional.setrValue2(conditionAssignment.getrValue1());
|
conditional.setrValue2(conditionAssignment.getrValue1());
|
||||||
|
|
||||||
// Replace the phi labels inside the destination block with the new block
|
// Replace the phi labels inside the destination block with the new block
|
||||||
Graph.Block destBlock = getGraph().getBlock(destLabel);
|
Graph.Block destBlock = graph.getBlock(destLabel);
|
||||||
LinkedHashMap<LabelRef, LabelRef> replacements = new LinkedHashMap<>();
|
LinkedHashMap<LabelRef, LabelRef> replacements = new LinkedHashMap<>();
|
||||||
replacements.put(block.getLabel(), newBlockLabel.getRef());
|
replacements.put(block.getLabel(), newBlockLabel.getRef());
|
||||||
replaceLabels(destBlock.getPhiBlock(), replacements);
|
replaceLabels(destBlock.getPhiBlock(), replacements);
|
||||||
@ -133,15 +141,16 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
* @param block The block containing the current if()
|
* @param block The block containing the current if()
|
||||||
* @param conditional The if()-statement
|
* @param conditional The if()-statement
|
||||||
* @param conditionAssignment The assignment defining the condition variable.
|
* @param conditionAssignment The assignment defining the condition variable.
|
||||||
|
* @param graph The control flow graph to modify
|
||||||
*/
|
*/
|
||||||
private void rewriteLogicOr(Graph.Block block, StatementConditionalJump conditional, StatementAssignment conditionAssignment) {
|
private void rewriteLogicOr(Graph.Block block, StatementConditionalJump conditional, StatementAssignment conditionAssignment, Graph graph) {
|
||||||
getLog().append("Rewriting || if()-condition to two if()s " + conditionAssignment.toString(getProgram(), false));
|
getLog().append("Rewriting || if()-condition to two if()s " + conditionAssignment.toString(getProgram(), false));
|
||||||
ScopeRef currentScopeRef = block.getScope();
|
ScopeRef currentScopeRef = block.getScope();
|
||||||
Scope currentScope = getProgramScope().getScope(currentScopeRef);
|
Scope currentScope = getProgramScope().getScope(currentScopeRef);
|
||||||
// Add a new block containing the second part of the && condition expression
|
// Add a new block containing the second part of the && condition expression
|
||||||
Label newBlockLabel = currentScope.addLabelIntermediate();
|
Label newBlockLabel = currentScope.addLabelIntermediate();
|
||||||
ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef);
|
ControlFlowBlock newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScopeRef);
|
||||||
getGraph().addBlock(newBlock);
|
graph.addBlock(newBlock);
|
||||||
StatementConditionalJump newConditional = new StatementConditionalJump(conditionAssignment.getrValue2(), conditional.getDestination(), conditional.getSource(), Comment.NO_COMMENTS);
|
StatementConditionalJump newConditional = new StatementConditionalJump(conditionAssignment.getrValue2(), conditional.getDestination(), conditional.getSource(), Comment.NO_COMMENTS);
|
||||||
// Copy unrolling to the new conditional
|
// Copy unrolling to the new conditional
|
||||||
newConditional.setDeclaredUnroll(conditional.isDeclaredUnroll());
|
newConditional.setDeclaredUnroll(conditional.isDeclaredUnroll());
|
||||||
@ -155,7 +164,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
conditional.setDeclaredUnroll(false);
|
conditional.setDeclaredUnroll(false);
|
||||||
|
|
||||||
// Update the default destination PHI block to reflect the last of the conditions
|
// Update the default destination PHI block to reflect the last of the conditions
|
||||||
Graph.Block defaultDestBlock = getGraph().getBlock(newBlock.getDefaultSuccessor());
|
Graph.Block defaultDestBlock = graph.getBlock(newBlock.getDefaultSuccessor());
|
||||||
if(defaultDestBlock.hasPhiBlock()) {
|
if(defaultDestBlock.hasPhiBlock()) {
|
||||||
StatementPhiBlock defaultDestPhiBlock = defaultDestBlock.getPhiBlock();
|
StatementPhiBlock defaultDestPhiBlock = defaultDestBlock.getPhiBlock();
|
||||||
for(StatementPhiBlock.PhiVariable phiVariable : defaultDestPhiBlock.getPhiVariables()) {
|
for(StatementPhiBlock.PhiVariable phiVariable : defaultDestPhiBlock.getPhiVariables()) {
|
||||||
@ -168,13 +177,13 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Graph.Block conditionalDestBlock = getGraph().getBlock(conditional.getDestination());
|
Graph.Block conditionalDestBlock = graph.getBlock(conditional.getDestination());
|
||||||
if(conditionalDestBlock.hasPhiBlock()) {
|
if(conditionalDestBlock.hasPhiBlock()) {
|
||||||
StatementPhiBlock conditionalDestPhiBlock = conditionalDestBlock.getPhiBlock();
|
StatementPhiBlock conditionalDestPhiBlock = conditionalDestBlock.getPhiBlock();
|
||||||
for(StatementPhiBlock.PhiVariable phiVariable : conditionalDestPhiBlock.getPhiVariables()) {
|
for(StatementPhiBlock.PhiVariable phiVariable : conditionalDestPhiBlock.getPhiVariables()) {
|
||||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||||
if(phiRValue.getPredecessor().equals(block.getLabel())) {
|
if(phiRValue.getPredecessor().equals(block.getLabel())) {
|
||||||
// Found phi-variable with current block as predecessor - copy the phivalue for the new block
|
// Found phi-variable with current block as predecessor - copy the phi-value for the new block
|
||||||
phiVariable.setrValue(newBlockLabel.getRef(), phiRValue.getrValue());
|
phiVariable.setrValue(newBlockLabel.getRef(), phiRValue.getrValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
|||||||
private void removeParameters(Set<ConstantRef> inlineRefs) {
|
private void removeParameters(Set<ConstantRef> inlineRefs) {
|
||||||
for(ConstantRef inlineRef : inlineRefs) {
|
for(ConstantRef inlineRef : inlineRefs) {
|
||||||
final Scope scope = getProgramScope().getConstant(inlineRef).getScope();
|
final Scope scope = getProgramScope().getConstant(inlineRef).getScope();
|
||||||
final Procedure procedure = getProcedure(scope);
|
final Procedure procedure = scope.getProcedure();
|
||||||
if(procedure!=null) {
|
if(procedure!=null) {
|
||||||
final List<Variable> parameters = procedure.getParameters();
|
final List<Variable> parameters = procedure.getParameters();
|
||||||
final boolean modified = parameters.removeIf(param -> param.getRef().equals(inlineRef));
|
final boolean modified = parameters.removeIf(param -> param.getRef().equals(inlineRef));
|
||||||
@ -83,15 +83,6 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Procedure getProcedure(Scope scope) {
|
|
||||||
if(scope instanceof Procedure)
|
|
||||||
return (Procedure) scope;
|
|
||||||
else if(scope instanceof ProgramScope)
|
|
||||||
return null;
|
|
||||||
else
|
|
||||||
return getProcedure(scope.getScope());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace any aliases within the constant values themselves
|
* Replace any aliases within the constant values themselves
|
||||||
*
|
*
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package dk.camelot64.kickc.passes;
|
package dk.camelot64.kickc.passes;
|
||||||
|
|
||||||
import dk.camelot64.kickc.CompileLog;
|
import dk.camelot64.kickc.CompileLog;
|
||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.*;
|
||||||
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.statements.*;
|
||||||
import dk.camelot64.kickc.model.symbols.Label;
|
import dk.camelot64.kickc.model.symbols.Label;
|
||||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||||
@ -14,7 +11,7 @@ import dk.camelot64.kickc.model.values.*;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/** Pass that eliminates constant if's - they are either removed (if false) or replaces the default successor (if true). */
|
/** Pass that eliminates blocks that are not referenced. */
|
||||||
public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
|
public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
|
||||||
|
|
||||||
public Pass2EliminateUnusedBlocks(Program program) {
|
public Pass2EliminateUnusedBlocks(Program program) {
|
||||||
@ -28,9 +25,13 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
|
|||||||
for(var block : getGraph().getAllBlocks()) {
|
for(var block : getGraph().getAllBlocks()) {
|
||||||
if(!referencedBlocks.contains(block.getLabel())) {
|
if(!referencedBlocks.contains(block.getLabel())) {
|
||||||
unusedBlocks.add(block.getLabel());
|
unusedBlocks.add(block.getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var block : getGraph().getAllBlocks()) {
|
||||||
|
if(unusedBlocks.contains(block.getLabel())) {
|
||||||
for(Statement stmt : block.getStatements()) {
|
for(Statement stmt : block.getStatements()) {
|
||||||
if(stmt instanceof StatementLValue) {
|
if(stmt instanceof StatementLValue assignment) {
|
||||||
StatementLValue assignment = (StatementLValue) stmt;
|
|
||||||
LValue lValue = assignment.getlValue();
|
LValue lValue = assignment.getlValue();
|
||||||
if(lValue instanceof VariableRef) {
|
if(lValue instanceof VariableRef) {
|
||||||
Variable variable = getProgramScope().getVariable((VariableRef) lValue);
|
Variable variable = getProgramScope().getVariable((VariableRef) lValue);
|
||||||
@ -52,12 +53,14 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Set<LabelRef> removedBlocks = new HashSet<>();
|
Set<LabelRef> removedBlocks = new HashSet<>();
|
||||||
for(LabelRef unusedBlock : unusedBlocks) {
|
for(LabelRef unusedBlock : unusedBlocks) {
|
||||||
Symbol unusedSymbol = getProgramScope().getSymbol(unusedBlock);
|
Symbol unusedSymbol = getProgramScope().getSymbol(unusedBlock);
|
||||||
if(unusedSymbol instanceof Label) {
|
if(unusedSymbol instanceof Label) {
|
||||||
getGraph().remove(unusedBlock);
|
final Procedure procedure = unusedSymbol.getScope().getProcedure();
|
||||||
|
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
|
||||||
|
final ControlFlowGraph procedureGraph = procedureCompilation.getGraph();
|
||||||
|
procedureGraph.remove(unusedBlock);
|
||||||
Label label = getProgramScope().getLabel(unusedBlock);
|
Label label = getProgramScope().getLabel(unusedBlock);
|
||||||
label.getScope().remove(label);
|
label.getScope().remove(label);
|
||||||
removePhiRValues(unusedBlock, getProgram());
|
removePhiRValues(unusedBlock, getProgram());
|
||||||
@ -85,31 +88,19 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
|
|||||||
public static void removeProcedure(ProcedureRef procedureRef, Set<LabelRef> removedBlocks, Program program) {
|
public static void removeProcedure(ProcedureRef procedureRef, Set<LabelRef> removedBlocks, Program program) {
|
||||||
program.getLog().append("Removing unused procedure " + procedureRef);
|
program.getLog().append("Removing unused procedure " + procedureRef);
|
||||||
Procedure unusedProcedure = program.getScope().getProcedure(procedureRef);
|
Procedure unusedProcedure = program.getScope().getProcedure(procedureRef);
|
||||||
List<Graph.Block> procedureBlocks = program.getGraph().getScopeBlocks(procedureRef);
|
final ProcedureCompilation procedureCompilation = program.getProcedureCompilation(procedureRef);
|
||||||
|
final ControlFlowGraph procedureGraph = procedureCompilation.getGraph();
|
||||||
|
List<Graph.Block> procedureBlocks = new ArrayList<>(procedureGraph.getAllBlocks());
|
||||||
for(var procedureBlock : procedureBlocks) {
|
for(var procedureBlock : procedureBlocks) {
|
||||||
LabelRef blockLabelRef = procedureBlock.getLabel();
|
LabelRef blockLabelRef = procedureBlock.getLabel();
|
||||||
program.getLog().append("Removing unused procedure block " + blockLabelRef);
|
program.getLog().append("Removing unused procedure block " + blockLabelRef);
|
||||||
program.getGraph().remove(blockLabelRef);
|
procedureGraph.remove(blockLabelRef);
|
||||||
removePhiRValues(blockLabelRef, program);
|
removePhiRValues(blockLabelRef, program);
|
||||||
removedBlocks.add(blockLabelRef);
|
removedBlocks.add(blockLabelRef);
|
||||||
}
|
}
|
||||||
unusedProcedure.getScope().remove(unusedProcedure);
|
unusedProcedure.getScope().remove(unusedProcedure);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all referenced blocks in the entire program
|
|
||||||
*
|
|
||||||
* @return All blocks referenced
|
|
||||||
*/
|
|
||||||
private Set<LabelRef> getReferencedBlocks() {
|
|
||||||
Set<LabelRef> referencedBlocks = new LinkedHashSet<>();
|
|
||||||
List<Graph.Block> entryPointBlocks = getProgram().getEntryPointBlocks();
|
|
||||||
for(var entryPointBlock : entryPointBlocks) {
|
|
||||||
findReferencedBlocks(entryPointBlock, referencedBlocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
return referencedBlocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all PHI RValues in any phi-statements referencing the passed block
|
* Remove all PHI RValues in any phi-statements referencing the passed block
|
||||||
@ -143,6 +134,21 @@ public class Pass2EliminateUnusedBlocks extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all referenced blocks in the entire program
|
||||||
|
*
|
||||||
|
* @return All blocks referenced
|
||||||
|
*/
|
||||||
|
private Set<LabelRef> getReferencedBlocks() {
|
||||||
|
Set<LabelRef> referencedBlocks = new LinkedHashSet<>();
|
||||||
|
List<Graph.Block> entryPointBlocks = getProgram().getEntryPointBlocks();
|
||||||
|
for(var entryPointBlock : entryPointBlocks) {
|
||||||
|
findReferencedBlocks(entryPointBlock, referencedBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
return referencedBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all referenced block labels recursively
|
* Find all referenced block labels recursively
|
||||||
*
|
*
|
||||||
|
@ -31,10 +31,16 @@ public class Pass3PhiLifting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void perform() {
|
public void perform() {
|
||||||
Graph graph = program.getGraph();
|
for(var procedureCompilation : program.getProcedureCompilations()) {
|
||||||
|
upliftProcedure(procedureCompilation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void upliftProcedure(ProcedureCompilation procedureCompilation) {
|
||||||
|
final ControlFlowGraph graph = procedureCompilation.getGraph();
|
||||||
|
List<Graph.Block> liftedBlocks = new ArrayList<>(graph.getAllBlocks());
|
||||||
ProgramScope programScope = program.getScope();
|
ProgramScope programScope = program.getScope();
|
||||||
List<Graph.Block> blocks = graph.getAllBlocks();
|
ListIterator<Graph.Block> blocksIt = liftedBlocks.listIterator();
|
||||||
ListIterator<Graph.Block> blocksIt = blocks.listIterator();
|
|
||||||
while(blocksIt.hasNext()) {
|
while(blocksIt.hasNext()) {
|
||||||
Graph.Block block = blocksIt.next();
|
Graph.Block block = blocksIt.next();
|
||||||
// Maps old predecessors to new blocks created
|
// Maps old predecessors to new blocks created
|
||||||
@ -45,7 +51,11 @@ public class Pass3PhiLifting {
|
|||||||
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
|
||||||
if(!(phiRValue.getrValue() instanceof ConstantValue)) {
|
if(!(phiRValue.getrValue() instanceof ConstantValue)) {
|
||||||
LabelRef predecessorRef = phiRValue.getPredecessor();
|
LabelRef predecessorRef = phiRValue.getPredecessor();
|
||||||
Graph.Block predecessorBlock = graph.getBlock(predecessorRef);
|
Graph.Block predecessorBlock = getBlock(liftedBlocks, predecessorRef);
|
||||||
|
if(predecessorBlock==null) {
|
||||||
|
// Look for the predecessor in the entire graph
|
||||||
|
predecessorBlock = program.getGraph().getBlock(predecessorRef);
|
||||||
|
}
|
||||||
//VariableRef rValVarRef = (VariableRef) phiRValue.getrValue();
|
//VariableRef rValVarRef = (VariableRef) phiRValue.getrValue();
|
||||||
Variable newVar;
|
Variable newVar;
|
||||||
if(phiVariable.getVariable().isVersion()) {
|
if(phiVariable.getVariable().isVersion()) {
|
||||||
@ -88,7 +98,7 @@ public class Pass3PhiLifting {
|
|||||||
}
|
}
|
||||||
program.getLog().append("Added new block during phi lifting " + newBlock.getLabel() + "(between " + predecessorRef + " and " + block.getLabel() + ")");
|
program.getLog().append("Added new block during phi lifting " + newBlock.getLabel() + "(between " + predecessorRef + " and " + block.getLabel() + ")");
|
||||||
} else {
|
} else {
|
||||||
newBlock = graph.getBlock(newBlockRef);
|
newBlock = getBlock(liftedBlocks, newBlockRef);
|
||||||
}
|
}
|
||||||
List<Statement> newBlockStatements = newBlock.getStatements();
|
List<Statement> newBlockStatements = newBlock.getStatements();
|
||||||
newBlockStatements.add(newAssignment);
|
newBlockStatements.add(newAssignment);
|
||||||
@ -121,6 +131,14 @@ public class Pass3PhiLifting {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the procedure with the PHI-lifted blocks
|
||||||
|
procedureCompilation.setGraph(new ControlFlowGraph(liftedBlocks));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Graph.Block getBlock(List<Graph.Block> blocks, LabelRef blockRef) {
|
||||||
|
return blocks.stream().filter(block -> block.getLabel().equals(blockRef)).findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package dk.camelot64.kickc.passes;
|
package dk.camelot64.kickc.passes;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
import dk.camelot64.kickc.model.*;
|
||||||
import dk.camelot64.kickc.model.Graph;
|
|
||||||
import dk.camelot64.kickc.model.Program;
|
|
||||||
import dk.camelot64.kickc.model.symbols.Scope;
|
import dk.camelot64.kickc.model.symbols.Scope;
|
||||||
import dk.camelot64.kickc.model.values.LabelRef;
|
import dk.camelot64.kickc.model.values.LabelRef;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/** Plan the optimal sequence for the blocks of the control flow graph */
|
/** Plan the optimal sequence for the blocks of the control flow graph */
|
||||||
public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
|
public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
|
||||||
@ -62,7 +62,7 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
getGraph().setSequence(sequence);
|
setSequence(sequence);
|
||||||
|
|
||||||
if(getLog().isVerboseSequencePlan()) {
|
if(getLog().isVerboseSequencePlan()) {
|
||||||
StringBuilder entry = new StringBuilder();
|
StringBuilder entry = new StringBuilder();
|
||||||
@ -78,6 +78,21 @@ public class PassNBlockSequencePlanner extends Pass2SsaOptimization {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSequence(List<LabelRef> sequence) {
|
||||||
|
if(sequence.size() != getGraph().getAllBlocks().size()) {
|
||||||
|
throw new CompileError("ERROR! Sequence does not contain all blocks from the program. Sequence: " + sequence.size() + " Blocks: " + getGraph().getAllBlocks().size());
|
||||||
|
}
|
||||||
|
for(var procedureCompilation : getProgram().getProcedureCompilations()) {
|
||||||
|
final ControlFlowGraph procedureGraph = procedureCompilation.getGraph();
|
||||||
|
final List<LabelRef> procedureLabels = procedureGraph.getAllBlocks().stream().map(Graph.Block::getLabel).toList();
|
||||||
|
final List<Graph.Block> procedureSequence = sequence.stream().filter(procedureLabels::contains).map(procedureGraph::getBlock).toList();
|
||||||
|
if(procedureSequence.size() != procedureGraph.getAllBlocks().size()) {
|
||||||
|
throw new CompileError("ERROR! Sequence does not contain all blocks for "+procedureCompilation.getProcedureRef()+". Sequence: " + procedureSequence.size() + " Blocks: " + procedureGraph.getAllBlocks().size());
|
||||||
|
}
|
||||||
|
procedureCompilation.setGraph(new ControlFlowGraph(procedureSequence));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pushTodo(Graph.Block block) {
|
void pushTodo(Graph.Block block) {
|
||||||
LabelRef blockRef = block.getLabel();
|
LabelRef blockRef = block.getLabel();
|
||||||
Scope blockScope = getProgramScope().getSymbol(blockRef).getScope();
|
Scope blockScope = getProgramScope().getSymbol(blockRef).getScope();
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package dk.camelot64.kickc.passes;
|
package dk.camelot64.kickc.passes;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.GraphBaseVisitor;
|
import dk.camelot64.kickc.model.*;
|
||||||
import dk.camelot64.kickc.model.Graph;
|
|
||||||
import dk.camelot64.kickc.model.Program;
|
|
||||||
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||||
import dk.camelot64.kickc.model.symbols.Label;
|
import dk.camelot64.kickc.model.symbols.Label;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Scope;
|
||||||
import dk.camelot64.kickc.model.values.LabelRef;
|
import dk.camelot64.kickc.model.values.LabelRef;
|
||||||
import dk.camelot64.kickc.model.values.RValue;
|
import dk.camelot64.kickc.model.values.RValue;
|
||||||
|
|
||||||
@ -100,10 +100,19 @@ public class PassNCullEmptyBlocks extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
replaceLabels(predecessor, replace);
|
replaceLabels(predecessor, replace);
|
||||||
}
|
}
|
||||||
getGraph().getAllBlocks().remove(removeBlock);
|
|
||||||
|
|
||||||
|
|
||||||
LabelRef removeBlockLabelRef = removeBlock.getLabel();
|
LabelRef removeBlockLabelRef = removeBlock.getLabel();
|
||||||
Label removeBlockLabel = getProgramScope().getLabel(removeBlockLabelRef);
|
Label removeBlockLabel = getProgramScope().getLabel(removeBlockLabelRef);
|
||||||
removeBlockLabel.getScope().remove(removeBlockLabel);
|
final Scope removeBlockScope = removeBlockLabel.getScope();
|
||||||
|
final Procedure procedure = removeBlockScope.getProcedure();
|
||||||
|
final ProcedureCompilation procedureCompilation = getProgram().getProcedureCompilation(procedure.getRef());
|
||||||
|
final List<Graph.Block> updatedBlocks = new ArrayList<>(procedureCompilation.getGraph().getAllBlocks());
|
||||||
|
updatedBlocks.removeIf(block -> block.getLabel().equals(removeBlockLabelRef));
|
||||||
|
procedureCompilation.setGraph(new ControlFlowGraph(updatedBlocks));
|
||||||
|
|
||||||
|
removeBlockScope.remove(removeBlockLabel);
|
||||||
if(!pass1)
|
if(!pass1)
|
||||||
getLog().append("Culled Empty Block " + removeBlockLabel.toString(getProgram()));
|
getLog().append("Culled Empty Block " + removeBlockLabel.toString(getProgram()));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user