1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-10-21 02:24:34 +00:00

Implemented phi function completion loop.

This commit is contained in:
Jesper Gravgaard 2017-05-12 10:26:56 +02:00
parent 807198113b
commit 3b8580498b
3 changed files with 141 additions and 17 deletions

View File

@ -21,12 +21,16 @@ public class PassGenerateSingleStaticAssignmentForm {
public void generate() { public void generate() {
versionAllAssignments(); versionAllAssignments();
versionAllUses(); versionAllUses();
boolean done = false;
do {
System.out.println("Completing Phi functions...");
done = completePhiFunctions();
} 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() { private void versionAllAssignments() {
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) { for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) { for (Statement statement : block.getStatements()) {
@ -43,9 +47,7 @@ public class PassGenerateSingleStaticAssignmentForm {
} }
} }
/** /** Version all uses of non-versioned non-intermediary variables */
* Version all uses of non-versioned non-intermediary variables
*/
private void versionAllUses() { private void versionAllUses() {
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) { for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
// Newest version of variables in the block. // Newest version of variables in the block.
@ -82,6 +84,14 @@ public class PassGenerateSingleStaticAssignmentForm {
} }
/**
* 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 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.
* @return Null if the rValue does not need versioning. The versioned symbol to use if it does.
*/
private Symbol findOrCreateVersion(RValue rValue, Map<Symbol, Symbol> blockVersions, Map<Symbol, Symbol> blockNewPhis) { private Symbol findOrCreateVersion(RValue rValue, Map<Symbol, Symbol> blockVersions, Map<Symbol, Symbol> blockNewPhis) {
Symbol version = null; Symbol version = null;
if (rValue instanceof Symbol) { if (rValue instanceof Symbol) {
@ -103,5 +113,94 @@ public class PassGenerateSingleStaticAssignmentForm {
return version; return version;
} }
/** 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<Symbol, Symbol>> newPhis = new HashMap<>();
Map<Symbol, Map<Symbol, Symbol>> symbolMap = buildSymbolMap();
for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) {
if (statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement;
if (phi.getPreviousVersions().isEmpty()) {
Symbol versioned = phi.getlValue();
Symbol unversioned = versioned.getVersionOf();
for (ControlFlowBlock predecessor : block.getPredecessors()) {
Symbol previousSymbol = symbolMap.get(predecessor.getLabel()).get(unversioned);
if (previousSymbol == null) {
// No previous symbol found in predecessor block. Look in new a phi functions.
Map<Symbol, Symbol> 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);
}
}
phi.addPreviousVersion(predecessor, previousSymbol);
}
}
}
}
}
// Ads new phi functions to blocks
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
Map<Symbol, Symbol> blockNewPhis = newPhis.get(block);
if(blockNewPhis!=null) {
for (Symbol symbol : blockNewPhis.keySet()) {
block.addPhiStatement(blockNewPhis.get(symbol));
}
}
}
return (newPhis.size()==0);
}
/**
* Builds a map of all which versions each symbol has in each block.
* Maps Control Flow Block Label -> ( Unversioned Symbol -> Versioned Symbol) for all relevant symbols.
*/
private Map<Symbol, Map<Symbol, Symbol>> buildSymbolMap() {
Map<Symbol, Map<Symbol, Symbol>> symbolMap = new HashMap<>();
for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) {
for (Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
LValue lValue = assignment.getlValue();
if(lValue instanceof Symbol) {
Symbol symbol = (Symbol) lValue;
if(symbol.isVersioned()) {
Symbol label = block.getLabel();
Symbol unversioned = symbol.getVersionOf();
Symbol versioned = symbol;
Map<Symbol, Symbol> blockMap = symbolMap.get(label);
if(blockMap == null) {
blockMap = new HashMap<>();
symbolMap.put(label, blockMap);
}
blockMap.put(unversioned, versioned);
}
}
} else if(statement instanceof StatementPhi) {
StatementPhi phi = (StatementPhi) statement;
Symbol versioned = phi.getlValue();
Symbol unversioned = versioned.getVersionOf();
Symbol label = block.getLabel();
Map<Symbol, Symbol> blockMap = symbolMap.get(label);
if(blockMap == null) {
blockMap = new HashMap<>();
symbolMap.put(label, blockMap);
}
blockMap.put(unversioned, versioned);
}
}
} return symbolMap;
}
} }

View File

@ -15,23 +15,46 @@ public class StatementPhi implements Statement {
private Symbol lValue; private Symbol lValue;
/** The previous version of the symbol from predeccesor control blocks. */ /** The previous version of the symbol from predeccesor control blocks. */
private List<Symbol> previousVersions; private List<PreviousSymbol> previousVersions;
public StatementPhi(Symbol lValue) { public StatementPhi(Symbol lValue) {
this.lValue = lValue; this.lValue = lValue;
this.previousVersions = new ArrayList<>(); this.previousVersions = new ArrayList<>();
} }
public LValue getlValue() { /**
* A previous version of the symbol that the phi function might take its value from.
* Which value is chosen depends on which block transition was made.
*/
public static class PreviousSymbol {
private ControlFlowBlock block;
private Symbol symbol;
public PreviousSymbol(ControlFlowBlock block, Symbol symbol) {
this.block = block;
this.symbol = symbol;
}
public ControlFlowBlock getBlock() {
return block;
}
public Symbol getSymbol() {
return symbol;
}
}
public Symbol getlValue() {
return lValue; return lValue;
} }
public void addPreviousVersion(Symbol previousVersion) { public void addPreviousVersion(ControlFlowBlock block, Symbol symbol) {
previousVersions.add(previousVersion); previousVersions.add(new PreviousSymbol(block, symbol));
} }
public List<Symbol> getPreviousVersions() { public List<PreviousSymbol> getPreviousVersions() {
return previousVersions; return previousVersions;
} }
@ -39,8 +62,8 @@ public class StatementPhi implements Statement {
public String toString() { public String toString() {
StringBuilder out = new StringBuilder(); StringBuilder out = new StringBuilder();
out.append(lValue + "" + "phi("); out.append(lValue + "" + "phi(");
for (Symbol previousVersion : previousVersions) { for (PreviousSymbol previousSymbol : previousVersions) {
out.append(" "+previousVersion.toString()); out.append(" "+previousSymbol.getBlock().getLabel().getName()+"/"+previousSymbol.getSymbol().getName());
} }
out.append(" )"); out.append(" )");
return out.toString(); return out.toString();

View File

@ -1,7 +1,6 @@
package dk.camelot64.kickc.icl; package dk.camelot64.kickc.icl;
import java.util.LinkedHashMap; import java.util.*;
import java.util.Map;
/** /**
* Manages symbols (variables, labels) * Manages symbols (variables, labels)
@ -58,7 +57,10 @@ public class SymbolManager {
@Override @Override
public String toString() { public String toString() {
StringBuffer out = new StringBuffer(); StringBuffer out = new StringBuffer();
for (String name : symbols.keySet()) { Set<String> names = symbols.keySet();
List<String> sortedNames = new ArrayList<>(names);
Collections.sort(sortedNames);
for (String name : sortedNames) {
Symbol symbol = symbols.get(name); Symbol symbol = symbols.get(name);
out.append(symbol.toString() + "\n"); out.append(symbol.toString() + "\n");
} }