diff --git a/src/dk/camelot64/kickc/icl/Constant.java b/src/dk/camelot64/kickc/icl/Constant.java index de4453b53..66d2ee51b 100644 --- a/src/dk/camelot64/kickc/icl/Constant.java +++ b/src/dk/camelot64/kickc/icl/Constant.java @@ -3,5 +3,4 @@ package dk.camelot64.kickc.icl; /** SSA form constant value */ public interface Constant extends RValue { - } diff --git a/src/dk/camelot64/kickc/icl/ConstantDouble.java b/src/dk/camelot64/kickc/icl/ConstantDouble.java index 16ca8097d..fba35849e 100644 --- a/src/dk/camelot64/kickc/icl/ConstantDouble.java +++ b/src/dk/camelot64/kickc/icl/ConstantDouble.java @@ -15,4 +15,8 @@ public class ConstantDouble implements Constant { public String toString() { return Double.toString(number); } + + public Double getNumber() { + return number; + } } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java b/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java new file mode 100644 index 000000000..390e03d3e --- /dev/null +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java @@ -0,0 +1,59 @@ +package dk.camelot64.kickc.icl; + +import java.util.Collection; + +/** Base visitor for iterating through a control flow graph */ +public class ControlFlowGraphBaseVisitor { + + public T visitGraph(ControlFlowGraph graph) { + Collection blocks = graph.getAllBlocks(); + for (ControlFlowBlock block : blocks) { + this.visitBlock(block); + } + return null; + } + + public T visitBlock(ControlFlowBlock block) { + for (Statement statement : block.getStatements()) { + this.visitStatement(statement); + } + return null; + } + + public T visitStatement(Statement statement) { + if(statement instanceof StatementAssignment) { + return visitAssignment((StatementAssignment) statement); + } else if(statement instanceof StatementConditionalJump) { + return visitConditionalJump((StatementConditionalJump) statement); + } else if(statement instanceof StatementJump) { + return visitJump((StatementJump) statement); + } else if(statement instanceof StatementJumpTarget) { + return visitJumpTarget((StatementJumpTarget) statement); + } else if(statement instanceof StatementPhi) { + return visitPhi((StatementPhi) statement); + } else { + throw new RuntimeException("Unhandled statement type "+statement); + } + } + + public T visitAssignment(StatementAssignment assignment) { + return null; + } + + public T visitConditionalJump(StatementConditionalJump conditionalJump) { + return null; + } + + public T visitJump(StatementJump jump) { + return null; + } + + public T visitJumpTarget(StatementJumpTarget jumpTarget) { + return null; + } + + public T visitPhi(StatementPhi phi) { + return null; + } + +} diff --git a/src/dk/camelot64/kickc/icl/LValue.java b/src/dk/camelot64/kickc/icl/LValue.java index ae0c4ffe3..f5e90ed00 100644 --- a/src/dk/camelot64/kickc/icl/LValue.java +++ b/src/dk/camelot64/kickc/icl/LValue.java @@ -1,5 +1,5 @@ package dk.camelot64.kickc.icl; /** Assignable value (capable of being on the left part of an assignment)*/ -public interface LValue { +public interface LValue extends RValue { } diff --git a/src/dk/camelot64/kickc/icl/PassAliasElimination.java b/src/dk/camelot64/kickc/icl/PassAliasElimination.java new file mode 100644 index 000000000..804276023 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PassAliasElimination.java @@ -0,0 +1,79 @@ +package dk.camelot64.kickc.icl; + +import java.util.HashMap; +import java.util.Map; + +/** Compiler Pass eliminating alias assignments */ +public class PassAliasElimination { + + private SymbolTable symbolTable; + private ControlFlowGraph graph; + + public PassAliasElimination(SymbolTable symbolTable, ControlFlowGraph graph) { + this.symbolTable = symbolTable; + this.graph = graph; + } + + /** + * Eliminate alias assignments replacing them with the aliassed variable. + */ + public void eliminate() { + final Map aliases = findAliases(); + PassHelper.removeAssignments(graph, symbolTable, aliases.values()); + PassHelper.replace(graph, aliases); + for (Variable var : aliases.keySet()) { + Variable alias = aliases.get(var); + System.out.println("Alias " + var + " " + alias); + } + } + + /** Make sure aliases of other aliases are pointing to the final alias. */ + private void finalizeAliases(Map aliases) { + for (Variable variable : aliases.keySet()) { + Variable alias = aliases.get(variable); + while(aliases.get(alias)!=null) { + alias = aliases.get(alias); + } + aliases.put(variable, alias); + } + } + + /** + * Find variables that have constant values. + * @return Map from Variable to the Constant value + */ + private Map findAliases() { + final Map aliases = new HashMap<>(); + ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { + @Override + public Void visitAssignment(StatementAssignment assignment) { + if (assignment.getLValue() instanceof VariableVersion || assignment.getLValue() instanceof VariableIntermediate) { + Variable variable = (Variable) assignment.getLValue(); + if (assignment.getRValue1() == null && assignment.getOperator() == null && assignment.getRValue2() instanceof Variable) { + // Alias assignment + Variable alias = (Variable) assignment.getRValue2(); + aliases.put(alias, variable); + } + } + return null; + } + + @Override + public Void visitPhi(StatementPhi phi) { + if(phi.getPreviousVersions().size()==1) { + StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0); + if(previousSymbol.getRValue() instanceof Variable) { + VariableVersion variable = phi.getLValue(); + Variable alias = (Variable) previousSymbol.getRValue(); + aliases.put(alias, variable); + } + } + return null; + } + }; + visitor.visitGraph(graph); + return aliases; + } + + +} diff --git a/src/dk/camelot64/kickc/icl/PassConstantPropagation.java b/src/dk/camelot64/kickc/icl/PassConstantPropagation.java new file mode 100644 index 000000000..aeb442b4a --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PassConstantPropagation.java @@ -0,0 +1,144 @@ +package dk.camelot64.kickc.icl; + +import java.util.HashMap; +import java.util.Map; + +/** Compiler Pass propagating constants in expressions eliminating constant variables */ +public class PassConstantPropagation { + + private SymbolTable symbolTable; + private ControlFlowGraph controlFlowGraph; + + public PassConstantPropagation(SymbolTable symbolTable, ControlFlowGraph controlFlowGraph) { + this.symbolTable = symbolTable; + this.controlFlowGraph = controlFlowGraph; + } + + /** + * Propagate constants, replacing variables with constants where possible. + * @return true if no more constant propagation is possible. (no constant propagation was performed) + * false if more constant propagation might be possible. (signalling another call) + */ + public void propagateConstants() { + boolean done; + do { + final Map constants = findConstantVariables(); + for (Variable constantVar : constants.keySet()) { + Constant constantValue = constants.get(constantVar); + System.out.println("Constant " + constantVar + " " + constantValue); + } + PassHelper.removeAssignments(controlFlowGraph, symbolTable, constants.keySet()); + PassHelper.replace(controlFlowGraph, constants); + done = (constants.size()==0); + } while (!done); + } + + /** + * Find variables that have constant values. + * @return Map from Variable to the Constant value + */ + private Map findConstantVariables() { + final Map constants = new HashMap<>(); + ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { + @Override + public Void visitAssignment(StatementAssignment assignment) { + if(assignment.getLValue() instanceof VariableVersion || assignment.getLValue() instanceof VariableIntermediate ) { + Variable variable = (Variable) assignment.getLValue(); + if(assignment.getRValue1() == null && assignment.getRValue2() instanceof Constant) { + if(assignment.getOperator()==null) { + // Constant assignment + Constant constant = (Constant) assignment.getRValue2(); + constants.put(variable, constant); + } else { + // Constant unary expression + Constant constant = calculateUnary(assignment.getOperator(), (Constant) assignment.getRValue2()); + constants.put(variable, constant); + } + } else if(assignment.getRValue1() instanceof Constant && assignment.getRValue2() instanceof Constant) { + // Constant binary expression + Constant constant = calculateBinary(assignment.getOperator(), (Constant) assignment.getRValue1(), (Constant) assignment.getRValue2()); + constants.put(variable, constant); + } + } + return null; + } + + @Override + public Void visitPhi(StatementPhi phi) { + if(phi.getPreviousVersions().size()==1) { + StatementPhi.PreviousSymbol previousSymbol = phi.getPreviousVersions().get(0); + if(previousSymbol.getRValue() instanceof Constant) { + VariableVersion variable = phi.getLValue(); + Constant constant = (Constant) previousSymbol.getRValue(); + constants.put(variable, constant); + } + } + return null; + } + }; + visitor.visitGraph(controlFlowGraph); + return constants; + } + + + public static Constant calculateBinary(Operator operator, Constant c1, Constant c2) { + switch(operator.getOperator()) { + case "-": { + if(c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) { + return new ConstantInteger(getInteger(c1) - getInteger(c2)); + } else { + return new ConstantDouble(getDouble(c1) - getDouble(c2)); + } + } + case "+": { + if(c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) { + return new ConstantInteger(getInteger(c1) + getInteger(c2)); + } else { + return new ConstantDouble(getDouble(c1) + getDouble(c2)); + } + } + default: + throw new RuntimeException("Unhandled Binary Operator "+operator.getOperator()); + } + } + + private static Integer getInteger(Constant constant) { + if(constant instanceof ConstantInteger) { + return ((ConstantInteger) constant).getNumber(); + } else { + throw new RuntimeException("Type Mismatch. Constant is not an integer number "+constant); + } + } + + private static Double getDouble(Constant constant) { + if(constant instanceof ConstantDouble) { + return ((ConstantDouble) constant).getNumber(); + } else if(constant instanceof ConstantInteger) { + return ((ConstantInteger) constant).getNumber().doubleValue(); + } else { + throw new RuntimeException("Type Mismatch. Constant is not a number "+constant); + } + } + + public static Constant calculateUnary(Operator operator, Constant c) { + switch(operator.getOperator()) { + case "-": { + if(c instanceof ConstantInteger) { + ConstantInteger cInt = (ConstantInteger) c; + return new ConstantInteger(-cInt.getNumber()); + } else if(c instanceof ConstantDouble) { + ConstantDouble cDoub = (ConstantDouble) c; + return new ConstantDouble(-cDoub.getNumber()); + } else { + throw new RuntimeException("Type mismatch. Unary Minus cannot handle value "+c); + } + } + case "+": { + return c; + } + default: + throw new RuntimeException("Unhandled Unary Operator "+operator.getOperator()); + } + } + +} diff --git a/src/dk/camelot64/kickc/icl/PassCullEmptyBlocks.java b/src/dk/camelot64/kickc/icl/PassCullEmptyBlocks.java new file mode 100644 index 000000000..4e0c1c0c8 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PassCullEmptyBlocks.java @@ -0,0 +1,42 @@ +package dk.camelot64.kickc.icl; + +import java.util.*; + +/** Pass that culls empty control flow blocks from the program */ +public class PassCullEmptyBlocks { + + private SymbolTable symbolTable; + private ControlFlowGraph graph; + + public PassCullEmptyBlocks(SymbolTable symbolTable, ControlFlowGraph controlFlowGraph) { + this.symbolTable = symbolTable; + this.graph = controlFlowGraph; + } + + public void cull() { + cullEmptyBlocks(); + } + + private void cullEmptyBlocks() { + for (Iterator iterator = graph.getAllBlocks().iterator(); iterator.hasNext(); ) { + ControlFlowBlock block = iterator.next(); + if (block.getStatements().isEmpty()) { + ControlFlowBlock successor = block.getDefaultSuccessor(); + for (ControlFlowBlock predecessor : block.getPredecessors()) { + if (predecessor.getDefaultSuccessor().equals(block)) { + predecessor.setDefaultSuccessor(successor); + successor.addPredecessor(predecessor); + } + if (predecessor.getConditionalSuccessor().equals(block)) { + predecessor.setConditionalSuccessor(successor); + successor.addPredecessor(predecessor); + } + } + successor.removePredecessor(block); + iterator.remove(); + symbolTable.remove(block.getLabel()); + } + } + } + +} diff --git a/src/dk/camelot64/kickc/icl/PassGenerateControlFlowGraph.java b/src/dk/camelot64/kickc/icl/PassGenerateControlFlowGraph.java index 2d9b69303..4ae903793 100644 --- a/src/dk/camelot64/kickc/icl/PassGenerateControlFlowGraph.java +++ b/src/dk/camelot64/kickc/icl/PassGenerateControlFlowGraph.java @@ -49,35 +49,9 @@ public class PassGenerateControlFlowGraph { currentBlock.addStatement(statement); } } - cullEmptyBlocks(); return new ControlFlowGraph(blocks, firstBlock); } - private void cullEmptyBlocks() { - List remove = new ArrayList<>(); - for (ControlFlowBlock block : blocks.values()) { - if(block.getStatements().isEmpty()) { - ControlFlowBlock successor = block.getDefaultSuccessor(); - for (ControlFlowBlock predecessor : block.getPredecessors()) { - if(predecessor.getDefaultSuccessor().equals(block)) { - predecessor.setDefaultSuccessor(successor); - successor.addPredecessor(predecessor); - } - if(predecessor.getConditionalSuccessor().equals(block)) { - predecessor.setConditionalSuccessor(successor); - successor.addPredecessor(predecessor); - } - } - successor.removePredecessor(block); - remove.add(block); - } - } - for (ControlFlowBlock block : remove) { - blocks.remove(block.getLabel()); - symbolTable.remove(block.getLabel()); - } - } - private ControlFlowBlock getOrCreateBlock(Label label) { ControlFlowBlock block = blocks.get(label); if(block==null) { diff --git a/src/dk/camelot64/kickc/icl/PassGenerateSingleStaticAssignmentForm.java b/src/dk/camelot64/kickc/icl/PassGenerateSingleStaticAssignmentForm.java index d817432e8..bc5f8fc36 100644 --- a/src/dk/camelot64/kickc/icl/PassGenerateSingleStaticAssignmentForm.java +++ b/src/dk/camelot64/kickc/icl/PassGenerateSingleStaticAssignmentForm.java @@ -34,7 +34,7 @@ public class PassGenerateSingleStaticAssignmentForm { for (Statement statement : block.getStatements()) { if (statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; - LValue lValue = assignment.getlValue(); + LValue lValue = assignment.getLValue(); if(lValue instanceof VariableUnversioned) { // Assignment to a non-versioned non-intermediary variable VariableUnversioned assignedSymbol = (VariableUnversioned) lValue; @@ -69,7 +69,7 @@ public class PassGenerateSingleStaticAssignmentForm { } } // Update map of versions encountered in the block - LValue lValue = assignment.getlValue(); + LValue lValue = assignment.getLValue(); if (lValue instanceof VariableVersion) { VariableVersion versioned = (VariableVersion) lValue; blockVersions.put(versioned.getVersionOf(), versioned); @@ -81,7 +81,6 @@ public class PassGenerateSingleStaticAssignmentForm { block.addPhiStatement(blockNewPhis.get(symbol)); } } - } /** @@ -126,7 +125,7 @@ public class PassGenerateSingleStaticAssignmentForm { if (statement instanceof StatementPhi) { StatementPhi phi = (StatementPhi) statement; if (phi.getPreviousVersions().isEmpty()) { - VariableVersion versioned = phi.getlValue(); + VariableVersion versioned = phi.getLValue(); VariableUnversioned unversioned = versioned.getVersionOf(); for (ControlFlowBlock predecessor : block.getPredecessors()) { VariableVersion previousSymbol = symbolMap.get(predecessor.getLabel()).get(unversioned); @@ -172,7 +171,7 @@ public class PassGenerateSingleStaticAssignmentForm { for (Statement statement : block.getStatements()) { if(statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; - LValue lValue = assignment.getlValue(); + LValue lValue = assignment.getLValue(); if(lValue instanceof VariableVersion) { VariableVersion versioned = (VariableVersion) lValue; Label label = block.getLabel(); @@ -186,7 +185,7 @@ public class PassGenerateSingleStaticAssignmentForm { } } else if(statement instanceof StatementPhi) { StatementPhi phi = (StatementPhi) statement; - VariableVersion versioned = phi.getlValue(); + VariableVersion versioned = phi.getLValue(); VariableUnversioned unversioned = versioned.getVersionOf(); Label label = block.getLabel(); Map blockMap = symbolMap.get(label); @@ -200,5 +199,4 @@ public class PassGenerateSingleStaticAssignmentForm { } return symbolMap; } - } diff --git a/src/dk/camelot64/kickc/icl/PassHelper.java b/src/dk/camelot64/kickc/icl/PassHelper.java new file mode 100644 index 000000000..c7cd061c6 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PassHelper.java @@ -0,0 +1,102 @@ +package dk.camelot64.kickc.icl; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +/** Helper functions for creating compiler passes */ +public class PassHelper { + + /** + * Replace all usages of variables in statements with aliases. + * @param aliases Variables that have alias values. + */ + public static void replace(ControlFlowGraph graph, final Map aliases) { + ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { + @Override + public Object visitAssignment(StatementAssignment assignment) { + if(getAlias(aliases, assignment.getLValue()) !=null) { + RValue alias = getAlias(aliases, assignment.getLValue()); + if(alias instanceof LValue) { + assignment.setLValue((LValue) alias); + } + } + if(getAlias(aliases, assignment.getRValue1())!=null) { + assignment.setRValue1(getAlias(aliases, assignment.getRValue1())); + } + if(getAlias(aliases, assignment.getRValue2())!=null) { + assignment.setRValue2(getAlias(aliases, assignment.getRValue2())); + } + return null; + } + + @Override + public Object visitConditionalJump(StatementConditionalJump conditionalJump) { + if(getAlias(aliases, conditionalJump.getCondition())!=null) { + conditionalJump.setCondition(getAlias(aliases, conditionalJump.getCondition())); + } + return null; + } + + @Override + public Object visitPhi(StatementPhi phi) { + if(getAlias(aliases, phi.getLValue())!=null) { + RValue alias = getAlias(aliases, phi.getLValue()); + if(alias instanceof LValue) { + phi.setLValue((Variable) alias); + } + } + for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) { + if(getAlias(aliases, previousSymbol.getRValue())!=null) { + previousSymbol.setRValue(getAlias(aliases, previousSymbol.getRValue())); + } + } + return null; + } + }; + visitor.visitGraph(graph); + } + + /** Get the alias to use for an RValue. + * + * @param aliases The alias map + * @param rValue The RValue to find an alias for + * @return The alias to use. Null if no alias exists. + */ + private static RValue getAlias(Map aliases,RValue rValue) { + RValue alias = aliases.get(rValue); + while (aliases.get(alias)!=null) { + alias = aliases.get(alias); + } + return alias; + } + + /** + * Remove all assignments to specific LValues from the control frlo graph (as they are no longer needed). + * @param graph The control flow graph + * @param symbolTable The symbol table + * @param variables The variables to eliminate + */ + public static void removeAssignments(ControlFlowGraph graph, SymbolTable symbolTable, Collection variables) { + for (ControlFlowBlock block : graph.getAllBlocks()) { + for (Iterator iterator = block.getStatements().iterator(); iterator.hasNext(); ) { + Statement statement = iterator.next(); + if (statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + if (variables.contains(assignment.getLValue())) { + iterator.remove(); + symbolTable.remove((Symbol) assignment.getLValue()); + } + } else if(statement instanceof StatementPhi) { + StatementPhi phi = (StatementPhi) statement; + if (variables.contains(phi.getLValue())) { + iterator.remove(); + symbolTable.remove(phi.getLValue()); + } + } + } + } + } + + +} diff --git a/src/dk/camelot64/kickc/icl/PassRedundantPhiElimination.java b/src/dk/camelot64/kickc/icl/PassRedundantPhiElimination.java new file mode 100644 index 000000000..2a59d5623 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PassRedundantPhiElimination.java @@ -0,0 +1,62 @@ +package dk.camelot64.kickc.icl; + +import java.util.HashMap; +import java.util.Map; + +/** Compiler Pass eliminating redundant phi functions */ +public class PassRedundantPhiElimination { + + private SymbolTable symbolTable; + private ControlFlowGraph graph; + + public PassRedundantPhiElimination(SymbolTable symbolTable, ControlFlowGraph graph) { + this.symbolTable = symbolTable; + this.graph = graph; + } + + /** + * Eliminate alias assignments replacing them with the aliassed variable. + */ + public void eliminate() { + final Map aliases = findRedundantPhis(); + PassHelper.removeAssignments(graph, symbolTable, aliases.keySet()); + PassHelper.replace(graph, aliases); + for (Variable var : aliases.keySet()) { + RValue alias = aliases.get(var); + System.out.println("Redundant Phi " + var + " " + alias); + } + } + + /** + * Find phi variables where all previous symbols are identical. + * @return Map from (phi) Variable to the previous value + */ + private Map findRedundantPhis() { + final Map aliases = new HashMap<>(); + ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { + @Override + public Void visitPhi(StatementPhi phi) { + boolean found = true; + RValue phiRValue = null; + for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) { + if(phiRValue==null) { + phiRValue = previousSymbol.getRValue(); + } else { + if(!phiRValue.equals(previousSymbol.getRValue())) { + found = false; + break; + } + } + } + if(found) { + VariableVersion variable = phi.getLValue(); + aliases.put(variable, phiRValue); + } + return null; + } + }; + visitor.visitGraph(graph); + return aliases; + } + +} diff --git a/src/dk/camelot64/kickc/icl/PassTypeInference.java b/src/dk/camelot64/kickc/icl/PassTypeInference.java index d8a73163e..54a48b3f1 100644 --- a/src/dk/camelot64/kickc/icl/PassTypeInference.java +++ b/src/dk/camelot64/kickc/icl/PassTypeInference.java @@ -9,7 +9,7 @@ public class PassTypeInference { for (Statement statement : sequence.getStatements()) { if (statement instanceof StatementAssignment) { StatementAssignment assignment = (StatementAssignment) statement; - Variable symbol = (Variable) assignment.getlValue(); + Variable symbol = (Variable) assignment.getLValue(); if (SymbolType.VAR.equals(symbol.getType())) { // Unresolved symbol - perform inference Operator operator = assignment.getOperator(); diff --git a/src/dk/camelot64/kickc/icl/StatementAssignment.java b/src/dk/camelot64/kickc/icl/StatementAssignment.java index 3c4687490..96c102284 100644 --- a/src/dk/camelot64/kickc/icl/StatementAssignment.java +++ b/src/dk/camelot64/kickc/icl/StatementAssignment.java @@ -38,7 +38,7 @@ public class StatementAssignment implements Statement { this.rValue2 = rValue2; } - public LValue getlValue() { + public LValue getLValue() { return lValue; } diff --git a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java index 39f8a2796..ffc8b69e0 100644 --- a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java +++ b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java @@ -28,4 +28,8 @@ public class StatementConditionalJump implements Statement { public String toString() { return "if("+condition+") goto "+destination.getName(); } + + public void setCondition(RValue condition) { + this.condition = condition; + } } diff --git a/src/dk/camelot64/kickc/icl/StatementPhi.java b/src/dk/camelot64/kickc/icl/StatementPhi.java index dfa22c5eb..8d24bddfb 100644 --- a/src/dk/camelot64/kickc/icl/StatementPhi.java +++ b/src/dk/camelot64/kickc/icl/StatementPhi.java @@ -14,7 +14,7 @@ public class StatementPhi implements Statement { /** The versioned variable being assigned a value by the statement. */ private VariableVersion lValue; - /** The previous version of the symbol from predeccesor control blocks. */ + /** The previous version of the rValue from predeccesor control blocks. */ private List previousVersions; public StatementPhi(VariableVersion lValue) { @@ -23,33 +23,41 @@ public class StatementPhi implements Statement { } /** - * A previous version of the symbol that the phi function might take its value from. + * A previous version of the rValue 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 VariableVersion symbol; + private RValue rValue; - public PreviousSymbol(ControlFlowBlock block, VariableVersion symbol) { + public PreviousSymbol(ControlFlowBlock block, RValue rValue) { this.block = block; - this.symbol = symbol; + this.rValue = rValue; } public ControlFlowBlock getBlock() { return block; } - public Symbol getSymbol() { - return symbol; + public RValue getRValue() { + return rValue; } + public void setRValue(RValue RValue) { + this.rValue = RValue; + } } - public VariableVersion getlValue() { + public VariableVersion getLValue() { return lValue; } + public void setLValue(Variable lValue) { + this.lValue = (VariableVersion) lValue; + } + + public void addPreviousVersion(ControlFlowBlock block, VariableVersion symbol) { previousVersions.add(new PreviousSymbol(block, symbol)); } @@ -63,7 +71,7 @@ public class StatementPhi implements Statement { StringBuilder out = new StringBuilder(); out.append(lValue + " ← " + "phi("); for (PreviousSymbol previousSymbol : previousVersions) { - out.append(" "+previousSymbol.getBlock().getLabel().getName()+"/"+previousSymbol.getSymbol().getName()); + out.append(" "+previousSymbol.getBlock().getLabel().getName()+"/"+previousSymbol.getRValue()); } out.append(" )"); return out.toString(); diff --git a/src/dk/camelot64/kickc/test/main.java b/src/dk/camelot64/kickc/test/main.java index 1b99c70b6..7ab72e3e4 100644 --- a/src/dk/camelot64/kickc/test/main.java +++ b/src/dk/camelot64/kickc/test/main.java @@ -25,16 +25,25 @@ public class main { new PassTypeInference().inferTypes(statementSequence, symbolTable); PassGenerateControlFlowGraph passGenerateControlFlowGraph = new PassGenerateControlFlowGraph(symbolTable); ControlFlowGraph controlFlowGraph = passGenerateControlFlowGraph.generate(statementSequence); + PassCullEmptyBlocks passCullEmptyBlocks = new PassCullEmptyBlocks(symbolTable, controlFlowGraph); + passCullEmptyBlocks.cull(); PassGenerateSingleStaticAssignmentForm passGenerateSingleStaticAssignmentForm = new PassGenerateSingleStaticAssignmentForm( symbolTable, controlFlowGraph); passGenerateSingleStaticAssignmentForm.generate(); + PassConstantPropagation passConstantPropagation = new PassConstantPropagation(symbolTable, controlFlowGraph); + passConstantPropagation.propagateConstants(); + PassAliasElimination passAliasElimination = new PassAliasElimination(symbolTable, controlFlowGraph); + passAliasElimination.eliminate(); + PassRedundantPhiElimination passRedundantPhiElimination = new PassRedundantPhiElimination(symbolTable, controlFlowGraph); + passRedundantPhiElimination.eliminate(); + PassCullEmptyBlocks passCullEmptyBlocks2 = new PassCullEmptyBlocks(symbolTable, controlFlowGraph); + passCullEmptyBlocks2.cull(); System.out.println("SYMBOLS"); System.out.println(symbolTable.toString()); System.out.println("PROGRAM"); System.out.println(statementSequence.toString()); System.out.println("CONTROL FLOW GRAPH"); System.out.println(controlFlowGraph.toString()); - } } diff --git a/src/dk/camelot64/kickc/test/test.kc b/src/dk/camelot64/kickc/test/test.kc index 76248d79f..8fa686ee9 100644 --- a/src/dk/camelot64/kickc/test/test.kc +++ b/src/dk/camelot64/kickc/test/test.kc @@ -1,10 +1,12 @@ byte a = 0; word b = 0; +byte d=a+b+1; while(a<10) { b=b+a; if(b>10) { b = b-10; } a=a+1; + byte e = d+d; } -byte c = -a; \ No newline at end of file +byte c = -d;