mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-20 02:32:36 +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() {
|
||||
versionAllAssignments();
|
||||
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() {
|
||||
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
|
||||
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() {
|
||||
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
|
||||
// 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) {
|
||||
Symbol version = null;
|
||||
if (rValue instanceof Symbol) {
|
||||
@ -103,5 +113,94 @@ public class PassGenerateSingleStaticAssignmentForm {
|
||||
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;
|
||||
|
||||
/** The previous version of the symbol from predeccesor control blocks. */
|
||||
private List<Symbol> previousVersions;
|
||||
|
||||
private List<PreviousSymbol> previousVersions;
|
||||
|
||||
public StatementPhi(Symbol lValue) {
|
||||
this.lValue = lValue;
|
||||
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;
|
||||
}
|
||||
|
||||
public void addPreviousVersion(Symbol previousVersion) {
|
||||
previousVersions.add(previousVersion);
|
||||
public void addPreviousVersion(ControlFlowBlock block, Symbol symbol) {
|
||||
previousVersions.add(new PreviousSymbol(block, symbol));
|
||||
}
|
||||
|
||||
public List<Symbol> getPreviousVersions() {
|
||||
public List<PreviousSymbol> getPreviousVersions() {
|
||||
return previousVersions;
|
||||
}
|
||||
|
||||
@ -39,8 +62,8 @@ public class StatementPhi implements Statement {
|
||||
public String toString() {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append(lValue + " ← " + "phi(");
|
||||
for (Symbol previousVersion : previousVersions) {
|
||||
out.append(" "+previousVersion.toString());
|
||||
for (PreviousSymbol previousSymbol : previousVersions) {
|
||||
out.append(" "+previousSymbol.getBlock().getLabel().getName()+"/"+previousSymbol.getSymbol().getName());
|
||||
}
|
||||
out.append(" )");
|
||||
return out.toString();
|
||||
|
@ -1,7 +1,6 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Manages symbols (variables, labels)
|
||||
@ -58,7 +57,10 @@ public class SymbolManager {
|
||||
@Override
|
||||
public String toString() {
|
||||
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);
|
||||
out.append(symbol.toString() + "\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user