mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-18 08:30:18 +00:00
Implemented phi function completion loop.
This commit is contained in:
parent
807198113b
commit
3b8580498b
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user