mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-09 03:30:40 +00:00
Changed control flow graph block collection to a modifiable list.
This commit is contained in:
parent
3879ac83b0
commit
b15a88f27e
@ -140,6 +140,8 @@ public class Compiler {
|
||||
new Pass1ModifiedVarsAnalysis(program).execute();
|
||||
getLog().append(program.getProcedureModifiedVars().toString(program));
|
||||
|
||||
new Pass1ProcedureInline(program).execute();
|
||||
|
||||
new Pass1ProcedureCallParameters(program).generate();
|
||||
//getLog().append("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL");
|
||||
//getLog().append(program.getGraph().toString(program));
|
||||
|
@ -15,7 +15,7 @@ import java.util.*;
|
||||
*/
|
||||
public class ControlFlowGraph {
|
||||
|
||||
private Map<LabelRef, ControlFlowBlock> blocks;
|
||||
private List<ControlFlowBlock> blocks;
|
||||
private LabelRef firstBlockRef;
|
||||
|
||||
/**
|
||||
@ -23,37 +23,41 @@ public class ControlFlowGraph {
|
||||
*/
|
||||
private List<LabelRef> sequence;
|
||||
|
||||
public ControlFlowGraph(Map<LabelRef, ControlFlowBlock> blocks, LabelRef firstBlockRef) {
|
||||
public ControlFlowGraph(List<ControlFlowBlock> blocks, LabelRef firstBlockRef) {
|
||||
this.blocks = blocks;
|
||||
this.firstBlockRef = firstBlockRef;
|
||||
}
|
||||
|
||||
public ControlFlowBlock getBlock(LabelRef symbol) {
|
||||
return blocks.get(symbol);
|
||||
for(ControlFlowBlock block : blocks) {
|
||||
if(block.getLabel().equals(symbol)) {
|
||||
return block;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addBlock(ControlFlowBlock block) {
|
||||
blocks.put(block.getLabel(), block);
|
||||
blocks.add(block);
|
||||
}
|
||||
|
||||
public ControlFlowBlock getFirstBlock() {
|
||||
return getBlock(firstBlockRef);
|
||||
}
|
||||
|
||||
public Collection<ControlFlowBlock> getAllBlocks() {
|
||||
if(sequence != null) {
|
||||
ArrayList<ControlFlowBlock> blocks = new ArrayList<>();
|
||||
for(LabelRef labelRef : sequence) {
|
||||
blocks.add(getBlock(labelRef));
|
||||
}
|
||||
public List<ControlFlowBlock> getAllBlocks() {
|
||||
return blocks;
|
||||
} else {
|
||||
return blocks.values();
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(LabelRef label) {
|
||||
blocks.remove(label);
|
||||
ListIterator<ControlFlowBlock> blocksIt = blocks.listIterator();
|
||||
while(blocksIt.hasNext()) {
|
||||
ControlFlowBlock block = blocksIt.next();
|
||||
if(block.getLabel().equals(label)) {
|
||||
blocksIt.remove();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,7 +109,7 @@ public class ControlFlowGraph {
|
||||
|
||||
public ControlFlowBlock getDefaultSuccessor(ControlFlowBlock block) {
|
||||
if(block.getDefaultSuccessor() != null) {
|
||||
return blocks.get(block.getDefaultSuccessor());
|
||||
return getBlock(block.getDefaultSuccessor());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -113,7 +117,7 @@ public class ControlFlowGraph {
|
||||
|
||||
public ControlFlowBlock getCallSuccessor(ControlFlowBlock block) {
|
||||
if(block.getCallSuccessor() != null) {
|
||||
return blocks.get(block.getCallSuccessor());
|
||||
return getBlock(block.getCallSuccessor());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -121,7 +125,7 @@ public class ControlFlowGraph {
|
||||
|
||||
public ControlFlowBlock getConditionalSuccessor(ControlFlowBlock block) {
|
||||
if(block.getConditionalSuccessor() != null) {
|
||||
return blocks.get(block.getConditionalSuccessor());
|
||||
return getBlock(block.getConditionalSuccessor());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -150,7 +154,15 @@ public class ControlFlowGraph {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public ControlFlowBlock getMainBlock() {
|
||||
|
@ -1,13 +1,13 @@
|
||||
package dk.camelot64.kickc.model;
|
||||
|
||||
import dk.camelot64.kickc.model.operators.Operator;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -23,7 +23,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
|
||||
/**
|
||||
* The copied blocks.
|
||||
*/
|
||||
private LinkedHashMap<LabelRef, ControlFlowBlock> copyBlockMap;
|
||||
private List<ControlFlowBlock> copyBlockList;
|
||||
|
||||
/**
|
||||
* The current block being copied.
|
||||
@ -39,15 +39,14 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
|
||||
public ControlFlowGraph visitGraph(ControlFlowGraph origGraph) {
|
||||
this.origGraph = origGraph;
|
||||
// Copy all blocks
|
||||
this.copyBlockMap = new LinkedHashMap<>();
|
||||
this.copyBlockList = new ArrayList<>();
|
||||
for(ControlFlowBlock origBlock : origGraph.getAllBlocks()) {
|
||||
ControlFlowBlock copyBlock = visitBlock(origBlock);
|
||||
if(copyBlock != null) {
|
||||
copyBlockMap.put(copyBlock.getLabel(), copyBlock);
|
||||
copyBlockList.add(copyBlock);
|
||||
}
|
||||
}
|
||||
ControlFlowBlock copyFirstBlock = copyBlockMap.get(origGraph.getFirstBlock().getLabel());
|
||||
ControlFlowGraph copyGraph = new ControlFlowGraph(copyBlockMap, copyFirstBlock.getLabel());
|
||||
ControlFlowGraph copyGraph = new ControlFlowGraph(copyBlockList, origGraph.getFirstBlock().getLabel());
|
||||
return copyGraph;
|
||||
}
|
||||
|
||||
@ -101,7 +100,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Obj
|
||||
protected ControlFlowBlock splitCurrentBlock(LabelRef label) {
|
||||
ControlFlowBlock newBlock = new ControlFlowBlock(label, origBlock.getScope());
|
||||
this.copyBlock.setDefaultSuccessor(newBlock.getLabel());
|
||||
this.copyBlockMap.put(this.copyBlock.getLabel(), this.copyBlock);
|
||||
this.copyBlockList.add(this.copyBlock);
|
||||
this.copyBlock = newBlock;
|
||||
return newBlock;
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.ControlFlowGraph;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.StatementSequence;
|
||||
import dk.camelot64.kickc.model.statements.*;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
@ -8,14 +11,14 @@ import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/** Pass that generates a control flow graph for the program */
|
||||
public class Pass1GenerateControlFlowGraph extends Pass1Base {
|
||||
|
||||
private Map<LabelRef, ControlFlowBlock> blocks;
|
||||
private List<ControlFlowBlock> blocks;
|
||||
|
||||
public Pass1GenerateControlFlowGraph(Program program) {
|
||||
super(program);
|
||||
@ -23,7 +26,7 @@ public class Pass1GenerateControlFlowGraph extends Pass1Base {
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
this.blocks = new LinkedHashMap<>();
|
||||
this.blocks = new ArrayList<>();
|
||||
ProgramScope scope = getScope();
|
||||
StatementSequence sequence = getProgram().getStatementSequence();
|
||||
ControlFlowBlock firstBlock = getOrCreateBlock(scope.addLabel(SymbolRef.BEGIN_BLOCK_NAME).getRef(), ScopeRef.ROOT);
|
||||
@ -92,11 +95,13 @@ public class Pass1GenerateControlFlowGraph extends Pass1Base {
|
||||
}
|
||||
|
||||
private ControlFlowBlock getOrCreateBlock(LabelRef label, ScopeRef scope) {
|
||||
ControlFlowBlock block = blocks.get(label);
|
||||
if(block == null) {
|
||||
block = new ControlFlowBlock(label, scope);
|
||||
blocks.put(block.getLabel(), block);
|
||||
for(ControlFlowBlock block : blocks) {
|
||||
if(block.getLabel().equals(label)) {
|
||||
return block;
|
||||
}
|
||||
}
|
||||
ControlFlowBlock block = new ControlFlowBlock(label, scope);
|
||||
blocks.add(block);
|
||||
return block;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,117 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.*;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementReturn;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
import dk.camelot64.kickc.model.values.VariableRef;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
|
||||
/** Pass that modifies a control flow graph to inline any procedures declared as inline */
|
||||
public class Pass1ProcedureInline extends Pass1Base {
|
||||
|
||||
public Pass1ProcedureInline(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
List<ControlFlowBlock> allBlocks = getGraph().getAllBlocks();
|
||||
for(ControlFlowBlock block : allBlocks) {
|
||||
List<Statement> blockStatements = block.getStatements();
|
||||
ListIterator<Statement> statementsIt = blockStatements.listIterator();
|
||||
while(statementsIt.hasNext()) {
|
||||
Statement statement = statementsIt.next();
|
||||
if(statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
ProcedureRef procedureRef = call.getProcedure();
|
||||
Procedure procedure = getScope().getProcedure(procedureRef);
|
||||
if(procedure.isDeclaredInline()) {
|
||||
// Generate parameter assignments
|
||||
// Copy all procedure blocks
|
||||
// Generate return assignment
|
||||
throw new CompileError("Inline functions not implemented!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
public StatementCall visitCall(StatementCall origCall) {
|
||||
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
|
||||
// Generate parameter passing assignments
|
||||
ProcedureRef procedureRef = origCall.getProcedure();
|
||||
Procedure procedure = getScope().getProcedure(procedureRef);
|
||||
List<Variable> parameterDecls = procedure.getParameters();
|
||||
List<RValue> parameterValues = origCall.getParameters();
|
||||
for(int i = 0; i < parameterDecls.size(); i++) {
|
||||
Variable parameterDecl = parameterDecls.get(i);
|
||||
RValue parameterValue = parameterValues.get(i);
|
||||
addStatementToCurrentBlock(new StatementAssignment(parameterDecl.getRef(), parameterValue));
|
||||
}
|
||||
String procedureName = origCall.getProcedureName();
|
||||
Variable procReturnVar = procedure.getVariable("return");
|
||||
VariableRef procReturnVarRef = null;
|
||||
if(procReturnVar != null) {
|
||||
procReturnVarRef = procReturnVar.getRef();
|
||||
}
|
||||
StatementCall copyCall = new StatementCall(procReturnVarRef, procedureName, null);
|
||||
copyCall.setParametersByAssignment(true);
|
||||
copyCall.setProcedure(procedureRef);
|
||||
addStatementToCurrentBlock(copyCall);
|
||||
getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef());
|
||||
Symbol currentBlockSymbol = getScope().getSymbol(getCurrentBlock().getLabel());
|
||||
Scope currentBlockScope;
|
||||
if(currentBlockSymbol instanceof Procedure) {
|
||||
currentBlockScope = (Scope) currentBlockSymbol;
|
||||
} else {
|
||||
currentBlockScope = currentBlockSymbol.getScope();
|
||||
}
|
||||
splitCurrentBlock(currentBlockScope.addLabelIntermediate().getRef());
|
||||
if(!SymbolType.VOID.equals(procedure.getReturnType()) && origCall.getlValue() != null) {
|
||||
addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef));
|
||||
} else {
|
||||
// No return type. Remove variable receiving the result.
|
||||
LValue lValue = origCall.getlValue();
|
||||
if(lValue instanceof VariableRef) {
|
||||
VariableRef lValueRef = (VariableRef) lValue;
|
||||
Variable lValueVar = getScope().getVariable(lValueRef);
|
||||
lValueVar.getScope().remove(lValueVar);
|
||||
}
|
||||
}
|
||||
// Add self-assignments for all variables modified in the procedure
|
||||
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
|
||||
for(VariableRef modifiedVar : modifiedVars) {
|
||||
addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatementReturn visitReturn(StatementReturn origReturn) {
|
||||
ControlFlowBlock currentBlock = getCurrentBlock();
|
||||
String currentProcName = currentBlock.getLabel().getScopeNames();
|
||||
Procedure procedure = program.getScope().getProcedure(currentProcName);
|
||||
// Add self-assignments for all variables modified in the procedure
|
||||
Set<VariableRef> modifiedVars = program.getProcedureModifiedVars().getModifiedVars(procedure.getRef());
|
||||
for(VariableRef modifiedVar : modifiedVars) {
|
||||
addStatementToCurrentBlock(new StatementAssignment(modifiedVar, modifiedVar));
|
||||
}
|
||||
return super.visitReturn(origReturn);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
@ -9,10 +9,7 @@ import dk.camelot64.kickc.model.statements.StatementPhiBlock;
|
||||
import dk.camelot64.kickc.model.symbols.*;
|
||||
import dk.camelot64.kickc.model.values.LabelRef;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Perform PhiLifting to greatly reduce overlapping of alive intervals for variables.
|
||||
@ -35,8 +32,10 @@ public class Pass3PhiLifting {
|
||||
public void perform() {
|
||||
ControlFlowGraph graph = program.getGraph();
|
||||
ProgramScope programScope = program.getScope();
|
||||
Collection<ControlFlowBlock> blocks = graph.getAllBlocks();
|
||||
for(ControlFlowBlock block : blocks) {
|
||||
List<ControlFlowBlock> blocks = graph.getAllBlocks();
|
||||
ListIterator<ControlFlowBlock> blocksIt = blocks.listIterator();
|
||||
while(blocksIt.hasNext()) {
|
||||
ControlFlowBlock block = blocksIt.next();
|
||||
// Maps old predecessors to new blocks created
|
||||
Map<LabelRef, LabelRef> newBlocks = new HashMap<>();
|
||||
if(block.hasPhiBlock()) {
|
||||
@ -73,7 +72,7 @@ public class Pass3PhiLifting {
|
||||
Scope currentScope = programScope.getSymbol(currentBlockLabel).getScope();
|
||||
Label newBlockLabel = currentScope.addLabelIntermediate();
|
||||
newBlock = new ControlFlowBlock(newBlockLabel.getRef(), currentScope.getRef());
|
||||
graph.addBlock(newBlock);
|
||||
blocksIt.add(newBlock);
|
||||
newBlock.setDefaultSuccessor(block.getLabel());
|
||||
newBlocks.put(predecessorRef, newBlock.getLabel());
|
||||
StatementConditionalJump previousConditionalJump = (StatementConditionalJump) lastPredecessorStatement;
|
||||
|
Loading…
x
Reference in New Issue
Block a user