mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-22 21:29:50 +00:00
Typified all Symbols
This commit is contained in:
parent
3b8580498b
commit
73fa2839e0
@ -7,7 +7,7 @@ import java.util.List;
|
||||
* The connections defines the control flow of the program. */
|
||||
public class ControlFlowBlock {
|
||||
|
||||
private Symbol label;
|
||||
private Label label;
|
||||
|
||||
private List<ControlFlowBlock> predecessors;
|
||||
|
||||
@ -17,7 +17,7 @@ public class ControlFlowBlock {
|
||||
|
||||
private ControlFlowBlock conditionalSuccessor;
|
||||
|
||||
public ControlFlowBlock(Symbol label) {
|
||||
public ControlFlowBlock(Label label) {
|
||||
this.label = label;
|
||||
this.statements = new ArrayList<>();
|
||||
this.predecessors = new ArrayList<>();
|
||||
@ -25,7 +25,7 @@ public class ControlFlowBlock {
|
||||
this.conditionalSuccessor = null;
|
||||
}
|
||||
|
||||
public Symbol getLabel() {
|
||||
public Label getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ public class ControlFlowBlock {
|
||||
return statements;
|
||||
}
|
||||
|
||||
public void addPhiStatement(Symbol newVersion) {
|
||||
public void addPhiStatement(VariableVersion newVersion) {
|
||||
statements.add(0, new StatementPhi(newVersion));
|
||||
}
|
||||
|
||||
|
51
src/dk/camelot64/kickc/icl/Label.java
Normal file
51
src/dk/camelot64/kickc/icl/Label.java
Normal file
@ -0,0 +1,51 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
public class Label implements Symbol {
|
||||
|
||||
/** The name of the label. */
|
||||
private String name;
|
||||
|
||||
private boolean intermediate;
|
||||
|
||||
public Label(String name, boolean intermediate) {
|
||||
this.name = name;
|
||||
this.intermediate = intermediate;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isIntermediate() {
|
||||
return intermediate;
|
||||
}
|
||||
|
||||
public SymbolType getType() {
|
||||
return SymbolType.LABEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "("+getType().getTypeName() + ") "+name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Label that = (Label) o;
|
||||
|
||||
return name.equals(that.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
}
|
@ -9,17 +9,17 @@ import java.util.Map;
|
||||
public class PassGenerateControlFlowGraph {
|
||||
|
||||
public static final String FIRST_BLOCK_NAME = "@0";
|
||||
private SymbolManager symbolManager;
|
||||
private SymbolTable symbolTable;
|
||||
private Map<Symbol, ControlFlowBlock> blocks;
|
||||
private ControlFlowBlock firstBlock;
|
||||
|
||||
public PassGenerateControlFlowGraph(SymbolManager symbolManager) {
|
||||
this.symbolManager = symbolManager;
|
||||
public PassGenerateControlFlowGraph(SymbolTable symbolTable) {
|
||||
this.symbolTable = symbolTable;
|
||||
this.blocks = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public ControlFlowGraph generate(StatementSequence sequence) {
|
||||
this.firstBlock = getOrCreateBlock(symbolManager.newNamedJumpLabel(FIRST_BLOCK_NAME));
|
||||
this.firstBlock = getOrCreateBlock(symbolTable.newNamedJumpLabel(FIRST_BLOCK_NAME));
|
||||
ControlFlowBlock currentBlock = this.firstBlock;
|
||||
for (Statement statement : sequence.getStatements()) {
|
||||
if(statement instanceof StatementJumpTarget) {
|
||||
@ -33,13 +33,13 @@ public class PassGenerateControlFlowGraph {
|
||||
ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination());
|
||||
currentBlock.setDefaultSuccessor(jmpBlock);
|
||||
jmpBlock.addPredecessor(currentBlock);
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(symbolManager.newIntermediateJumpLabel());
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.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());
|
||||
ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.newIntermediateJumpLabel());
|
||||
currentBlock.setDefaultSuccessor(nextBlock);
|
||||
currentBlock.setConditionalSuccessor(jmpBlock);
|
||||
nextBlock.addPredecessor(currentBlock);
|
||||
@ -74,11 +74,11 @@ public class PassGenerateControlFlowGraph {
|
||||
}
|
||||
for (ControlFlowBlock block : remove) {
|
||||
blocks.remove(block.getLabel());
|
||||
symbolManager.remove(block.getLabel());
|
||||
symbolTable.remove(block.getLabel());
|
||||
}
|
||||
}
|
||||
|
||||
private ControlFlowBlock getOrCreateBlock(Symbol label) {
|
||||
private ControlFlowBlock getOrCreateBlock(Label label) {
|
||||
ControlFlowBlock block = blocks.get(label);
|
||||
if(block==null) {
|
||||
block = new ControlFlowBlock(label);
|
||||
|
@ -10,10 +10,10 @@ import java.util.Map;
|
||||
*/
|
||||
public class PassGenerateSingleStaticAssignmentForm {
|
||||
|
||||
private SymbolManager symbols;
|
||||
private SymbolTable symbols;
|
||||
private ControlFlowGraph controlFlowGraph;
|
||||
|
||||
public PassGenerateSingleStaticAssignmentForm(SymbolManager symbols, ControlFlowGraph controlFlowGraph) {
|
||||
public PassGenerateSingleStaticAssignmentForm(SymbolTable symbols, ControlFlowGraph controlFlowGraph) {
|
||||
this.symbols = symbols;
|
||||
this.controlFlowGraph = controlFlowGraph;
|
||||
}
|
||||
@ -21,25 +21,24 @@ public class PassGenerateSingleStaticAssignmentForm {
|
||||
public void generate() {
|
||||
versionAllAssignments();
|
||||
versionAllUses();
|
||||
boolean done = false;
|
||||
boolean done;
|
||||
do {
|
||||
System.out.println("Completing Phi functions...");
|
||||
done = completePhiFunctions();
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Version all non-versioned non-intermediary being assigned a value. */
|
||||
private void versionAllAssignments() {
|
||||
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
Symbol assignedSymbol = (Symbol) assignment.getlValue();
|
||||
if (!assignedSymbol.isIntermediate() && !assignedSymbol.isVersioned()) {
|
||||
LValue lValue = assignment.getlValue();
|
||||
if(lValue instanceof VariableUnversioned) {
|
||||
// Assignment to a non-versioned non-intermediary variable
|
||||
Symbol version = symbols.createVersion(assignedSymbol);
|
||||
VariableUnversioned assignedSymbol = (VariableUnversioned) lValue;
|
||||
VariableVersion version = symbols.createVersion(assignedSymbol);
|
||||
assignment.setLValue(version);
|
||||
}
|
||||
}
|
||||
@ -51,33 +50,34 @@ public class PassGenerateSingleStaticAssignmentForm {
|
||||
private void versionAllUses() {
|
||||
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
|
||||
// Newest version of variables in the block.
|
||||
Map<Symbol, Symbol> blockVersions = new HashMap<>();
|
||||
Map<VariableUnversioned, VariableVersion> blockVersions = new HashMap<>();
|
||||
// New phi functions introduced in the block to create versions of variables.
|
||||
Map<Symbol, Symbol> blockNewPhis = new HashMap<>();
|
||||
Map<VariableUnversioned, VariableVersion> blockNewPhis = new HashMap<>();
|
||||
for (Statement statement : block.getStatements()) {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
{
|
||||
Symbol version = findOrCreateVersion(assignment.getRValue1(), blockVersions, blockNewPhis);
|
||||
VariableVersion version = findOrCreateVersion(assignment.getRValue1(), blockVersions, blockNewPhis);
|
||||
if (version != null) {
|
||||
assignment.setRValue1(version);
|
||||
}
|
||||
}
|
||||
{
|
||||
Symbol version = findOrCreateVersion(assignment.getRValue2(), blockVersions, blockNewPhis);
|
||||
VariableVersion version = findOrCreateVersion(assignment.getRValue2(), blockVersions, blockNewPhis);
|
||||
if (version != null) {
|
||||
assignment.setRValue2(version);
|
||||
}
|
||||
}
|
||||
// Update map of versions encountered in the block
|
||||
Symbol lSymbol = (Symbol) assignment.getlValue();
|
||||
if (lSymbol.isVersioned()) {
|
||||
blockVersions.put(lSymbol.getVersionOf(), lSymbol);
|
||||
LValue lValue = assignment.getlValue();
|
||||
if (lValue instanceof VariableVersion) {
|
||||
VariableVersion versioned = (VariableVersion) lValue;
|
||||
blockVersions.put(versioned.getVersionOf(), versioned);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add new Phi functions to block
|
||||
for (Symbol symbol : blockNewPhis.keySet()) {
|
||||
for (VariableUnversioned symbol : blockNewPhis.keySet()) {
|
||||
block.addPhiStatement(blockNewPhis.get(symbol));
|
||||
}
|
||||
}
|
||||
@ -92,22 +92,23 @@ public class PassGenerateSingleStaticAssignmentForm {
|
||||
* @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) {
|
||||
Symbol rSymbol = (Symbol) rValue;
|
||||
if (!rSymbol.isIntermediate() && !rSymbol.isVersioned()) {
|
||||
// rValue needs versioning - look for version in statements
|
||||
version = blockVersions.get(rSymbol);
|
||||
if (version == null) {
|
||||
// look for version in new phi functions
|
||||
version = blockNewPhis.get(rSymbol);
|
||||
}
|
||||
if (version == null) {
|
||||
// create a new phi function
|
||||
version = symbols.createVersion(rSymbol);
|
||||
blockNewPhis.put(rSymbol, version);
|
||||
}
|
||||
private VariableVersion findOrCreateVersion(
|
||||
RValue rValue,
|
||||
Map<VariableUnversioned, VariableVersion> blockVersions,
|
||||
Map<VariableUnversioned, VariableVersion> blockNewPhis) {
|
||||
VariableVersion version = null;
|
||||
if (rValue instanceof VariableUnversioned) {
|
||||
// rValue needs versioning - look for version in statements
|
||||
VariableUnversioned rSymbol = (VariableUnversioned) rValue;
|
||||
version = blockVersions.get(rSymbol);
|
||||
if (version == null) {
|
||||
// look for version in new phi functions
|
||||
version = blockNewPhis.get(rSymbol);
|
||||
}
|
||||
if (version == null) {
|
||||
// create a new phi function
|
||||
version = symbols.createVersion(rSymbol);
|
||||
blockNewPhis.put(rSymbol, version);
|
||||
}
|
||||
}
|
||||
return version;
|
||||
@ -118,20 +119,20 @@ public class PassGenerateSingleStaticAssignmentForm {
|
||||
* 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();
|
||||
Map<ControlFlowBlock, Map<VariableUnversioned, VariableVersion>> newPhis = new HashMap<>();
|
||||
Map<Label, Map<VariableUnversioned, VariableVersion>> 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();
|
||||
VariableVersion versioned = phi.getlValue();
|
||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
||||
for (ControlFlowBlock predecessor : block.getPredecessors()) {
|
||||
Symbol previousSymbol = symbolMap.get(predecessor.getLabel()).get(unversioned);
|
||||
VariableVersion 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);
|
||||
Map<VariableUnversioned, VariableVersion> predecessorNewPhis = newPhis.get(predecessor);
|
||||
if (predecessorNewPhis == null) {
|
||||
predecessorNewPhis = new HashMap<>();
|
||||
newPhis.put(predecessor, predecessorNewPhis);
|
||||
@ -151,9 +152,9 @@ public class PassGenerateSingleStaticAssignmentForm {
|
||||
}
|
||||
// Ads new phi functions to blocks
|
||||
for (ControlFlowBlock block : controlFlowGraph.getAllBlocks()) {
|
||||
Map<Symbol, Symbol> blockNewPhis = newPhis.get(block);
|
||||
Map<VariableUnversioned, VariableVersion> blockNewPhis = newPhis.get(block);
|
||||
if(blockNewPhis!=null) {
|
||||
for (Symbol symbol : blockNewPhis.keySet()) {
|
||||
for (VariableUnversioned symbol : blockNewPhis.keySet()) {
|
||||
block.addPhiStatement(blockNewPhis.get(symbol));
|
||||
}
|
||||
}
|
||||
@ -165,33 +166,30 @@ public class PassGenerateSingleStaticAssignmentForm {
|
||||
* 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<>();
|
||||
private Map<Label, Map<VariableUnversioned, VariableVersion>> buildSymbolMap() {
|
||||
Map<Label, Map<VariableUnversioned, VariableVersion>> 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);
|
||||
if(lValue instanceof VariableVersion) {
|
||||
VariableVersion versioned = (VariableVersion) lValue;
|
||||
Label label = block.getLabel();
|
||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
||||
Map<VariableUnversioned, VariableVersion> 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);
|
||||
VariableVersion versioned = phi.getlValue();
|
||||
VariableUnversioned unversioned = versioned.getVersionOf();
|
||||
Label label = block.getLabel();
|
||||
Map<VariableUnversioned, VariableVersion> blockMap = symbolMap.get(label);
|
||||
if(blockMap == null) {
|
||||
blockMap = new HashMap<>();
|
||||
symbolMap.put(label, blockMap);
|
||||
|
@ -7,11 +7,11 @@ import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
/** Generates program SSA form by visiting the ANTLR4 parse tree*/
|
||||
public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
|
||||
|
||||
private SymbolManager symbolManager;
|
||||
private SymbolTable symbolTable;
|
||||
private StatementSequence sequence;
|
||||
|
||||
public PassGenerateStatementSequence() {
|
||||
this.symbolManager = new SymbolManager();
|
||||
this.symbolTable = new SymbolTable();
|
||||
this.sequence = new StatementSequence();
|
||||
}
|
||||
|
||||
@ -49,8 +49,8 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
|
||||
@Override
|
||||
public RValue visitStmtIfElse(KickCParser.StmtIfElseContext ctx) {
|
||||
RValue rValue = this.visit(ctx.expr());
|
||||
Symbol ifJumpLabel = symbolManager.newIntermediateJumpLabel();
|
||||
Symbol elseJumpLabel = symbolManager.newIntermediateJumpLabel();
|
||||
Label ifJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Label elseJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Statement ifJmpStmt = new StatementConditionalJump(rValue, ifJumpLabel);
|
||||
sequence.addStatement(ifJmpStmt);
|
||||
Statement elseJmpStmt = new StatementJump(elseJumpLabel);
|
||||
@ -60,7 +60,7 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
|
||||
this.visit(ctx.stmt(0));
|
||||
KickCParser.StmtContext elseStmt = ctx.stmt(1);
|
||||
if(elseStmt!=null) {
|
||||
Symbol endJumpLabel = symbolManager.newIntermediateJumpLabel();
|
||||
Label endJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Statement endJmpStmt = new StatementJump(endJumpLabel);
|
||||
sequence.addStatement(endJmpStmt);
|
||||
StatementJumpTarget elseJumpTarget = new StatementJumpTarget(elseJumpLabel);
|
||||
@ -77,9 +77,9 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
|
||||
|
||||
@Override
|
||||
public RValue visitStmtWhile(KickCParser.StmtWhileContext ctx) {
|
||||
Symbol beginJumpLabel = symbolManager.newIntermediateJumpLabel();
|
||||
Symbol doJumpLabel = symbolManager.newIntermediateJumpLabel();
|
||||
Symbol endJumpLabel = symbolManager.newIntermediateJumpLabel();
|
||||
Label beginJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Label doJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
Label endJumpLabel = symbolTable.newIntermediateJumpLabel();
|
||||
StatementJumpTarget beginJumpTarget = new StatementJumpTarget(beginJumpLabel);
|
||||
sequence.addStatement(beginJumpTarget);
|
||||
RValue rValue = this.visit(ctx.expr());
|
||||
@ -100,11 +100,11 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
|
||||
@Override
|
||||
public RValue visitStmtAssignment(KickCParser.StmtAssignmentContext ctx) {
|
||||
if(ctx.TYPE()!=null) {
|
||||
symbolManager.newVariableDeclaration(ctx.NAME().getText(), ctx.TYPE().getText());
|
||||
symbolTable.newVariableDeclaration(ctx.NAME().getText(), ctx.TYPE().getText());
|
||||
}
|
||||
if(ctx.expr()!=null) {
|
||||
RValue rValue = this.visit(ctx.expr());
|
||||
Symbol variable = symbolManager.newVariableAssignment(ctx.NAME().getText());
|
||||
VariableUnversioned variable = symbolTable.newVariableUsage(ctx.NAME().getText());
|
||||
Statement stmt = new StatementAssignment(variable, rValue);
|
||||
sequence.addStatement(stmt);
|
||||
}
|
||||
@ -139,7 +139,7 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
|
||||
RValue right = this.visit(ctx.expr(1));
|
||||
String op = ((TerminalNode)ctx.getChild(1)).getSymbol().getText();
|
||||
Operator operator = new Operator(op);
|
||||
Symbol tmpVar = symbolManager.newIntermediateAssignment();
|
||||
VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment();
|
||||
Statement stmt = new StatementAssignment(tmpVar, left, operator, right);
|
||||
sequence.addStatement(stmt);
|
||||
return tmpVar;
|
||||
@ -150,7 +150,7 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
|
||||
RValue child = this.visit(ctx.expr());
|
||||
String op = ((TerminalNode)ctx.getChild(0)).getSymbol().getText();
|
||||
Operator operator = new Operator(op);
|
||||
Symbol tmpVar = symbolManager.newIntermediateAssignment();
|
||||
VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment();
|
||||
Statement stmt = new StatementAssignment(tmpVar, operator, child);
|
||||
sequence.addStatement(stmt);
|
||||
return tmpVar;
|
||||
@ -163,15 +163,15 @@ public class PassGenerateStatementSequence extends KickCBaseVisitor<RValue> {
|
||||
|
||||
@Override
|
||||
public RValue visitExprId(KickCParser.ExprIdContext ctx) {
|
||||
return symbolManager.newVariableUsage(ctx.NAME().getText());
|
||||
return symbolTable.newVariableUsage(ctx.NAME().getText());
|
||||
}
|
||||
|
||||
public StatementSequence getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public SymbolManager getSymbols() {
|
||||
return this.symbolManager;
|
||||
public SymbolTable getSymbols() {
|
||||
return this.symbolTable;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ package dk.camelot64.kickc.icl;
|
||||
*/
|
||||
public class PassTypeInference {
|
||||
|
||||
public void inferTypes(StatementSequence sequence, SymbolManager symbols) {
|
||||
public void inferTypes(StatementSequence sequence, SymbolTable symbols) {
|
||||
for (Statement statement : sequence.getStatements()) {
|
||||
if (statement instanceof StatementAssignment) {
|
||||
StatementAssignment assignment = (StatementAssignment) statement;
|
||||
Symbol symbol = (Symbol) assignment.getlValue();
|
||||
Variable symbol = (Variable) assignment.getlValue();
|
||||
if (SymbolType.VAR.equals(symbol.getType())) {
|
||||
// Unresolved symbol - perform inference
|
||||
Operator operator = assignment.getOperator();
|
||||
|
@ -9,9 +9,9 @@ package dk.camelot64.kickc.icl;
|
||||
public class StatementConditionalJump implements Statement {
|
||||
|
||||
private RValue condition;
|
||||
private Symbol destination;
|
||||
private Label destination;
|
||||
|
||||
public StatementConditionalJump(RValue condition, Symbol destination) {
|
||||
public StatementConditionalJump(RValue condition, Label destination) {
|
||||
this.condition = condition;
|
||||
this.destination = destination;
|
||||
}
|
||||
@ -20,7 +20,7 @@ public class StatementConditionalJump implements Statement {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public Symbol getDestination() {
|
||||
public Label getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
|
@ -8,13 +8,13 @@ package dk.camelot64.kickc.icl;
|
||||
*/
|
||||
public class StatementJump implements Statement {
|
||||
|
||||
private Symbol destination;
|
||||
private Label destination;
|
||||
|
||||
public StatementJump(Symbol destination) {
|
||||
public StatementJump(Label destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public Symbol getDestination() {
|
||||
public Label getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
|
@ -5,13 +5,13 @@ package dk.camelot64.kickc.icl;
|
||||
*/
|
||||
public class StatementJumpTarget implements Statement {
|
||||
|
||||
private Symbol label;
|
||||
private Label label;
|
||||
|
||||
public StatementJumpTarget(Symbol label) {
|
||||
public StatementJumpTarget(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public Symbol getLabel() {
|
||||
public Label getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,12 @@ import java.util.List;
|
||||
public class StatementPhi implements Statement {
|
||||
|
||||
/** The versioned variable being assigned a value by the statement. */
|
||||
private Symbol lValue;
|
||||
private VariableVersion lValue;
|
||||
|
||||
/** The previous version of the symbol from predeccesor control blocks. */
|
||||
private List<PreviousSymbol> previousVersions;
|
||||
|
||||
public StatementPhi(Symbol lValue) {
|
||||
public StatementPhi(VariableVersion lValue) {
|
||||
this.lValue = lValue;
|
||||
this.previousVersions = new ArrayList<>();
|
||||
}
|
||||
@ -28,9 +28,9 @@ public class StatementPhi implements Statement {
|
||||
*/
|
||||
public static class PreviousSymbol {
|
||||
private ControlFlowBlock block;
|
||||
private Symbol symbol;
|
||||
private VariableVersion symbol;
|
||||
|
||||
public PreviousSymbol(ControlFlowBlock block, Symbol symbol) {
|
||||
public PreviousSymbol(ControlFlowBlock block, VariableVersion symbol) {
|
||||
this.block = block;
|
||||
this.symbol = symbol;
|
||||
}
|
||||
@ -46,11 +46,11 @@ public class StatementPhi implements Statement {
|
||||
|
||||
}
|
||||
|
||||
public Symbol getlValue() {
|
||||
public VariableVersion getlValue() {
|
||||
return lValue;
|
||||
}
|
||||
|
||||
public void addPreviousVersion(ControlFlowBlock block, Symbol symbol) {
|
||||
public void addPreviousVersion(ControlFlowBlock block, VariableVersion symbol) {
|
||||
previousVersions.add(new PreviousSymbol(block, symbol));
|
||||
}
|
||||
|
||||
|
@ -1,97 +1,10 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
public class Symbol implements RValue, LValue {
|
||||
public interface Symbol {
|
||||
|
||||
/** The name of the symbol. */
|
||||
private String name;
|
||||
public String getName();
|
||||
|
||||
/** The type of the symbol. VAR means tha type is unknown, and has not been inferred yet. */
|
||||
private SymbolType type;
|
||||
public SymbolType getType();
|
||||
|
||||
/** true if the symbol type is infered (not declared) */
|
||||
private boolean inferredType;
|
||||
|
||||
/** true if this is an intermediate variable that is created as a part of evaluating an expression. */
|
||||
private boolean intermediate;
|
||||
|
||||
/** If the symbol is a version of another symbol created during generation of single static assignment form (SSA) this contains the main symbol. */
|
||||
private Symbol versionOf;
|
||||
|
||||
/** The number of the next version (if anyone versions this symbol)*/
|
||||
private Integer nextVersionNumber;
|
||||
|
||||
public Symbol(String name, SymbolType type, boolean intermediate) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.intermediate = intermediate;
|
||||
this.inferredType = false;
|
||||
this.versionOf = null;
|
||||
if(!intermediate) {
|
||||
this.nextVersionNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Symbol(Symbol versionOf, int version) {
|
||||
this.name = versionOf.getName() + "#" + version;
|
||||
this.type = versionOf.getType();
|
||||
this.intermediate = versionOf.isIntermediate();
|
||||
this.inferredType = versionOf.isInferredType();
|
||||
this.versionOf = versionOf;
|
||||
this.nextVersionNumber = null;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** Get the version number of the next version. (if anyone versions the symbol). */
|
||||
int getNextVersionNumber() {
|
||||
return nextVersionNumber++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "("+type.getTypeName() + (inferredType ?"*":"") + ") "+name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Symbol symbol = (Symbol) o;
|
||||
if (!name.equals(symbol.name)) return false;
|
||||
return type == symbol.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isInferredType() {
|
||||
return inferredType;
|
||||
}
|
||||
|
||||
public boolean isVersioned() {
|
||||
return versionOf != null;
|
||||
}
|
||||
|
||||
public Symbol getVersionOf() {
|
||||
return versionOf;
|
||||
}
|
||||
}
|
||||
|
@ -1,79 +0,0 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Manages symbols (variables, labels)
|
||||
*/
|
||||
public class SymbolManager {
|
||||
|
||||
private Map<String, Symbol> symbols;
|
||||
private int intermediateVarCount = 0;
|
||||
private int intermediateLabelCount = 1;
|
||||
|
||||
public SymbolManager() {
|
||||
this.symbols = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
private Symbol addSymbol(String name, SymbolType symbolType, boolean intermediate) {
|
||||
if(symbols.get(name)!=null) {
|
||||
throw new RuntimeException("Symbol already declared "+name);
|
||||
}
|
||||
Symbol symbol = new Symbol(name, symbolType, intermediate);
|
||||
symbols.put(name, symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public void newVariableDeclaration(String name, String type) {
|
||||
SymbolType symbolType = SymbolType.get(type);
|
||||
addSymbol(name, symbolType, false);
|
||||
}
|
||||
|
||||
public Symbol newVariableAssignment(String varName) {
|
||||
return symbols.get(varName);
|
||||
}
|
||||
|
||||
public Symbol newVariableUsage(String varName) {
|
||||
return symbols.get(varName);
|
||||
}
|
||||
|
||||
public Symbol newIntermediateAssignment() {
|
||||
String name = "$"+intermediateVarCount++;
|
||||
Symbol symbol = addSymbol(name, SymbolType.VAR, true);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Symbol newNamedJumpLabel(String name) {
|
||||
Symbol symbol = addSymbol(name, SymbolType.LABEL, false);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Symbol newIntermediateJumpLabel() {
|
||||
String name = "@"+ intermediateLabelCount++;
|
||||
Symbol symbol = addSymbol(name, SymbolType.LABEL, true);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
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");
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public void remove(Symbol symbol) {
|
||||
symbols.remove(symbol.getName());
|
||||
}
|
||||
|
||||
public Symbol createVersion(Symbol symbol) {
|
||||
Symbol version = new Symbol(symbol, symbol.getNextVersionNumber());
|
||||
symbols.put(version.getName(), version);
|
||||
return version;
|
||||
}
|
||||
}
|
79
src/dk/camelot64/kickc/icl/SymbolTable.java
Normal file
79
src/dk/camelot64/kickc/icl/SymbolTable.java
Normal file
@ -0,0 +1,79 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Manages symbols (variables, labels)
|
||||
*/
|
||||
public class SymbolTable {
|
||||
|
||||
private Map<String, Symbol> symbols;
|
||||
private int intermediateVarCount = 0;
|
||||
private int intermediateLabelCount = 1;
|
||||
|
||||
public SymbolTable() {
|
||||
this.symbols = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
private Symbol addSymbol(Symbol symbol) {
|
||||
if(symbols.get(symbol.getName())!=null) {
|
||||
throw new RuntimeException("Symbol already declared "+symbol.getName());
|
||||
}
|
||||
symbols.put(symbol.getName(), symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public VariableUnversioned newVariableDeclaration(String name, String type) {
|
||||
SymbolType symbolType = SymbolType.get(type);
|
||||
VariableUnversioned symbol = new VariableUnversioned(name, symbolType);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public VariableUnversioned newVariableUsage(String name) {
|
||||
return (VariableUnversioned) symbols.get(name);
|
||||
}
|
||||
|
||||
public VariableIntermediate newIntermediateAssignment() {
|
||||
String name = "$"+intermediateVarCount++;
|
||||
VariableIntermediate symbol = new VariableIntermediate(name, SymbolType.VAR);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Label newNamedJumpLabel(String name) {
|
||||
Label symbol = new Label(name, false);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
public Label newIntermediateJumpLabel() {
|
||||
String name = "@"+ intermediateLabelCount++;
|
||||
Label symbol = new Label(name, true);
|
||||
addSymbol(symbol);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer out = new StringBuffer();
|
||||
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");
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public void remove(Symbol symbol) {
|
||||
symbols.remove(symbol.getName());
|
||||
}
|
||||
|
||||
public VariableVersion createVersion(VariableUnversioned symbol) {
|
||||
VariableVersion version = new VariableVersion(symbol, symbol.getNextVersionNumber());
|
||||
symbols.put(version.getName(), version);
|
||||
return version;
|
||||
}
|
||||
}
|
62
src/dk/camelot64/kickc/icl/Variable.java
Normal file
62
src/dk/camelot64/kickc/icl/Variable.java
Normal file
@ -0,0 +1,62 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
public abstract class Variable implements Symbol, RValue, LValue {
|
||||
|
||||
/** The name of the symbol. */
|
||||
private String name;
|
||||
|
||||
/** The type of the symbol. VAR means tha type is unknown, and has not been inferred yet. */
|
||||
private SymbolType type;
|
||||
|
||||
/** true if the symbol type is infered (not declared) */
|
||||
private boolean inferredType;
|
||||
|
||||
public Variable(String name, SymbolType type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
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 isInferredType() {
|
||||
return inferredType;
|
||||
}
|
||||
|
||||
public abstract boolean isVersioned();
|
||||
|
||||
public abstract boolean isIntermediate();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "("+type.getTypeName() + (inferredType ?"*":"") + ") "+name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Variable symbol = (Variable) o;
|
||||
if (!name.equals(symbol.name)) return false;
|
||||
return type == symbol.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
19
src/dk/camelot64/kickc/icl/VariableIntermediate.java
Normal file
19
src/dk/camelot64/kickc/icl/VariableIntermediate.java
Normal file
@ -0,0 +1,19 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
public class VariableIntermediate extends Variable {
|
||||
|
||||
public VariableIntermediate(String name, SymbolType type) {
|
||||
super(name, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIntermediate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return false;
|
||||
}
|
||||
}
|
28
src/dk/camelot64/kickc/icl/VariableUnversioned.java
Normal file
28
src/dk/camelot64/kickc/icl/VariableUnversioned.java
Normal file
@ -0,0 +1,28 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
public class VariableUnversioned extends Variable {
|
||||
|
||||
/** The number of the next version */
|
||||
private Integer nextVersionNumber;
|
||||
|
||||
public VariableUnversioned(String name, SymbolType type) {
|
||||
super(name, type);
|
||||
this.nextVersionNumber = 0;
|
||||
}
|
||||
|
||||
/** Get the version number of the next version. (if anyone versions the symbol). */
|
||||
int getNextVersionNumber() {
|
||||
return nextVersionNumber++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIntermediate() {
|
||||
return false;
|
||||
}
|
||||
}
|
26
src/dk/camelot64/kickc/icl/VariableVersion.java
Normal file
26
src/dk/camelot64/kickc/icl/VariableVersion.java
Normal file
@ -0,0 +1,26 @@
|
||||
package dk.camelot64.kickc.icl;
|
||||
|
||||
/** A Symbol (variable, jump label, etc.) */
|
||||
public class VariableVersion extends Variable {
|
||||
|
||||
private VariableUnversioned versionOf;
|
||||
|
||||
public VariableVersion(VariableUnversioned versionOf, int version) {
|
||||
super(versionOf.getName()+"#"+version, versionOf.getType());
|
||||
this.versionOf = versionOf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIntermediate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public VariableUnversioned getVersionOf() {
|
||||
return versionOf;
|
||||
}
|
||||
}
|
@ -21,14 +21,15 @@ public class main {
|
||||
PassGenerateStatementSequence passGenerateStatementSequence = new PassGenerateStatementSequence();
|
||||
passGenerateStatementSequence.generate(file);
|
||||
StatementSequence statementSequence = passGenerateStatementSequence.getSequence();
|
||||
SymbolManager symbolManager = passGenerateStatementSequence.getSymbols();
|
||||
new PassTypeInference().inferTypes(statementSequence, symbolManager);
|
||||
PassGenerateControlFlowGraph passGenerateControlFlowGraph = new PassGenerateControlFlowGraph(symbolManager);
|
||||
SymbolTable symbolTable = passGenerateStatementSequence.getSymbols();
|
||||
new PassTypeInference().inferTypes(statementSequence, symbolTable);
|
||||
PassGenerateControlFlowGraph passGenerateControlFlowGraph = new PassGenerateControlFlowGraph(symbolTable);
|
||||
ControlFlowGraph controlFlowGraph = passGenerateControlFlowGraph.generate(statementSequence);
|
||||
PassGenerateSingleStaticAssignmentForm passGenerateSingleStaticAssignmentForm = new PassGenerateSingleStaticAssignmentForm(symbolManager, controlFlowGraph);
|
||||
PassGenerateSingleStaticAssignmentForm passGenerateSingleStaticAssignmentForm = new PassGenerateSingleStaticAssignmentForm(
|
||||
symbolTable, controlFlowGraph);
|
||||
passGenerateSingleStaticAssignmentForm.generate();
|
||||
System.out.println("SYMBOLS");
|
||||
System.out.println(symbolManager.toString());
|
||||
System.out.println(symbolTable.toString());
|
||||
System.out.println("PROGRAM");
|
||||
System.out.println(statementSequence.toString());
|
||||
System.out.println("CONTROL FLOW GRAPH");
|
||||
|
Loading…
Reference in New Issue
Block a user