diff --git a/src/dk/camelot64/kickc/icl/Constant.java b/src/dk/camelot64/kickc/icl/Constant.java new file mode 100644 index 000000000..de4453b53 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/Constant.java @@ -0,0 +1,7 @@ +package dk.camelot64.kickc.icl; + +/** SSA form constant value */ +public interface Constant extends RValue { + + +} diff --git a/src/dk/camelot64/kickc/ssa/SSAConstantBool.java b/src/dk/camelot64/kickc/icl/ConstantBool.java similarity index 59% rename from src/dk/camelot64/kickc/ssa/SSAConstantBool.java rename to src/dk/camelot64/kickc/icl/ConstantBool.java index d57379687..8e89d70e2 100644 --- a/src/dk/camelot64/kickc/ssa/SSAConstantBool.java +++ b/src/dk/camelot64/kickc/icl/ConstantBool.java @@ -1,13 +1,13 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; /** * SSA form constant integer value */ -public class SSAConstantBool implements SSAConstant { +public class ConstantBool implements Constant { private Boolean value; - public SSAConstantBool(Boolean value) { + public ConstantBool(Boolean value) { this.value = value; } diff --git a/src/dk/camelot64/kickc/ssa/SSAConstantDouble.java b/src/dk/camelot64/kickc/icl/ConstantDouble.java similarity index 59% rename from src/dk/camelot64/kickc/ssa/SSAConstantDouble.java rename to src/dk/camelot64/kickc/icl/ConstantDouble.java index 47e201fc1..16ca8097d 100644 --- a/src/dk/camelot64/kickc/ssa/SSAConstantDouble.java +++ b/src/dk/camelot64/kickc/icl/ConstantDouble.java @@ -1,13 +1,13 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; /** * SSA form constant integer value */ -public class SSAConstantDouble implements SSAConstant { +public class ConstantDouble implements Constant { private Double number; - public SSAConstantDouble(Double number) { + public ConstantDouble(Double number) { this.number= number; } diff --git a/src/dk/camelot64/kickc/ssa/SSAConstantInteger.java b/src/dk/camelot64/kickc/icl/ConstantInteger.java similarity index 65% rename from src/dk/camelot64/kickc/ssa/SSAConstantInteger.java rename to src/dk/camelot64/kickc/icl/ConstantInteger.java index b45c90caa..0b42a91e2 100644 --- a/src/dk/camelot64/kickc/ssa/SSAConstantInteger.java +++ b/src/dk/camelot64/kickc/icl/ConstantInteger.java @@ -1,13 +1,13 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; /** * SSA form constant integer value */ -public class SSAConstantInteger implements SSAConstant { +public class ConstantInteger implements Constant { private Integer number; - public SSAConstantInteger(Integer number) { + public ConstantInteger(Integer number) { this.number = number; } diff --git a/src/dk/camelot64/kickc/ssa/SSAConstantString.java b/src/dk/camelot64/kickc/icl/ConstantString.java similarity index 58% rename from src/dk/camelot64/kickc/ssa/SSAConstantString.java rename to src/dk/camelot64/kickc/icl/ConstantString.java index 8fa21afff..63296076d 100644 --- a/src/dk/camelot64/kickc/ssa/SSAConstantString.java +++ b/src/dk/camelot64/kickc/icl/ConstantString.java @@ -1,13 +1,13 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; /** * SSA form constant integer value */ -public class SSAConstantString implements SSAConstant { +public class ConstantString implements Constant { private String value; - public SSAConstantString(String value) { + public ConstantString(String value) { this.value = value; } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java new file mode 100644 index 000000000..43934d202 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java @@ -0,0 +1,101 @@ +package dk.camelot64.kickc.icl; + +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. */ +public class ControlFlowBlock { + + private Symbol label; + + private List predecessors; + + private List statements; + + private ControlFlowBlock defaultSuccessor; + + private ControlFlowBlock conditionalSuccessor; + + public ControlFlowBlock(Symbol label) { + this.label = label; + this.statements = new ArrayList<>(); + this.predecessors = new ArrayList<>(); + this.defaultSuccessor = null; + this.conditionalSuccessor = null; + } + + public Symbol getLabel() { + return label; + } + + public void addStatement(Statement statement) { + this.statements.add(statement); + } + + public void addPredecessor(ControlFlowBlock block) { + this.predecessors.add(block); + } + + public void setDefaultSuccessor(ControlFlowBlock defaultSuccessor) { + this.defaultSuccessor = defaultSuccessor; + } + + public ControlFlowBlock getDefaultSuccessor() { + return defaultSuccessor; + } + + public ControlFlowBlock getConditionalSuccessor() { + return conditionalSuccessor; + } + + public List getPredecessors() { + return predecessors; + } + + public void setConditionalSuccessor(ControlFlowBlock conditionalSuccessor) { + this.conditionalSuccessor = conditionalSuccessor; + } + + public void removePredecessor(ControlFlowBlock block) { + predecessors.remove(block); + } + + public List getStatements() { + return statements; + } + + @Override + public String toString() { + StringBuffer out = new StringBuffer(); + out.append(label.getName() + ":" + "\n"); + out.append(" from:"); + for (ControlFlowBlock predecessor : predecessors) { + out.append(predecessor.getLabel().getName()+" "); + } + out.append("\n"); + for (Statement statement : statements) { + out.append(" "+statement+"\n"); + } + out.append(" to:"); + if(defaultSuccessor!=null) { + out.append(defaultSuccessor.getLabel().getName()); + } + out.append("\n"); + return out.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ControlFlowBlock that = (ControlFlowBlock) o; + return label.equals(that.label); + } + + @Override + public int hashCode() { + return label.hashCode(); + } + +} diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraph.java b/src/dk/camelot64/kickc/icl/ControlFlowGraph.java new file mode 100644 index 000000000..112ab3ef6 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraph.java @@ -0,0 +1,34 @@ +package dk.camelot64.kickc.icl; + +import java.util.Map; + +/** The control flow graph of the program. + * The control flow graph is a set of connected basic blocks. */ +public class ControlFlowGraph { + + private Map blocks; + + private ControlFlowBlock firstBlock; + + public ControlFlowGraph(Map blocks, ControlFlowBlock firstBlock) { + this.blocks = blocks; + this.firstBlock = firstBlock; + } + + public ControlFlowBlock getBlock(Symbol symbol) { + return blocks.get(symbol); + } + + public ControlFlowBlock getFirstBlock() { + return firstBlock; + } + + @Override + public String toString() { + StringBuffer out = new StringBuffer(); + for (ControlFlowBlock block : blocks.values()) { + out.append(block); + } + return out.toString(); + } +} diff --git a/src/dk/camelot64/kickc/icl/LValue.java b/src/dk/camelot64/kickc/icl/LValue.java new file mode 100644 index 000000000..ae0c4ffe3 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/LValue.java @@ -0,0 +1,5 @@ +package dk.camelot64.kickc.icl; + +/** Assignable value (capable of being on the left part of an assignment)*/ +public interface LValue { +} diff --git a/src/dk/camelot64/kickc/ssa/KickCNumberParser.java b/src/dk/camelot64/kickc/icl/NumberParser.java similarity index 94% rename from src/dk/camelot64/kickc/ssa/KickCNumberParser.java rename to src/dk/camelot64/kickc/icl/NumberParser.java index 4cab556b0..35fba88c6 100644 --- a/src/dk/camelot64/kickc/ssa/KickCNumberParser.java +++ b/src/dk/camelot64/kickc/icl/NumberParser.java @@ -1,7 +1,7 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; /** Parser for converting literal numbers to the corresponding Java Integer/Double */ -public class KickCNumberParser { +public class NumberParser { public static Number parseLiteral(String literal) { boolean isInt = !literal.contains("."); diff --git a/src/dk/camelot64/kickc/ssa/SSAOperator.java b/src/dk/camelot64/kickc/icl/Operator.java similarity index 52% rename from src/dk/camelot64/kickc/ssa/SSAOperator.java rename to src/dk/camelot64/kickc/icl/Operator.java index c3a80eaac..f80aef649 100644 --- a/src/dk/camelot64/kickc/ssa/SSAOperator.java +++ b/src/dk/camelot64/kickc/icl/Operator.java @@ -1,11 +1,11 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; -/** SSA Form Operator. The operation performed on the rvalues in an SSA Statement. */ -public class SSAOperator { +/** An Operator. The operation performed on the rvalues in a Statement. */ +public class Operator { private String operator; - public SSAOperator(String operator) { + public Operator(String operator) { this.operator = operator; } diff --git a/src/dk/camelot64/kickc/icl/PassGenerateControlFlowGraph.java b/src/dk/camelot64/kickc/icl/PassGenerateControlFlowGraph.java new file mode 100644 index 000000000..a3ba3c72b --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PassGenerateControlFlowGraph.java @@ -0,0 +1,91 @@ +package dk.camelot64.kickc.icl; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** Pass that generates a control flow graph for the program */ +public class PassGenerateControlFlowGraph { + + public static final String FIRST_BLOCK_NAME = "@0"; + private SymbolManager symbolManager; + private Map blocks; + private ControlFlowBlock firstBlock; + + public PassGenerateControlFlowGraph(SymbolManager symbolManager) { + this.symbolManager = symbolManager; + this.blocks = new LinkedHashMap<>(); + } + + public ControlFlowGraph generate(StatementSequence sequence) { + this.firstBlock = getOrCreateBlock(symbolManager.newNamedJumpLabel(FIRST_BLOCK_NAME)); + ControlFlowBlock currentBlock = this.firstBlock; + for (Statement statement : sequence.getStatements()) { + if(statement instanceof StatementJumpTarget) { + StatementJumpTarget statementJumpTarget = (StatementJumpTarget) statement; + ControlFlowBlock nextBlock = getOrCreateBlock(statementJumpTarget.getLabel()); + currentBlock.setDefaultSuccessor(nextBlock); + nextBlock.addPredecessor(currentBlock); + currentBlock = nextBlock; + } else if(statement instanceof StatementJump) { + StatementJump statementJump = (StatementJump) statement; + ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination()); + currentBlock.setDefaultSuccessor(jmpBlock); + jmpBlock.addPredecessor(currentBlock); + ControlFlowBlock nextBlock = getOrCreateBlock(symbolManager.newIntermediateJumpLabel()); + currentBlock = nextBlock; + } else if(statement instanceof StatementConditionalJump) { + currentBlock.addStatement(statement); + StatementConditionalJump statementConditionalJump = (StatementConditionalJump) statement; + ControlFlowBlock jmpBlock = getOrCreateBlock(statementConditionalJump.getDestination()); + ControlFlowBlock nextBlock = getOrCreateBlock(symbolManager.newIntermediateJumpLabel()); + currentBlock.setDefaultSuccessor(nextBlock); + currentBlock.setConditionalSuccessor(jmpBlock); + nextBlock.addPredecessor(currentBlock); + jmpBlock.addPredecessor(currentBlock); + currentBlock = nextBlock; + } else { + 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()); + symbolManager.remove(block.getLabel()); + } + } + + private ControlFlowBlock getOrCreateBlock(Symbol label) { + ControlFlowBlock block = blocks.get(label); + if(block==null) { + block = new ControlFlowBlock(label); + blocks.put(block.getLabel(), block); + } + return block; + } + + +} diff --git a/src/dk/camelot64/kickc/icl/PassGenerateStatementSequence.java b/src/dk/camelot64/kickc/icl/PassGenerateStatementSequence.java new file mode 100644 index 000000000..a0fe3f05e --- /dev/null +++ b/src/dk/camelot64/kickc/icl/PassGenerateStatementSequence.java @@ -0,0 +1,172 @@ +package dk.camelot64.kickc.icl; + +import dk.camelot64.kickc.parser.KickCBaseVisitor; +import dk.camelot64.kickc.parser.KickCParser; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** Generates program SSA form by visiting the ANTLR4 parse tree*/ +public class PassGenerateStatementSequence extends KickCBaseVisitor { + + private SymbolManager symbolManager; + private StatementSequence sequence; + + public PassGenerateStatementSequence() { + this.symbolManager = new SymbolManager(); + this.sequence = new StatementSequence(); + } + + @Override + public RValue visitFile(KickCParser.FileContext ctx) { + this.visit(ctx.stmtSeq()); + return null; + } + + + @Override + public RValue visitStmtSeq(KickCParser.StmtSeqContext ctx) { + for(int i=0; i * lValue := rValue1 <operator> rValue2 */ -public class SSAStatementAssignment implements SSAStatement { +public class StatementAssignment implements Statement { /** The variable being assigned a value by the statement. */ - private SSALValue lValue; + private LValue lValue; - private SSARValue rValue1; - private SSAOperator operator; - private SSARValue rValue2; + private RValue rValue1; + private Operator operator; + private RValue rValue2; - public SSAStatementAssignment(SSALValue lValue, SSARValue rValue2) { + public StatementAssignment(LValue lValue, RValue rValue2) { this.lValue = lValue; this.rValue1 = null; this.operator = null; this.rValue2 = rValue2; } - public SSAStatementAssignment(SSALValue lValue, SSARValue rValue1, SSAOperator operator, SSARValue rValue2) { + public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) { this.lValue = lValue; this.rValue1 = rValue1; this.operator = operator; this.rValue2 = rValue2; } - public SSAStatementAssignment(SSALValue lValue, SSAOperator operator, SSARValue rValue2) { + public StatementAssignment(LValue lValue, Operator operator, RValue rValue2) { this.lValue = lValue; this.rValue1 = null; this.operator = operator; this.rValue2 = rValue2; } - public SSALValue getlValue() { + public LValue getlValue() { return lValue; } - public SSARValue getRValue1() { + public RValue getRValue1() { return rValue1; } - public SSAOperator getOperator() { + public Operator getOperator() { return operator; } - public SSARValue getRValue2() { + public RValue getRValue2() { return rValue2; } @Override public String toString() { return - " "+ + lValue + " ← " + (rValue1==null?"":rValue1+" ") + (operator==null?"":operator+" ") + diff --git a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java new file mode 100644 index 000000000..4b0ab6a75 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java @@ -0,0 +1,31 @@ +package dk.camelot64.kickc.icl; + +/** + * Intermediate Compiler Form Statement with a conditional jump. + * Intermediate form used for compiler optimization. + *
+ * if ( Yj ) goto XX + */ +public class StatementConditionalJump implements Statement { + + private RValue condition; + private Symbol destination; + + public StatementConditionalJump(RValue condition, Symbol destination) { + this.condition = condition; + this.destination = destination; + } + + public RValue getCondition() { + return condition; + } + + public Symbol getDestination() { + return destination; + } + + @Override + public String toString() { + return "if("+condition+") goto "+destination.getName(); + } +} diff --git a/src/dk/camelot64/kickc/ssa/SSAStatementJump.java b/src/dk/camelot64/kickc/icl/StatementJump.java similarity index 51% rename from src/dk/camelot64/kickc/ssa/SSAStatementJump.java rename to src/dk/camelot64/kickc/icl/StatementJump.java index 767406270..d22c5b6b7 100644 --- a/src/dk/camelot64/kickc/ssa/SSAStatementJump.java +++ b/src/dk/camelot64/kickc/icl/StatementJump.java @@ -1,4 +1,4 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; /** * Single Static Assignment Form Statement unconditional jump. @@ -6,20 +6,20 @@ package dk.camelot64.kickc.ssa; *
* goto XX */ -public class SSAStatementJump implements SSAStatement { +public class StatementJump implements Statement { - private SSAJumpLabel destination; + private Symbol destination; - public SSAStatementJump(SSAJumpLabel destination) { + public StatementJump(Symbol destination) { this.destination = destination; } - public SSAJumpLabel getDestination() { + public Symbol getDestination() { return destination; } @Override public String toString() { - return " "+"goto "+destination; + return "goto "+destination.getName(); } } diff --git a/src/dk/camelot64/kickc/icl/StatementJumpTarget.java b/src/dk/camelot64/kickc/icl/StatementJumpTarget.java new file mode 100644 index 000000000..7de1ebe1c --- /dev/null +++ b/src/dk/camelot64/kickc/icl/StatementJumpTarget.java @@ -0,0 +1,24 @@ +package dk.camelot64.kickc.icl; + +/** + * Single Static Assignment Form Statement Jump target. + */ +public class StatementJumpTarget implements Statement { + + private Symbol label; + + public StatementJumpTarget(Symbol label) { + this.label = label; + } + + public Symbol getLabel() { + return label; + } + + @Override + public String toString() { + return label+":"; + } + + +} diff --git a/src/dk/camelot64/kickc/icl/StatementSequence.java b/src/dk/camelot64/kickc/icl/StatementSequence.java new file mode 100644 index 000000000..83294f0fc --- /dev/null +++ b/src/dk/camelot64/kickc/icl/StatementSequence.java @@ -0,0 +1,34 @@ +package dk.camelot64.kickc.icl; + +import java.util.ArrayList; +import java.util.List; + +/** A sequence of Statements */ +public class StatementSequence { + + private List statements; + + public StatementSequence() { + this.statements = new ArrayList<>(); + } + + public void addStatement(Statement statement) { + this.statements.add(statement); + } + + @Override + public String toString() { + StringBuffer out = new StringBuffer(); + for (Statement statement : statements) { + if(!(statement instanceof StatementJumpTarget)) { + out.append(" "); + } + out.append(statement.toString()+"\n"); + } + return out.toString(); + } + + public List getStatements() { + return statements; + } +} diff --git a/src/dk/camelot64/kickc/icl/Symbol.java b/src/dk/camelot64/kickc/icl/Symbol.java new file mode 100644 index 000000000..20b05c94f --- /dev/null +++ b/src/dk/camelot64/kickc/icl/Symbol.java @@ -0,0 +1,62 @@ +package dk.camelot64.kickc.icl; + +/** A Symbol (variable, jump label, etc.) */ +public class Symbol implements RValue, LValue { + + private String name; + + private SymbolType type; + + private boolean intermediate; + + private boolean inferredType; + + public Symbol(String name, SymbolType type, boolean intermediate) { + this.name = name; + this.type = type; + this.intermediate = intermediate; + this.inferredType = false; + } + + public String getName() { + return name; + } + + public SymbolType getType() { + return type; + } + + public void setInferredType(SymbolType type) { + this.type = type; + this.inferredType = true; + } + + public boolean isIntermediate() { + return intermediate; + } + + @Override + public String toString() { + return "("+name + ": " + type.getTypeName() + (inferredType ?"*":"") + ")"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Symbol symbol = (Symbol) o; + if (intermediate != symbol.intermediate) return false; + if (inferredType != symbol.inferredType) return false; + if (!name.equals(symbol.name)) return false; + return type == symbol.type; + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + (type != null ? type.hashCode() : 0); + result = 31 * result + (intermediate ? 1 : 0); + result = 31 * result + (inferredType ? 1 : 0); + return result; + } +} diff --git a/src/dk/camelot64/kickc/ssa/SymbolManager.java b/src/dk/camelot64/kickc/icl/SymbolManager.java similarity index 81% rename from src/dk/camelot64/kickc/ssa/SymbolManager.java rename to src/dk/camelot64/kickc/icl/SymbolManager.java index 656d9757a..67145768c 100644 --- a/src/dk/camelot64/kickc/ssa/SymbolManager.java +++ b/src/dk/camelot64/kickc/icl/SymbolManager.java @@ -1,4 +1,4 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; import java.util.LinkedHashMap; import java.util.Map; @@ -11,7 +11,7 @@ public class SymbolManager { private Map symbols; private int intermediateVarCount = 0; - private int intermediateLabelCount = 0; + private int intermediateLabelCount = 1; public SymbolManager() { this.symbols = new LinkedHashMap<>(); @@ -45,15 +45,15 @@ public class SymbolManager { return symbol; } - public SSAJumpLabel newNamedJumpLabel(String name) { + public Symbol newNamedJumpLabel(String name) { Symbol symbol = addSymbol(name, SymbolType.LABEL, false); - return new SSAJumpLabel(name); + return symbol; } - public SSAJumpLabel newIntermediateJumpLabel() { + public Symbol newIntermediateJumpLabel() { String name = "@"+ intermediateLabelCount++; - addSymbol(name, SymbolType.LABEL, true); - return new SSAJumpLabel(name); + Symbol symbol = addSymbol(name, SymbolType.LABEL, true); + return symbol; } @Override @@ -65,4 +65,8 @@ public class SymbolManager { } return out.toString(); } + + public void remove(Symbol symbol) { + symbols.remove(symbol.getName()); + } } diff --git a/src/dk/camelot64/kickc/ssa/SymbolType.java b/src/dk/camelot64/kickc/icl/SymbolType.java similarity index 94% rename from src/dk/camelot64/kickc/ssa/SymbolType.java rename to src/dk/camelot64/kickc/icl/SymbolType.java index cd7451243..d66bf44f8 100644 --- a/src/dk/camelot64/kickc/ssa/SymbolType.java +++ b/src/dk/camelot64/kickc/icl/SymbolType.java @@ -1,4 +1,4 @@ -package dk.camelot64.kickc.ssa; +package dk.camelot64.kickc.icl; /** Symbol Types */ public enum SymbolType { diff --git a/src/dk/camelot64/kickc/ssa/GenerateSSA.java b/src/dk/camelot64/kickc/ssa/GenerateSSA.java deleted file mode 100644 index 64c710541..000000000 --- a/src/dk/camelot64/kickc/ssa/GenerateSSA.java +++ /dev/null @@ -1,172 +0,0 @@ -package dk.camelot64.kickc.ssa; - -import dk.camelot64.kickc.parser.KickCBaseVisitor; -import dk.camelot64.kickc.parser.KickCParser; -import org.antlr.v4.runtime.tree.TerminalNode; - -/** Generates program SSA form by visiting the ANTLR4 parse tree*/ -public class GenerateSSA extends KickCBaseVisitor { - - private SymbolManager symbolManager; - private SSASequence sequence; - - public GenerateSSA() { - this.symbolManager = new SymbolManager(); - this.sequence = new SSASequence(); - } - - @Override - public SSARValue visitFile(KickCParser.FileContext ctx) { - this.visit(ctx.stmtSeq()); - return null; - } - - - @Override - public SSARValue visitStmtSeq(KickCParser.StmtSeqContext ctx) { - for(int i=0; i statements; - - public SSABasicBlock() { - this.statements = new ArrayList<>(); - } - - public void addStatement(SSAStatement statement) { - this.statements.add(statement); - } - - @Override - public String toString() { - return "SSABasicBlock{" + - "statements=" + statements + - '}'; - } -} diff --git a/src/dk/camelot64/kickc/ssa/SSAConstant.java b/src/dk/camelot64/kickc/ssa/SSAConstant.java deleted file mode 100644 index c6f1c3f60..000000000 --- a/src/dk/camelot64/kickc/ssa/SSAConstant.java +++ /dev/null @@ -1,7 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** SSA form constant value */ -public interface SSAConstant extends SSARValue, SSAFragment { - - -} diff --git a/src/dk/camelot64/kickc/ssa/SSAFragment.java b/src/dk/camelot64/kickc/ssa/SSAFragment.java deleted file mode 100644 index aed11352c..000000000 --- a/src/dk/camelot64/kickc/ssa/SSAFragment.java +++ /dev/null @@ -1,7 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** - * Any SSA Form fragment resulting from translating a part of the parse tree - */ -public interface SSAFragment { -} diff --git a/src/dk/camelot64/kickc/ssa/SSAJumpLabel.java b/src/dk/camelot64/kickc/ssa/SSAJumpLabel.java deleted file mode 100644 index 2913fc646..000000000 --- a/src/dk/camelot64/kickc/ssa/SSAJumpLabel.java +++ /dev/null @@ -1,16 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** A label representing a target of a jump in SSA code */ -public class SSAJumpLabel { - - private String name; - - public SSAJumpLabel(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } -} diff --git a/src/dk/camelot64/kickc/ssa/SSALValue.java b/src/dk/camelot64/kickc/ssa/SSALValue.java deleted file mode 100644 index 8d081983f..000000000 --- a/src/dk/camelot64/kickc/ssa/SSALValue.java +++ /dev/null @@ -1,5 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** Left value in SSA Form */ -public interface SSALValue { -} diff --git a/src/dk/camelot64/kickc/ssa/SSARValue.java b/src/dk/camelot64/kickc/ssa/SSARValue.java deleted file mode 100644 index b479b6bda..000000000 --- a/src/dk/camelot64/kickc/ssa/SSARValue.java +++ /dev/null @@ -1,5 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** Right value in SSA FORM */ -public interface SSARValue { -} diff --git a/src/dk/camelot64/kickc/ssa/SSASequence.java b/src/dk/camelot64/kickc/ssa/SSASequence.java deleted file mode 100644 index fe91bdd1a..000000000 --- a/src/dk/camelot64/kickc/ssa/SSASequence.java +++ /dev/null @@ -1,33 +0,0 @@ -package dk.camelot64.kickc.ssa; - -import java.util.ArrayList; -import java.util.List; - -/** - * A sequence of SSA Statements - */ -public class SSASequence { - - List statements; - - public SSASequence() { - this.statements = new ArrayList<>(); - } - - public void addStatement(SSAStatement statement) { - this.statements.add(statement); - } - - @Override - public String toString() { - StringBuffer out = new StringBuffer(); - for (SSAStatement statement : statements) { - out.append(statement.toString()+"\n"); - } - return out.toString(); - } - - public List getStatements() { - return statements; - } -} diff --git a/src/dk/camelot64/kickc/ssa/SSAStatementConditionalJump.java b/src/dk/camelot64/kickc/ssa/SSAStatementConditionalJump.java deleted file mode 100644 index 5b0726c09..000000000 --- a/src/dk/camelot64/kickc/ssa/SSAStatementConditionalJump.java +++ /dev/null @@ -1,31 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** - * Single Static Assignment Form Statement with a conditional jump. - * Intermediate form used for compiler optimization. - *
- * if ( Yj ) goto XX - */ -public class SSAStatementConditionalJump implements SSAStatement { - - private SSARValue condition; - private SSAJumpLabel destination; - - public SSAStatementConditionalJump(SSARValue condition, SSAJumpLabel destination) { - this.condition = condition; - this.destination = destination; - } - - public SSARValue getCondition() { - return condition; - } - - public SSAJumpLabel getDestination() { - return destination; - } - - @Override - public String toString() { - return " "+"if("+condition+") goto "+destination; - } -} diff --git a/src/dk/camelot64/kickc/ssa/SSAStatementJumpTarget.java b/src/dk/camelot64/kickc/ssa/SSAStatementJumpTarget.java deleted file mode 100644 index 4232b4bdb..000000000 --- a/src/dk/camelot64/kickc/ssa/SSAStatementJumpTarget.java +++ /dev/null @@ -1,24 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** - * Single Static Assignment Form Statement Jump target. - */ -public class SSAStatementJumpTarget implements SSAStatement { - - private SSAJumpLabel label; - - public SSAStatementJumpTarget(SSAJumpLabel label) { - this.label = label; - } - - public SSAJumpLabel getLabel() { - return label; - } - - @Override - public String toString() { - return label+":"; - } - - -} diff --git a/src/dk/camelot64/kickc/ssa/SSAVariable.java b/src/dk/camelot64/kickc/ssa/SSAVariable.java deleted file mode 100644 index 674832225..000000000 --- a/src/dk/camelot64/kickc/ssa/SSAVariable.java +++ /dev/null @@ -1,40 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** An SSA form Variable. SSA form variables come in different flavors: - *
    - *
  • Each potential modification of a language variable becomes a separate versioned SSA variable.
  • - *
  • Expressions are broken into separate SSA statements, each defining a new temporary/intermediate variable.
  • - *
- * - * Named variables are initially created without serials. These are first added after the basic control blocks have been defined. - * - * */ -public class SSAVariable implements SSARValue, SSALValue, SSAFragment { - - private String name; - - private Integer serial; - - public SSAVariable(String name) { - this.name = name; - this.serial = null; - } - - public SSAVariable(String name, int serial) { - this.name = name; - this.serial = serial; - } - - public String getName() { - return name; - } - - public int getSerial() { - return serial; - } - - @Override - public String toString() { - return name + (serial==null?"":"_"+serial); - } -} diff --git a/src/dk/camelot64/kickc/ssa/Symbol.java b/src/dk/camelot64/kickc/ssa/Symbol.java deleted file mode 100644 index cfa7991d2..000000000 --- a/src/dk/camelot64/kickc/ssa/Symbol.java +++ /dev/null @@ -1,43 +0,0 @@ -package dk.camelot64.kickc.ssa; - -/** A Symbol (variable, jump label, etc.) */ -public class Symbol implements SSARValue, SSALValue, SSAFragment { - - private String name; - - private SymbolType type; - - private boolean intermediate; - - private boolean inferredType; - - public Symbol(String name, SymbolType type, boolean intermediate) { - this.name = name; - this.type = type; - this.intermediate = intermediate; - this.inferredType = false; - } - - public String getName() { - return name; - } - - public SymbolType getType() { - return type; - } - - public void setInferredType(SymbolType type) { - this.type = type; - this.inferredType = true; - } - - public boolean isIntermediate() { - return intermediate; - } - - @Override - public String toString() { - return "("+name + (intermediate?"*":"") + ": " + type.getTypeName() + (inferredType ?"*":"") + ")"; - } - -} diff --git a/src/dk/camelot64/kickc/test/main.java b/src/dk/camelot64/kickc/test/main.java index 9140a0000..4aa97f8fc 100644 --- a/src/dk/camelot64/kickc/test/main.java +++ b/src/dk/camelot64/kickc/test/main.java @@ -1,10 +1,11 @@ package dk.camelot64.kickc.test; +import dk.camelot64.kickc.icl.ControlFlowGraph; +import dk.camelot64.kickc.icl.PassGenerateControlFlowGraph; import dk.camelot64.kickc.parser.KickCLexer; import dk.camelot64.kickc.parser.KickCParser; -import dk.camelot64.kickc.ssa.GenerateSSA; -import dk.camelot64.kickc.ssa.PassTypeInference; -import dk.camelot64.kickc.ssa.SSASequence; +import dk.camelot64.kickc.icl.PassGenerateStatementSequence; +import dk.camelot64.kickc.icl.PassTypeInference; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; @@ -20,16 +21,18 @@ public class main { KickCParser parser = new KickCParser(new CommonTokenStream(lexer)); parser.setBuildParseTree(true); KickCParser.FileContext file = parser.file(); - GenerateSSA ev = new GenerateSSA(); - ev.visit(file); - - PassTypeInference passTypeInference = new PassTypeInference(); - passTypeInference.inferTypes(ev.getSequence(), ev.getSymbols()); - - System.out.println("PROGRAM"); - System.out.println(ev.getSequence().toString()); + PassGenerateStatementSequence passGenerateStatementSequence = new PassGenerateStatementSequence(); + passGenerateStatementSequence.visit(file); + new PassTypeInference().inferTypes(passGenerateStatementSequence.getSequence(), passGenerateStatementSequence.getSymbols()); + PassGenerateControlFlowGraph passGenerateControlFlowGraph = new PassGenerateControlFlowGraph(passGenerateStatementSequence.getSymbols()); + ControlFlowGraph controlFlowGraph = passGenerateControlFlowGraph.generate(passGenerateStatementSequence.getSequence()); System.out.println("SYMBOLS"); - System.out.println(ev.getSymbols().toString()); + System.out.println(passGenerateStatementSequence.getSymbols().toString()); + System.out.println("PROGRAM"); + System.out.println(passGenerateStatementSequence.getSequence().toString()); + System.out.println("CONTROL FLOW GRAPH"); + System.out.println(controlFlowGraph.toString()); + } }