1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-23 09:33:30 +00:00

Refactoring control flow graph to enable proc calls. Still need to handle return values properly.

This commit is contained in:
jespergravgaard 2017-06-11 23:36:05 +02:00
parent 12bff79433
commit 3b2cc5cde1
17 changed files with 490 additions and 105 deletions

7
.idea/dictionaries/jespergravgaard.xml generated Normal file
View File

@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="jespergravgaard">
<words>
<w>unversioned</w>
</words>
</dictionary>
</component>

View File

@ -4,23 +4,23 @@ import java.util.ArrayList;
import java.util.List;
/** A named/labelled sequence of SSA statements connected to other basic blocks.
* The connections defines the control flow of the program. */
* 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 {
private Label label;
private List<ControlFlowBlock> predecessors;
private List<Statement> statements;
private ControlFlowBlock defaultSuccessor;
private Label defaultSuccessor;
private ControlFlowBlock conditionalSuccessor;
private Label conditionalSuccessor;
private Label callSuccessor;
public ControlFlowBlock(Label label) {
this.label = label;
this.statements = new ArrayList<>();
this.predecessors = new ArrayList<>();
this.defaultSuccessor = null;
this.conditionalSuccessor = null;
}
@ -33,32 +33,28 @@ public class ControlFlowBlock {
this.statements.add(statement);
}
public void addPredecessor(ControlFlowBlock block) {
this.predecessors.add(block);
}
public void setDefaultSuccessor(ControlFlowBlock defaultSuccessor) {
public void setDefaultSuccessor(Label defaultSuccessor) {
this.defaultSuccessor = defaultSuccessor;
}
public ControlFlowBlock getDefaultSuccessor() {
public Label getDefaultSuccessor() {
return defaultSuccessor;
}
public ControlFlowBlock getConditionalSuccessor() {
public Label getConditionalSuccessor() {
return conditionalSuccessor;
}
public List<ControlFlowBlock> getPredecessors() {
return predecessors;
}
public void setConditionalSuccessor(ControlFlowBlock conditionalSuccessor) {
public void setConditionalSuccessor(Label conditionalSuccessor) {
this.conditionalSuccessor = conditionalSuccessor;
}
public void removePredecessor(ControlFlowBlock block) {
predecessors.remove(block);
public Label getCallSuccessor() {
return callSuccessor;
}
public void setCallSuccessor(Label callSuccessor) {
this.callSuccessor = callSuccessor;
}
public List<Statement> getStatements() {
@ -71,13 +67,22 @@ public class ControlFlowBlock {
@Override
public String toString() {
return toString(null);
}
public String toString(ControlFlowGraph graph) {
StringBuffer out = new StringBuffer();
out.append(label.getLocalName() + ":" );
if(predecessors.size()>0) {
out.append(" from");
for (ControlFlowBlock predecessor : predecessors) {
out.append(" " + predecessor.getLabel().getLocalName());
out.append(" from");
if(graph!=null) {
List<ControlFlowBlock> predecessors = graph.getPredecessors(this);
if(predecessors.size()>0) {
for (ControlFlowBlock predecessor : predecessors) {
out.append(" " + predecessor.getLabel().getLocalName());
}
}
} else {
out.append(" @UNKNOWN");
}
out.append("\n");
for (Statement statement : statements) {
@ -85,7 +90,7 @@ public class ControlFlowBlock {
}
if(defaultSuccessor!=null) {
out.append(" to:");
out.append(defaultSuccessor.getLabel().getLocalName());
out.append(defaultSuccessor.getLocalName());
out.append("\n");
}
return out.toString();
@ -112,4 +117,5 @@ public class ControlFlowBlock {
}
return false;
}
}

View File

@ -1,6 +1,8 @@
package dk.camelot64.kickc.icl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/** The control flow graph of the program.
@ -28,7 +30,7 @@ public class ControlFlowGraph {
public String toString() {
StringBuffer out = new StringBuffer();
for (ControlFlowBlock block : blocks.values()) {
out.append(block.toString());
out.append(block.toString(this));
}
return out.toString();
}
@ -59,4 +61,27 @@ public class ControlFlowGraph {
return null;
}
public ControlFlowBlock getDefaultSuccessor(ControlFlowBlock block) {
if(block.getDefaultSuccessor()!=null) {
return blocks.get(block.getDefaultSuccessor());
} 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);
}
}
return predecessorBlocks;
}
}

View File

@ -20,7 +20,7 @@ public class ControlFlowGraphBaseVisitor<T> {
return null;
}
public T visitStatement(Statement statement) {
public Object visitStatement(Statement statement) {
if(statement instanceof StatementAssignment) {
return visitAssignment((StatementAssignment) statement);
} else if(statement instanceof StatementConditionalJump) {
@ -31,11 +31,31 @@ public class ControlFlowGraphBaseVisitor<T> {
return visitJumpTarget((StatementLabel) statement);
} else if(statement instanceof StatementPhi) {
return visitPhi((StatementPhi) statement);
} else if(statement instanceof StatementCallLValue) {
return visitCallLValue((StatementCallLValue) statement);
} else if(statement instanceof StatementReturn) {
return visitReturn((StatementReturn) statement);
} else if(statement instanceof StatementProcedureBegin) {
return visitProcedureBegin((StatementProcedureBegin) statement);
} else if(statement instanceof StatementProcedureEnd) {
return visitProcedureEnd((StatementProcedureEnd) statement);
} else {
throw new RuntimeException("Unhandled statement type "+statement);
}
}
public T visitProcedureBegin(StatementProcedureBegin statement) {
return null;
}
public T visitProcedureEnd(StatementProcedureEnd statement) {
return null;
}
public T visitReturn(StatementReturn aReturn) {
return null;
}
public T visitAssignment(StatementAssignment assignment) {
return null;
}
@ -56,4 +76,8 @@ public class ControlFlowGraphBaseVisitor<T> {
return null;
}
public T visitCallLValue(StatementCallLValue callLValue) {
return null;
}
}

View File

@ -0,0 +1,180 @@
package dk.camelot64.kickc.icl;
import java.util.HashMap;
import java.util.List;
/**
* A visitor that copies a complete control flow graph. contains visitor-methods usable for modifying the copy at any point
*/
public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor<Object> {
/**
* The origGraph graph.
*/
private ControlFlowGraph origGraph;
/**
* The copied blocks.
*/
private HashMap<Symbol, ControlFlowBlock> copyBlockMap;
/**
* The current block being copied.
*/
private ControlFlowBlock origBlock;
/**
* The current block where statements are generated into.
*/
private ControlFlowBlock copyBlock;
@Override
public ControlFlowGraph visitGraph(ControlFlowGraph origGraph) {
this.origGraph = origGraph;
// Copy all blocks
this.copyBlockMap = new HashMap<>();
for (ControlFlowBlock origBlock : origGraph.getAllBlocks()) {
ControlFlowBlock copyBlock = visitBlock(origBlock);
if (copyBlock != null) {
copyBlockMap.put(copyBlock.getLabel(), copyBlock);
}
}
ControlFlowBlock copyFirstBlock = copyBlockMap.get(origGraph.getFirstBlock().getLabel());
ControlFlowGraph copyGraph = new ControlFlowGraph(copyBlockMap, copyFirstBlock);
return copyGraph;
}
@Override
public ControlFlowBlock visitBlock(ControlFlowBlock origBlock) {
Label label = origBlock.getLabel();
ControlFlowBlock copyBlock = new ControlFlowBlock(label);
this.origBlock = origBlock;
this.copyBlock = copyBlock;
// Handle statements
List<Statement> origBlockStatements = origBlock.getStatements();
for (Statement origStatement : origBlockStatements) {
Statement copyStatement = visitStatement(origStatement);
if (copyStatement != null) {
this.copyBlock.addStatement(copyStatement);
}
}
// Handle successors
if (origBlock.getDefaultSuccessor() != null) {
this.copyBlock.setDefaultSuccessor(origBlock.getDefaultSuccessor());
}
if (origBlock.getConditionalSuccessor() != null) {
this.copyBlock.setConditionalSuccessor(origBlock.getConditionalSuccessor());
}
if (origBlock.getCallSuccessor() != null) {
this.copyBlock.setCallSuccessor(origBlock.getCallSuccessor());
}
ControlFlowBlock result = this.copyBlock;
this.origBlock = null;
this.copyBlock = null;
return result;
}
/**
* Adds an extra statement to the current block at the current generated position.
* The new statement is added beofre the copy currently being generated.
*
* @param statement The statement to add
*/
protected void addStatementToCurrentBlock(Statement statement) {
this.copyBlock.addStatement(statement);
}
/**
* Splits the current block into two blocks in the generated graph.
* The new block will have the current block as predecessor and current the block will have the new block as default successor.
*
* @param label The label to use for the new block
* @return The new block.
*/
protected ControlFlowBlock splitCurrentBlock(Label label) {
ControlFlowBlock newBlock = new ControlFlowBlock(label);
this.copyBlock.setDefaultSuccessor(newBlock.getLabel());
this.copyBlockMap.put(this.copyBlock.getLabel(), this.copyBlock);
this.copyBlock = newBlock;
return newBlock;
}
/**
* Get the block currently being generated.
*
* @return The current block being generated into
*/
public ControlFlowBlock getCurrentBlock() {
return copyBlock;
}
@Override
public Statement visitStatement(Statement statement) {
return (Statement) super.visitStatement(statement);
}
@Override
public StatementPhi visitPhi(StatementPhi phi) {
VariableVersion lValue = phi.getLValue();
StatementPhi copyPhi = new StatementPhi(lValue);
for (StatementPhi.PreviousSymbol origPreviousVersion : phi.getPreviousVersions()) {
RValue rValue = origPreviousVersion.getRValue();
Label block = origPreviousVersion.getBlock();
copyPhi.addPreviousVersion(block, rValue);
}
return copyPhi;
}
@Override
public StatementAssignment visitAssignment(StatementAssignment origAssignment) {
LValue lValue = origAssignment.getLValue();
RValue rValue1 = origAssignment.getRValue1();
Operator operator = origAssignment.getOperator();
RValue rValue2 = origAssignment.getRValue2();
return new StatementAssignment(lValue, rValue1, operator, rValue2);
}
@Override
public StatementConditionalJump visitConditionalJump(StatementConditionalJump origConditionalJump) {
RValue rValue1 = origConditionalJump.getRValue1();
Operator operator = origConditionalJump.getOperator();
RValue rValue2 = origConditionalJump.getRValue2();
Label destination = origConditionalJump.getDestination();
return new StatementConditionalJump(rValue1, operator, rValue2, destination);
}
@Override
public StatementJump visitJump(StatementJump origJump) {
Label destination = origJump.getDestination();
return new StatementJump(destination);
}
@Override
public StatementLabel visitJumpTarget(StatementLabel origJump) {
Label label = origJump.getLabel();
return new StatementLabel(label);
}
@Override
public StatementCallLValue visitCallLValue(StatementCallLValue callLValue) {
LValue lValue = callLValue.getLValue();
String procedureName = callLValue.getProcedureName();
List<RValue> parameters = callLValue.getParameters();
return new StatementCallLValue(lValue, procedureName, parameters);
}
@Override
public StatementProcedureBegin visitProcedureBegin(StatementProcedureBegin origProcedureBegin) {
return new StatementProcedureBegin(origProcedureBegin.getProcedure());
}
@Override
public StatementProcedureEnd visitProcedureEnd(StatementProcedureEnd origProcedureEnd) {
return new StatementProcedureEnd(origProcedureEnd.getProcedure());
}
@Override
public StatementReturn visitReturn(StatementReturn origReturn) {
return new StatementReturn(origReturn.getValue());
}
}

View File

@ -28,15 +28,13 @@ public class Pass1GenerateControlFlowGraph {
if(statement instanceof StatementLabel) {
StatementLabel statementLabel = (StatementLabel) statement;
ControlFlowBlock nextBlock = getOrCreateBlock(statementLabel.getLabel());
currentBlock.setDefaultSuccessor(nextBlock);
nextBlock.addPredecessor(currentBlock);
currentBlock.setDefaultSuccessor(nextBlock.getLabel());
blockStack.pop();
blockStack.push(nextBlock);
} else if(statement instanceof StatementJump) {
StatementJump statementJump = (StatementJump) statement;
ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination());
currentBlock.setDefaultSuccessor(jmpBlock);
jmpBlock.addPredecessor(currentBlock);
currentBlock.setDefaultSuccessor(jmpBlock.getLabel());
ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate());
blockStack.pop();
blockStack.push(nextBlock);
@ -45,28 +43,30 @@ public class Pass1GenerateControlFlowGraph {
StatementConditionalJump statementConditionalJump = (StatementConditionalJump) statement;
ControlFlowBlock jmpBlock = getOrCreateBlock(statementConditionalJump.getDestination());
ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate());
currentBlock.setDefaultSuccessor(nextBlock);
currentBlock.setConditionalSuccessor(jmpBlock);
nextBlock.addPredecessor(currentBlock);
jmpBlock.addPredecessor(currentBlock);
currentBlock.setDefaultSuccessor(nextBlock.getLabel());
currentBlock.setConditionalSuccessor(jmpBlock.getLabel());
blockStack.pop();
blockStack.push(nextBlock);
} else if(statement instanceof StatementProcedureBegin) {
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
StatementProcedureBegin procedure = (StatementProcedureBegin) statement;
procedure.setStrategy(StatementProcedureBegin.Strategy.PASS_BY_REGISTER);
Label procedureLabel = procedure.getProcedure().getLabel();
StatementProcedureBegin procedureBegin = (StatementProcedureBegin) statement;
procedureBegin.setStrategy(StatementProcedureBegin.Strategy.PASS_BY_REGISTER);
Label procedureLabel = procedureBegin.getProcedure().getLabel();
ControlFlowBlock procBlock = getOrCreateBlock(procedureLabel);
blockStack.push(procBlock);
} else if(statement instanceof StatementProcedureEnd) {
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
currentBlock.setDefaultSuccessor(new ControlFlowBlock(new Label("@RETURN", scope, false)));
currentBlock.setDefaultSuccessor(new Label("@RETURN", scope, false));
ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate());
blockStack.pop();
ControlFlowBlock prevBlock = blockStack.pop();
prevBlock.setDefaultSuccessor(nextBlock);
nextBlock.addPredecessor(prevBlock);
ControlFlowBlock prevBlock = blockStack.pop();
prevBlock.setDefaultSuccessor(nextBlock.getLabel());
blockStack.push(nextBlock);
} else if(statement instanceof StatementReturn) {
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
StatementReturn aReturn = (StatementReturn) statement;
currentBlock.addStatement(aReturn);
// TODO: Make all returns exit through the same exit-block!
} else {
currentBlock.addStatement(statement);
}

View File

@ -28,7 +28,9 @@ public class Pass1GenerateSingleStaticAssignmentForm {
} while (!done);
}
/** Version all non-versioned non-intermediary being assigned a value. */
/**
* Version all non-versioned non-intermediary being assigned a value.
*/
private void versionAllAssignments() {
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) {
@ -41,12 +43,23 @@ public class Pass1GenerateSingleStaticAssignmentForm {
VariableVersion version = symbols.createVersion(assignedSymbol);
assignment.setLValue(version);
}
} else if(statement instanceof StatementCallLValue) {
StatementCallLValue call = (StatementCallLValue) statement;
LValue lValue = call.getLValue();
if (lValue instanceof VariableUnversioned) {
// Assignment to a non-versioned non-intermediary variable
VariableUnversioned assignedSymbol = (VariableUnversioned) lValue;
VariableVersion version = symbols.createVersion(assignedSymbol);
call.setLValue(version);
}
}
}
}
}
/** Version all uses of non-versioned non-intermediary variables */
/**
* Version all uses of non-versioned non-intermediary variables
*/
private void versionAllUses() {
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
// Newest version of variables in the block.
@ -105,9 +118,10 @@ public class Pass1GenerateSingleStaticAssignmentForm {
/**
* Find and return the latest version of an rValue (if it is a non-versioned symbol).
* If a version is needed and no version is found a new version is created as a phi-function.
* @param rValue The rValue to examine
*
* @param rValue The rValue to examine
* @param blockVersions The current version defined in the block for each symbol.
* @param blockNewPhis New versions to be created as phi-functions. Modified if a new phi-function needs to be created.
* @param blockNewPhis New versions to be created as phi-functions. Modified if a new phi-function needs to be created.
* @return Null if the rValue does not need versioning. The versioned symbol to use if it does.
*/
private VariableVersion findOrCreateVersion(
@ -132,12 +146,14 @@ public class Pass1GenerateSingleStaticAssignmentForm {
return version;
}
/** Look through all new phi-functions and fill out their parameters.
/**
* Look through all new phi-functions and fill out their parameters.
*
* @return true if all phis were completely filled out.
* false if new phis were added, meaning another iteration is needed.
* */
*/
private boolean completePhiFunctions() {
Map<ControlFlowBlock, Map<VariableUnversioned, VariableVersion>> newPhis = new HashMap<>();
Map<Label, Map<VariableUnversioned, VariableVersion>> newPhis = new HashMap<>();
Map<Label, Map<VariableUnversioned, VariableVersion>> symbolMap = buildSymbolMap();
for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) {
@ -146,35 +162,36 @@ public class Pass1GenerateSingleStaticAssignmentForm {
if (phi.getPreviousVersions().isEmpty()) {
VariableVersion versioned = phi.getLValue();
VariableUnversioned unversioned = versioned.getVersionOf();
for (ControlFlowBlock predecessor : block.getPredecessors()) {
Map<VariableUnversioned, VariableVersion> predecessorMap = symbolMap.get(predecessor.getLabel());
for (ControlFlowBlock predecessor : controlFlowGraph.getPredecessors(block)) {
Label predecessorLabel = predecessor.getLabel();
Map<VariableUnversioned, VariableVersion> predecessorMap = symbolMap.get(predecessorLabel);
VariableVersion previousSymbol = null;
if (predecessorMap != null) {
previousSymbol = predecessorMap.get(unversioned);
}
if (previousSymbol == null) {
// No previous symbol found in predecessor block. Look in new phi functions.
Map<VariableUnversioned, VariableVersion> predecessorNewPhis = newPhis.get(predecessor);
if (predecessorNewPhis == null) {
predecessorNewPhis = new HashMap<>();
newPhis.put(predecessor, predecessorNewPhis);
}
previousSymbol = predecessorNewPhis.get(unversioned);
if (previousSymbol == null) {
// No previous symbol found in predecessor block. Add a new phi function to the predecessor.
previousSymbol = symbols.createVersion(unversioned);
predecessorNewPhis.put(unversioned, previousSymbol);
}
if (previousSymbol == null) {
// No previous symbol found in predecessor block. Look in new phi functions.
Map<VariableUnversioned, VariableVersion> predecessorNewPhis = newPhis.get(predecessorLabel);
if (predecessorNewPhis == null) {
predecessorNewPhis = new HashMap<>();
newPhis.put(predecessorLabel, predecessorNewPhis);
}
previousSymbol = predecessorNewPhis.get(unversioned);
if (previousSymbol == null) {
// No previous symbol found in predecessor block. Add a new phi function to the predecessor.
previousSymbol = symbols.createVersion(unversioned);
predecessorNewPhis.put(unversioned, previousSymbol);
}
phi.addPreviousVersion(predecessor, previousSymbol);
}
phi.addPreviousVersion(predecessorLabel, previousSymbol);
}
}
}
}
}
// Ads new phi functions to blocks
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
Map<VariableUnversioned, VariableVersion> blockNewPhis = newPhis.get(block);
Map<VariableUnversioned, VariableVersion> blockNewPhis = newPhis.get(block.getLabel());
if (blockNewPhis != null) {
for (VariableUnversioned symbol : blockNewPhis.keySet()) {
block.addPhiStatement(blockNewPhis.get(symbol));
@ -217,6 +234,21 @@ public class Pass1GenerateSingleStaticAssignmentForm {
symbolMap.put(label, blockMap);
}
blockMap.put(unversioned, versioned);
} else if (statement instanceof StatementCallLValue) {
StatementCallLValue call = (StatementCallLValue) statement;
LValue lValue = call.getLValue();
if (lValue instanceof VariableVersion) {
VariableVersion versioned = (VariableVersion) lValue;
Label label = block.getLabel();
VariableUnversioned unversioned = versioned.getVersionOf();
Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
if (blockMap == null) {
blockMap = new HashMap<>();
symbolMap.put(label, blockMap);
}
blockMap.put(unversioned, versioned);
}
}
}
}

View File

@ -0,0 +1,46 @@
package dk.camelot64.kickc.icl;
import java.util.List;
/** Pass that modifies a control flow graph to call procedures by passing parameters through registers */
public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor {
private Scope scope;
private ControlFlowGraph graph;
public Pass1ProcedureCallParameters(Scope scope, ControlFlowGraph graph ) {
this.scope = scope;
this.graph= graph;
}
public ControlFlowGraph generate() {
ControlFlowGraph generated = visitGraph(graph);
return generated;
}
@Override
public StatementCallLValue visitCallLValue(StatementCallLValue origCall) {
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
// Generate parameter passing assignments
Procedure procedure = origCall.getProcedure();
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, parameterValue));
}
String procedureName = origCall.getProcedureName();
Variable procReturnVar = procedure.getVariable("return");
StatementCallLValue copyCall = new StatementCallLValue(procReturnVar, procedureName, null);
copyCall.setParametersByAssignment(true);
copyCall.setProcedure(procedure);
addStatementToCurrentBlock(copyCall);
getCurrentBlock().setCallSuccessor(procedure.getLabel());
splitCurrentBlock(scope.addLabelIntermediate());
addStatementToCurrentBlock(new StatementAssignment(origCall.getLValue(), procReturnVar));
return null;
}
}

View File

@ -0,0 +1,38 @@
package dk.camelot64.kickc.icl;
/** Pass that modifies a control flow graph to call procedures by passing return value through registers */
public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor {
private Scope scope;
private ControlFlowGraph graph;
public Pass1ProcedureCallsReturnValue(Scope scope, ControlFlowGraph graph ) {
this.scope = scope;
this.graph= graph;
}
public ControlFlowGraph generate() {
ControlFlowGraph generated = visitGraph(graph);
return generated;
}
@Override
public StatementCallLValue visitCallLValue(StatementCallLValue origCall) {
// Procedure strategy implemented is currently variable-based transfer of parameters/return values
// Generate return value assignment
Procedure procedure = origCall.getProcedure();
String procedureName = origCall.getProcedureName();
StatementCallLValue copyCall = new StatementCallLValue(null, procedureName, null);
copyCall.setParametersByAssignment(true);
copyCall.setProcedure(procedure);
addStatementToCurrentBlock(copyCall);
getCurrentBlock().setCallSuccessor(procedure.getLabel());
//StatementAssignment returnAssignment = new StatementAssignment();
return null;
}
}

View File

@ -47,6 +47,9 @@ public class Pass1TypeInference {
String procedureName = call.getProcedureName();
Procedure procedure = scopes.peek().getProcedure(procedureName);
call.setProcedure(procedure);
if(procedure.getParameters().size()!=call.getParameters().size()) {
throw new RuntimeException("Wrong number of parameters in call. Expected " +procedure.getParameters().size()+". "+statement.toString());
}
((Variable) lValue).setInferredType(procedure.getReturnType());
}
}

View File

@ -18,29 +18,23 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization {
remove.add(block);
}
}
for (ControlFlowBlock block : remove) {
ControlFlowBlock successor = block.getDefaultSuccessor();
for (ControlFlowBlock predecessor : block.getPredecessors()) {
replace.put(block.getLabel(), predecessor.getLabel());
if (block.equals(predecessor.getDefaultSuccessor())) {
predecessor.setDefaultSuccessor(successor);
if (successor != null) {
successor.addPredecessor(predecessor);
}
for (ControlFlowBlock removeBlock : remove) {
ControlFlowBlock successor = getGraph().getDefaultSuccessor(removeBlock);
for (ControlFlowBlock predecessor : getGraph().getPredecessors(removeBlock)) {
replace.put(removeBlock.getLabel(), predecessor.getLabel());
if (removeBlock.getLabel().equals(predecessor.getDefaultSuccessor())) {
predecessor.setDefaultSuccessor(successor.getLabel());
}
if (block.equals(predecessor.getConditionalSuccessor())) {
predecessor.setConditionalSuccessor(successor);
if (successor != null) {
successor.addPredecessor(predecessor);
}
if (removeBlock.getLabel().equals(predecessor.getConditionalSuccessor())) {
predecessor.setConditionalSuccessor(successor.getLabel());
}
if (removeBlock.getLabel().equals(predecessor.getCallSuccessor())) {
predecessor.setCallSuccessor(successor.getLabel());
}
}
if (successor != null && block.getLabel().isIntermediate()) {
successor.removePredecessor(block);
}
getGraph().getAllBlocks().remove(block);
getSymbols().remove(block.getLabel());
System.out.println("Culled Empty Block " + block.getLabel());
getGraph().getAllBlocks().remove(removeBlock);
getSymbols().remove(removeBlock.getLabel());
System.out.println("Culled Empty Block " + removeBlock.getLabel());
}
replaceLabels(replace);
return remove.size()>0;

View File

@ -168,9 +168,9 @@ public abstract class Pass2SsaOptimization {
@Override
public Void visitPhi(StatementPhi phi) {
for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) {
Label replacement = getReplacement(replacements, previousSymbol.getBlock().getLabel());
Label replacement = getReplacement(replacements, previousSymbol.getBlock());
if (replacement != null) {
previousSymbol.setBlock(graph.getBlock(replacement));
previousSymbol.setBlock(replacement);
}
}
return null;

View File

@ -27,7 +27,7 @@ public class Pass3CodeGeneration {
// Generate statements
genStatements(asm, block);
// Generate exit
ControlFlowBlock defaultSuccessor = block.getDefaultSuccessor();
ControlFlowBlock defaultSuccessor = graph.getDefaultSuccessor(block);
if (defaultSuccessor != null) {
if (defaultSuccessor.hasPhiStatements()) {
genBlockPhiTransition(asm, block, defaultSuccessor);
@ -81,8 +81,8 @@ public class Pass3CodeGeneration {
private void genBlockEntryPoints(AsmProgram asm, ControlFlowBlock block) {
if (block.hasPhiStatements()) {
for (ControlFlowBlock predecessor : block.getPredecessors()) {
if (block.equals(predecessor.getConditionalSuccessor())) {
for (ControlFlowBlock predecessor : graph.getPredecessors(block)) {
if (block.getLabel().equals(predecessor.getConditionalSuccessor())) {
genBlockPhiTransition(asm, predecessor, block);
asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getLocalName().replace('@', 'B'));
}

View File

@ -125,6 +125,7 @@ public class Scope implements Symbol {
}
Procedure procedure = new Procedure(name, type, this);
add(procedure);
procedure.addVariable("return", type);
return procedure;
}

View File

@ -14,11 +14,13 @@ public class StatementCallLValue implements StatementLValue {
private String procedureName;
private List<RValue> parameters;
private Procedure procedure;
private boolean parametersByAssignment;
public StatementCallLValue(LValue lValue, String procedureName, List<RValue> parameters) {
this.lValue = lValue;
this.procedureName = procedureName;
this.parameters = parameters;
this.parametersByAssignment = false;
}
public LValue getLValue() {
@ -53,6 +55,14 @@ public class StatementCallLValue implements StatementLValue {
return parameters.get(idx);
}
public boolean isParametersByAssignment() {
return parametersByAssignment;
}
public void setParametersByAssignment(boolean parametersByAssignment) {
this.parametersByAssignment = parametersByAssignment;
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
@ -64,10 +74,20 @@ public class StatementCallLValue implements StatementLValue {
} else {
res.append(procedureName + " ");
}
for (RValue parameter : parameters) {
res.append(parameter+" ");
if(parameters!=null) {
for (RValue parameter : parameters) {
res.append(parameter + " ");
}
}
if(parametersByAssignment) {
res.append("param-assignment");
}
return res.toString();
}
public void clearParameters() {
this.parameters = null;
this.parametersByAssignment = true;
}
}

View File

@ -27,15 +27,15 @@ public class StatementPhi implements StatementLValue {
* Which value is chosen depends on which block transition was made.
*/
public static class PreviousSymbol {
private ControlFlowBlock block;
private Label block;
private RValue rValue;
public PreviousSymbol(ControlFlowBlock block, RValue rValue) {
public PreviousSymbol(Label block, RValue rValue) {
this.block = block;
this.rValue = rValue;
}
public ControlFlowBlock getBlock() {
public Label getBlock() {
return block;
}
@ -43,12 +43,11 @@ public class StatementPhi implements StatementLValue {
return rValue;
}
public void setRValue(RValue RValue) {
this.rValue = RValue;
}
public void setBlock(ControlFlowBlock block) {
public void setBlock(Label block) {
this.block = block;
}
}
@ -65,8 +64,8 @@ public class StatementPhi implements StatementLValue {
this.lValue = (VariableVersion) lValue;
}
public void addPreviousVersion(ControlFlowBlock block, VariableVersion symbol) {
previousVersions.add(new PreviousSymbol(block, symbol));
public void addPreviousVersion(Label block, RValue rValue) {
previousVersions.add(new PreviousSymbol(block, rValue));
}
public List<PreviousSymbol> getPreviousVersions() {
@ -78,7 +77,7 @@ public class StatementPhi implements StatementLValue {
StringBuilder out = new StringBuilder();
out.append(lValue + "" + "phi(");
for (PreviousSymbol previousSymbol : previousVersions) {
out.append(" "+previousSymbol.getBlock().getLabel().getLocalName()+"/"+previousSymbol.getRValue());
out.append(" "+previousSymbol.getBlock().getLocalName()+"/"+previousSymbol.getRValue());
}
out.append(" )");
return out.toString();

View File

@ -42,15 +42,25 @@ public class Main {
System.out.println("INITIAL CONTROL FLOW GRAPH");
System.out.println(controlFlowGraph.toString());
if(1==1) return;
Pass1ProcedureCallParameters pass1ProcedureCallParameters = new Pass1ProcedureCallParameters(programScope, controlFlowGraph);
controlFlowGraph = pass1ProcedureCallParameters.generate();
System.out.println("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL");
System.out.println(controlFlowGraph.toString());
Pass1GenerateSingleStaticAssignmentForm pass1GenerateSingleStaticAssignmentForm =
new Pass1GenerateSingleStaticAssignmentForm(programScope, controlFlowGraph);
pass1GenerateSingleStaticAssignmentForm.generate();
System.out.println("CONTROL FLOW GRAPH SSA");
System.out.println(controlFlowGraph.toString());
//Pass1ProcedureCallsReturnValue pass1ProcedureCallsReturnValue = new Pass1ProcedureCallsReturnValue(programScope, controlFlowGraph);
//controlFlowGraph = pass1ProcedureCallsReturnValue.generate();
//System.out.println("CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN");
//System.out.println(controlFlowGraph.toString());
if(1==1) return;
List<Pass2SsaOptimization> optimizations = new ArrayList<>();
optimizations.add(new Pass2CullEmptyBlocks(controlFlowGraph, programScope));
optimizations.add(new Pass2ConstantPropagation(controlFlowGraph, programScope));