diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index f8a9758e8..b073e2868 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -135,13 +135,14 @@ public class AsmFragment { signature.append(bind(conditionalJump.getRValue2())); } signature.append("_then_"); - Label destination = conditionalJump.getDestination(); + LabelRef destination = conditionalJump.getDestination(); ControlFlowBlock destinationBlock = graph.getBlock(destination); String destinationLabel = destination.getFullName(); if (destinationBlock.hasPhiStatements()) { destinationLabel = (destinationBlock.getLabel().getLocalName() + "_from_" + block.getLabel().getLocalName()).replace('@', 'B').replace(':','_'); } - signature.append(bind(new Label(destinationLabel, destination.getScope(),false))); + Symbol destSymbol = symbols.getSymbol(destination); + signature.append(bind(new Label(destinationLabel, destSymbol.getScope(),false))); return signature.toString(); } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java index 993a97535..2862e0fca 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java @@ -8,24 +8,24 @@ import java.util.List; * The block only knows its own successors. To find predecessor blocks access to the entire graph is needed.*/ public class ControlFlowBlock { - private Label label; + private LabelRef label; private List statements; - private Label defaultSuccessor; + private LabelRef defaultSuccessor; - private Label conditionalSuccessor; + private LabelRef conditionalSuccessor; - private Label callSuccessor; + private LabelRef callSuccessor; - public ControlFlowBlock(Label label) { + public ControlFlowBlock(LabelRef label) { this.label = label; this.statements = new ArrayList<>(); this.defaultSuccessor = null; this.conditionalSuccessor = null; } - public Label getLabel() { + public LabelRef getLabel() { return label; } @@ -33,27 +33,27 @@ public class ControlFlowBlock { this.statements.add(statement); } - public void setDefaultSuccessor(Label defaultSuccessor) { + public void setDefaultSuccessor(LabelRef defaultSuccessor) { this.defaultSuccessor = defaultSuccessor; } - public Label getDefaultSuccessor() { + public LabelRef getDefaultSuccessor() { return defaultSuccessor; } - public Label getConditionalSuccessor() { + public LabelRef getConditionalSuccessor() { return conditionalSuccessor; } - public void setConditionalSuccessor(Label conditionalSuccessor) { + public void setConditionalSuccessor(LabelRef conditionalSuccessor) { this.conditionalSuccessor = conditionalSuccessor; } - public Label getCallSuccessor() { + public LabelRef getCallSuccessor() { return callSuccessor; } - public void setCallSuccessor(Label callSuccessor) { + public void setCallSuccessor(LabelRef callSuccessor) { this.callSuccessor = callSuccessor; } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraph.java b/src/dk/camelot64/kickc/icl/ControlFlowGraph.java index f7b5617ea..74297c778 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraph.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraph.java @@ -6,16 +6,16 @@ import java.util.*; * The control flow graph is a set of connected basic blocks. */ public class ControlFlowGraph { - private Map blocks; + private Map blocks; private ControlFlowBlock firstBlock; private List sequence; - public ControlFlowGraph(Map blocks, ControlFlowBlock firstBlock) { + public ControlFlowGraph(Map blocks, ControlFlowBlock firstBlock) { this.blocks = blocks; this.firstBlock = firstBlock; } - public ControlFlowBlock getBlock(Symbol symbol) { + public ControlFlowBlock getBlock(SymbolRef symbol) { return blocks.get(symbol); } @@ -106,7 +106,7 @@ public class ControlFlowGraph { public ControlFlowBlock getMainBlock() { for (ControlFlowBlock block : getAllBlocks()) { - Label label = block.getLabel(); + LabelRef label = block.getLabel(); if(label.getFullName().equals("main")) { return block; } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java b/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java index 3c6eee3d8..13ae05413 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java @@ -16,7 +16,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor copyBlockMap; + private LinkedHashMap copyBlockMap; /** * The current block being copied. @@ -46,7 +46,7 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor= 0) { @@ -181,6 +185,10 @@ public abstract class Scope implements Symbol { return (Label) symbols.get(name); } + public Label getLabel(LabelRef labelRef) { + return (Label) symbols.get(labelRef); + } + public Procedure addProcedure(String name, SymbolType type) { Symbol symbol = symbols.get(name); if (symbol != null) { diff --git a/src/dk/camelot64/kickc/icl/StatementCall.java b/src/dk/camelot64/kickc/icl/StatementCall.java index bff178315..064e7de27 100644 --- a/src/dk/camelot64/kickc/icl/StatementCall.java +++ b/src/dk/camelot64/kickc/icl/StatementCall.java @@ -12,8 +12,8 @@ public class StatementCall implements StatementLValue { /** The variable being assigned a value by the call. Can be null. */ private LValue lValue; private String procedureName; + private ProcedureRef procedure; private List parameters; - private Procedure procedure; private boolean parametersByAssignment; public StatementCall(LValue lValue, String procedureName, List parameters) { @@ -35,11 +35,11 @@ public class StatementCall implements StatementLValue { return procedureName; } - public Procedure getProcedure() { + public ProcedureRef getProcedure() { return procedure; } - public void setProcedure(Procedure procedure) { + public void setProcedure(ProcedureRef procedure) { this.procedure = procedure; } diff --git a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java index b75c57adb..cae856f76 100644 --- a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java +++ b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java @@ -14,16 +14,16 @@ public class StatementConditionalJump implements Statement { private RValue rValue1; private Operator operator; private RValue rValue2; - private Label destination; + private LabelRef destination; - public StatementConditionalJump(RValue condition, Label destination) { + public StatementConditionalJump(RValue condition, LabelRef destination) { this.rValue1 = null; this.operator = null; this.rValue2 = condition; this.destination = destination; } - public StatementConditionalJump(RValue rValue1, Operator operator, RValue rValue2, Label destination) { + public StatementConditionalJump(RValue rValue1, Operator operator, RValue rValue2, LabelRef destination) { this.rValue1 = rValue1; this.operator = operator; this.rValue2 = rValue2; @@ -42,7 +42,7 @@ public class StatementConditionalJump implements Statement { return rValue2; } - public Label getDestination() { + public LabelRef getDestination() { return destination; } @@ -58,7 +58,7 @@ public class StatementConditionalJump implements Statement { this.rValue2 = rValue2; } - public void setDestination(Label destination) { + public void setDestination(LabelRef destination) { this.destination = destination; } diff --git a/src/dk/camelot64/kickc/icl/StatementJump.java b/src/dk/camelot64/kickc/icl/StatementJump.java index 53f71eea2..4cfed455b 100644 --- a/src/dk/camelot64/kickc/icl/StatementJump.java +++ b/src/dk/camelot64/kickc/icl/StatementJump.java @@ -8,17 +8,17 @@ package dk.camelot64.kickc.icl; */ public class StatementJump implements Statement { - private Label destination; + private LabelRef destination; - public StatementJump(Label destination) { + public StatementJump(LabelRef destination) { this.destination = destination; } - public Label getDestination() { + public LabelRef getDestination() { return destination; } - public void setDestination(Label destination) { + public void setDestination(LabelRef destination) { this.destination = destination; } @@ -34,5 +34,7 @@ public class StatementJump implements Statement { @Override public String getAsString() { - return "goto "+destination.getFullName(); } + return "goto "+destination.getFullName(); + } + } diff --git a/src/dk/camelot64/kickc/icl/StatementLabel.java b/src/dk/camelot64/kickc/icl/StatementLabel.java index 8c6885f97..a3918569c 100644 --- a/src/dk/camelot64/kickc/icl/StatementLabel.java +++ b/src/dk/camelot64/kickc/icl/StatementLabel.java @@ -5,13 +5,13 @@ package dk.camelot64.kickc.icl; */ public class StatementLabel implements Statement { - private Label label; + private LabelRef label; - public StatementLabel(Label label) { + public StatementLabel(LabelRef label) { this.label = label; } - public Label getLabel() { + public LabelRef getLabel() { return label; } diff --git a/src/dk/camelot64/kickc/icl/StatementPhi.java b/src/dk/camelot64/kickc/icl/StatementPhi.java index e41d12bbc..84e25c05c 100644 --- a/src/dk/camelot64/kickc/icl/StatementPhi.java +++ b/src/dk/camelot64/kickc/icl/StatementPhi.java @@ -31,15 +31,15 @@ public class StatementPhi implements StatementLValue { * Which value is chosen depends on which block transition was made. */ public static class PreviousSymbol { - private Label block; + private LabelRef block; private RValue rValue; - public PreviousSymbol(Label block, RValue rValue) { + public PreviousSymbol(LabelRef block, RValue rValue) { this.block = block; this.rValue = rValue; } - public Label getBlock() { + public LabelRef getBlock() { return block; } @@ -51,7 +51,7 @@ public class StatementPhi implements StatementLValue { this.rValue = RValue; } - public void setBlock(Label block) { + public void setBlock(LabelRef block) { this.block = block; } } @@ -68,7 +68,7 @@ public class StatementPhi implements StatementLValue { this.lValue = (VariableRef) lValue; } - public void addPreviousVersion(Label block, RValue rValue) { + public void addPreviousVersion(LabelRef block, RValue rValue) { previousVersions.add(new PreviousSymbol(block, rValue)); } diff --git a/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java b/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java index ec54df483..9769f9caa 100644 --- a/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java +++ b/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java @@ -3,7 +3,7 @@ package dk.camelot64.kickc.icl; /** Procedure declaration in SSA */ public class StatementProcedureBegin implements Statement { - private Procedure procedure; + private ProcedureRef procedure; private Strategy strategy; @@ -12,11 +12,11 @@ public class StatementProcedureBegin implements Statement { INLINE } - public StatementProcedureBegin(Procedure procedure) { + public StatementProcedureBegin(ProcedureRef procedure) { this.procedure = procedure; } - public Procedure getProcedure() { + public ProcedureRef getProcedure() { return procedure; } diff --git a/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java b/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java index f60fe661d..5803892af 100644 --- a/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java +++ b/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java @@ -3,13 +3,13 @@ package dk.camelot64.kickc.icl; /** Procedure declaration in SSA */ public class StatementProcedureEnd implements Statement { - private Procedure procedure; + private ProcedureRef procedure; - public StatementProcedureEnd(Procedure procedure) { + public StatementProcedureEnd(ProcedureRef procedure) { this.procedure = procedure; } - public Procedure getProcedure() { + public ProcedureRef getProcedure() { return procedure; } diff --git a/src/dk/camelot64/kickc/icl/SymbolRef.java b/src/dk/camelot64/kickc/icl/SymbolRef.java new file mode 100644 index 000000000..fa896f024 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/SymbolRef.java @@ -0,0 +1,93 @@ +package dk.camelot64.kickc.icl; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** A reference to a symbol (variable, procedure or label) */ +public class SymbolRef implements Value { + + /** The full name of the variable. Allowing lookup in the symbol table. */ + private String fullName; + + public SymbolRef(String fullName) { + this.fullName = fullName; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + SymbolRef symbolRef = (SymbolRef) o; + + return fullName != null ? fullName.equals(symbolRef.fullName) : symbolRef.fullName == null; + } + + @Override + public int hashCode() { + return fullName != null ? fullName.hashCode() : 0; + } + + @Override + public String getAsTypedString(ProgramScope scope) { + return scope.getSymbol(fullName).getTypedName(); + } + + @Override + @JsonIgnore + public String getAsString() { + return fullName; + } + + @JsonIgnore + public int getScopeDepth() { + int depth = 0; + char[] chars = fullName.toCharArray(); + for (char c : chars) { + if(c==':') depth++; + } + return depth/2; + } + + @JsonIgnore + public boolean isVersion() { + return fullName.contains("#"); + } + + @JsonIgnore + public boolean isIntermediate() { + if(fullName.contains("@BEGIN") || fullName.contains("@END") ) return false; + return fullName.contains("$") || fullName.contains("@"); + } + + @JsonIgnore + public String getLocalName() { + int lastScopeIdx = fullName.lastIndexOf("::"); + if(lastScopeIdx==-1) { + return fullName; + } else { + return fullName.substring(lastScopeIdx+2); + } + } + + @JsonIgnore + public String getScopeNames() { + int lastScopeIdx = fullName.lastIndexOf("::"); + if(lastScopeIdx==-1) { + return ""; + } else { + return fullName.substring(0, lastScopeIdx); + } + } +} diff --git a/src/dk/camelot64/kickc/icl/Variable.java b/src/dk/camelot64/kickc/icl/Variable.java index 856c6cbc4..482ca2b78 100644 --- a/src/dk/camelot64/kickc/icl/Variable.java +++ b/src/dk/camelot64/kickc/icl/Variable.java @@ -129,6 +129,7 @@ public abstract class Variable implements Symbol { } @Override + @JsonIgnore public String getAsString() { return getTypedName(); } diff --git a/src/dk/camelot64/kickc/icl/VariableRef.java b/src/dk/camelot64/kickc/icl/VariableRef.java index fd66343c3..cbf7c1a0b 100644 --- a/src/dk/camelot64/kickc/icl/VariableRef.java +++ b/src/dk/camelot64/kickc/icl/VariableRef.java @@ -1,59 +1,14 @@ package dk.camelot64.kickc.icl; /** A reference to a variable from the symbol table */ -public class VariableRef implements RValue, LValue { - - /** The full name of the variable. Allowing lookup in the symbol table. */ - private String fullName; +public class VariableRef extends SymbolRef implements RValue, LValue { public VariableRef(String fullName) { - this.fullName = fullName; + super(fullName); } public VariableRef(Variable variable) { this(variable.getFullName()); } - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - VariableRef that = (VariableRef) o; - - return fullName != null ? fullName.equals(that.fullName) : that.fullName == null; - } - - @Override - public int hashCode() { - return fullName != null ? fullName.hashCode() : 0; - } - - @Override - public String toString() { - return getAsString(); - } - - @Override - public String getAsTypedString(ProgramScope scope) { - Variable variable = scope.getVariable(this); - return variable.getTypedName(); - } - - @Override - public String getAsString() { - return fullName; - } } diff --git a/src/dk/camelot64/kickc/passes/Pass1GenerateControlFlowGraph.java b/src/dk/camelot64/kickc/passes/Pass1GenerateControlFlowGraph.java index 9c5d95615..4693746a6 100644 --- a/src/dk/camelot64/kickc/passes/Pass1GenerateControlFlowGraph.java +++ b/src/dk/camelot64/kickc/passes/Pass1GenerateControlFlowGraph.java @@ -12,7 +12,7 @@ public class Pass1GenerateControlFlowGraph { public static final String BEGIN_BLOCK_NAME = "@BEGIN"; public static final String END_BLOCK_NAME = "@END"; private Scope scope; - private Map blocks; + private Map blocks; private ControlFlowBlock firstBlock; public Pass1GenerateControlFlowGraph(Scope scope) { @@ -21,10 +21,10 @@ public class Pass1GenerateControlFlowGraph { } public ControlFlowGraph generate(StatementSequence sequence) { - this.firstBlock = getOrCreateBlock(scope.addLabel(BEGIN_BLOCK_NAME)); + this.firstBlock = getOrCreateBlock(scope.addLabel(BEGIN_BLOCK_NAME).getRef()); Stack blockStack = new Stack<>(); blockStack.push(firstBlock); - sequence.addStatement(new StatementLabel(scope.addLabel(END_BLOCK_NAME))); + sequence.addStatement(new StatementLabel(scope.addLabel(END_BLOCK_NAME).getRef())); for (Statement statement : sequence.getStatements()) { ControlFlowBlock currentBlock = blockStack.peek(); if(statement instanceof StatementLabel) { @@ -37,14 +37,14 @@ public class Pass1GenerateControlFlowGraph { StatementJump statementJump = (StatementJump) statement; ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination()); currentBlock.setDefaultSuccessor(jmpBlock.getLabel()); - ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate()); + ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate().getRef()); blockStack.pop(); blockStack.push(nextBlock); } else if(statement instanceof StatementConditionalJump) { currentBlock.addStatement(statement); StatementConditionalJump statementConditionalJump = (StatementConditionalJump) statement; ControlFlowBlock jmpBlock = getOrCreateBlock(statementConditionalJump.getDestination()); - ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate()); + ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate().getRef()); currentBlock.setDefaultSuccessor(nextBlock.getLabel()); currentBlock.setConditionalSuccessor(jmpBlock.getLabel()); blockStack.pop(); @@ -53,13 +53,14 @@ public class Pass1GenerateControlFlowGraph { // Procedure strategy implemented is currently variable-based transfer of parameters/return values StatementProcedureBegin procedureBegin = (StatementProcedureBegin) statement; procedureBegin.setStrategy(StatementProcedureBegin.Strategy.PASS_BY_REGISTER); - Label procedureLabel = procedureBegin.getProcedure().getLabel(); - ControlFlowBlock procBlock = getOrCreateBlock(procedureLabel); + ProcedureRef procedureRef = procedureBegin.getProcedure(); + LabelRef procedureLabelRef = procedureRef.getLabelRef(); + ControlFlowBlock procBlock = getOrCreateBlock(procedureLabelRef); blockStack.push(procBlock); } else if(statement instanceof StatementProcedureEnd) { // Procedure strategy implemented is currently variable-based transfer of parameters/return values - currentBlock.setDefaultSuccessor(new Label("@RETURN", scope, false)); - ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate()); + currentBlock.setDefaultSuccessor(new Label("@RETURN", scope, false).getRef()); + ControlFlowBlock nextBlock = getOrCreateBlock(scope.addLabelIntermediate().getRef()); blockStack.pop(); ControlFlowBlock prevBlock = blockStack.pop(); prevBlock.setDefaultSuccessor(nextBlock.getLabel()); @@ -77,7 +78,7 @@ public class Pass1GenerateControlFlowGraph { return new ControlFlowGraph(blocks, firstBlock); } - private ControlFlowBlock getOrCreateBlock(Label label) { + private ControlFlowBlock getOrCreateBlock(LabelRef label) { ControlFlowBlock block = blocks.get(label); if(block==null) { block = new ControlFlowBlock(label); diff --git a/src/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java b/src/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java index bd44ad354..e43a09ad0 100644 --- a/src/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java +++ b/src/dk/camelot64/kickc/passes/Pass1GenerateSingleStaticAssignmentForm.java @@ -170,8 +170,8 @@ public class Pass1GenerateSingleStaticAssignmentForm { * false if new phis were added, meaning another iteration is needed. */ private boolean completePhiFunctions() { - Map> newPhis = new LinkedHashMap<>(); - Map> symbolMap = buildSymbolMap(); + Map> newPhis = new LinkedHashMap<>(); + Map> symbolMap = buildSymbolMap(); for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) { for (Statement statement : block.getStatements()) { if (statement instanceof StatementPhi) { @@ -181,7 +181,7 @@ public class Pass1GenerateSingleStaticAssignmentForm { VariableVersion versioned = (VariableVersion) symbols.getVariable(phiLValVarRef); VariableUnversioned unversioned = versioned.getVersionOf(); for (ControlFlowBlock predecessor : controlFlowGraph.getPredecessors(block)) { - Label predecessorLabel = predecessor.getLabel(); + LabelRef predecessorLabel = predecessor.getLabel(); Map predecessorMap = symbolMap.get(predecessorLabel); VariableVersion previousSymbol = null; if (predecessorMap != null) { @@ -223,8 +223,8 @@ public class Pass1GenerateSingleStaticAssignmentForm { * 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> buildSymbolMap() { - Map> symbolMap = new LinkedHashMap<>(); + private Map> buildSymbolMap() { + Map> symbolMap = new LinkedHashMap<>(); for (ControlFlowBlock block : this.controlFlowGraph.getAllBlocks()) { for (Statement statement : block.getStatements()) { if (statement instanceof StatementLValue) { @@ -234,7 +234,7 @@ public class Pass1GenerateSingleStaticAssignmentForm { Variable lValueVar = symbols.getVariable((VariableRef) lValue); if (lValueVar instanceof VariableVersion) { VariableVersion versioned = (VariableVersion) lValueVar; - Label label = block.getLabel(); + LabelRef label = block.getLabel(); VariableUnversioned unversioned = versioned.getVersionOf(); Map blockMap = symbolMap.get(label); if (blockMap == null) { diff --git a/src/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java b/src/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java index 77802d75f..2e926948d 100644 --- a/src/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java +++ b/src/dk/camelot64/kickc/passes/Pass1GenerateStatementSequence.java @@ -88,25 +88,25 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { PrePostModifierHandler.addPostModifiers(this, ctx.expr()); Label ifJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label elseJumpLabel = getCurrentSymbols().addLabelIntermediate(); - Statement ifJmpStmt = new StatementConditionalJump(rValue, ifJumpLabel); + Statement ifJmpStmt = new StatementConditionalJump(rValue, ifJumpLabel.getRef()); sequence.addStatement(ifJmpStmt); - Statement elseJmpStmt = new StatementJump(elseJumpLabel); + Statement elseJmpStmt = new StatementJump(elseJumpLabel.getRef()); sequence.addStatement(elseJmpStmt); - StatementLabel ifJumpTarget = new StatementLabel(ifJumpLabel); + StatementLabel ifJumpTarget = new StatementLabel(ifJumpLabel.getRef()); sequence.addStatement(ifJumpTarget); this.visit(ctx.stmt(0)); KickCParser.StmtContext elseStmt = ctx.stmt(1); if (elseStmt != null) { Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); - Statement endJmpStmt = new StatementJump(endJumpLabel); + Statement endJmpStmt = new StatementJump(endJumpLabel.getRef()); sequence.addStatement(endJmpStmt); - StatementLabel elseJumpTarget = new StatementLabel(elseJumpLabel); + StatementLabel elseJumpTarget = new StatementLabel(elseJumpLabel.getRef()); sequence.addStatement(elseJumpTarget); this.visit(elseStmt); - StatementLabel endJumpTarget = new StatementLabel(endJumpLabel); + StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef()); sequence.addStatement(endJumpTarget); } else { - StatementLabel elseJumpTarget = new StatementLabel(elseJumpLabel); + StatementLabel elseJumpTarget = new StatementLabel(elseJumpLabel.getRef()); sequence.addStatement(elseJumpTarget); } return null; @@ -117,21 +117,21 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label doJumpLabel = getCurrentSymbols().addLabelIntermediate(); Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); - StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel); + StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef()); sequence.addStatement(beginJumpTarget); PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr()); PrePostModifierHandler.addPostModifiers(this, ctx.expr()); - Statement doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel); + Statement doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel.getRef()); sequence.addStatement(doJmpStmt); - Statement endJmpStmt = new StatementJump(endJumpLabel); + Statement endJmpStmt = new StatementJump(endJumpLabel.getRef()); sequence.addStatement(endJmpStmt); - StatementLabel doJumpTarget = new StatementLabel(doJumpLabel); + StatementLabel doJumpTarget = new StatementLabel(doJumpLabel.getRef()); sequence.addStatement(doJumpTarget); this.visit(ctx.stmt()); - Statement beginJmpStmt = new StatementJump(beginJumpLabel); + Statement beginJmpStmt = new StatementJump(beginJumpLabel.getRef()); sequence.addStatement(beginJmpStmt); - StatementLabel endJumpTarget = new StatementLabel(endJumpLabel); + StatementLabel endJumpTarget = new StatementLabel(endJumpLabel.getRef()); sequence.addStatement(endJumpTarget); return null; } @@ -139,7 +139,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public Void visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) { Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate(); - StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel); + StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel.getRef()); sequence.addStatement(beginJumpTarget); if (ctx.stmt() != null) { this.visit(ctx.stmt()); @@ -147,7 +147,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { PrePostModifierHandler.addPreModifiers(this, ctx.expr()); RValue rValue = (RValue) this.visit(ctx.expr()); PrePostModifierHandler.addPostModifiers(this, ctx.expr()); - Statement doJmpStmt = new StatementConditionalJump(rValue, beginJumpLabel); + Statement doJmpStmt = new StatementConditionalJump(rValue, beginJumpLabel.getRef()); sequence.addStatement(doJmpStmt); return null; } @@ -168,11 +168,11 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { parameterList = (List) this.visit(ctx.parameterListDecl()); } procedure.setParameters(parameterList); - sequence.addStatement(new StatementProcedureBegin(procedure)); + sequence.addStatement(new StatementProcedureBegin(procedure.getRef())); if (ctx.stmtSeq() != null) { this.visit(ctx.stmtSeq()); } - sequence.addStatement(new StatementLabel(procExit)); + sequence.addStatement(new StatementLabel(procExit.getRef())); if (returnVar != null) { sequence.addStatement(new StatementAssignment(returnVar, returnVar)); } @@ -180,7 +180,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { if(returnVar!=null) {new VariableRef(returnVar); } sequence.addStatement(new StatementReturn(returnVarRef)); scopeStack.pop(); - sequence.addStatement(new StatementProcedureEnd(procedure)); + sequence.addStatement(new StatementProcedureEnd(procedure.getRef())); return null; } @@ -214,7 +214,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { PrePostModifierHandler.addPostModifiers(this, exprCtx); } Label returnLabel = procedure.getLabel("@return"); - sequence.addStatement(new StatementJump(returnLabel)); + sequence.addStatement(new StatementJump(returnLabel.getRef())); return null; } @@ -261,7 +261,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { public LValue visitLvaluePtr(KickCParser.LvaluePtrContext ctx) { LValue lval = (LValue) visit(ctx.lvalue()); if (lval instanceof VariableRef) { - return new PointerDereferenceSimple((VariableRef) lval); + return new PointerDereferenceSimple(lval); } else { throw new RuntimeException("Not implemented"); } diff --git a/src/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java b/src/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java index 6eaeb634d..959c05347 100644 --- a/src/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java +++ b/src/dk/camelot64/kickc/passes/Pass1ProcedureCallParameters.java @@ -24,7 +24,8 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { public StatementCall visitCall(StatementCall origCall) { // Procedure strategy implemented is currently variable-based transfer of parameters/return values // Generate parameter passing assignments - Procedure procedure = origCall.getProcedure(); + ProcedureRef procedureRef = origCall.getProcedure(); + Procedure procedure = (Procedure) scope.getSymbol(procedureRef); List parameterDecls = procedure.getParameters(); List parameterValues = origCall.getParameters(); for (int i = 0; i < parameterDecls.size(); i++) { @@ -35,13 +36,15 @@ public class Pass1ProcedureCallParameters extends ControlFlowGraphCopyVisitor { String procedureName = origCall.getProcedureName(); Variable procReturnVar = procedure.getVariable("return"); VariableRef procReturnVarRef = null; - if(procReturnVar!=null) {new VariableRef(procReturnVar); } + if (procReturnVar != null) { + procReturnVarRef = new VariableRef(procReturnVar); + } StatementCall copyCall = new StatementCall(procReturnVarRef, procedureName, null); copyCall.setParametersByAssignment(true); - copyCall.setProcedure(procedure); + copyCall.setProcedure(procedureRef); addStatementToCurrentBlock(copyCall); - getCurrentBlock().setCallSuccessor(procedure.getLabel()); - splitCurrentBlock(scope.addLabelIntermediate()); + getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef()); + splitCurrentBlock(scope.addLabelIntermediate().getRef()); if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) { addStatementToCurrentBlock(new StatementAssignment(origCall.getlValue(), procReturnVarRef)); } else { diff --git a/src/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java b/src/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java index d1b5ff0ba..8244e2b6a 100644 --- a/src/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java +++ b/src/dk/camelot64/kickc/passes/Pass1ProcedureCallsReturnValue.java @@ -5,10 +5,10 @@ import dk.camelot64.kickc.icl.*; /** Pass that modifies a control flow graph to call procedures by passing return value through registers */ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor { - private Scope scope; + private ProgramScope scope; private ControlFlowGraph graph; - public Pass1ProcedureCallsReturnValue(Scope scope, ControlFlowGraph graph) { + public Pass1ProcedureCallsReturnValue(ProgramScope scope, ControlFlowGraph graph) { this.scope = scope; this.graph = graph; } @@ -22,18 +22,19 @@ public class Pass1ProcedureCallsReturnValue extends ControlFlowGraphCopyVisitor public StatementCall visitCall(StatementCall origCall) { // Procedure strategy implemented is currently variable-based transfer of parameters/return values // Generate return value assignment - Procedure procedure = origCall.getProcedure(); + ProcedureRef procedureRef = origCall.getProcedure(); + Procedure procedure = (Procedure) scope.getSymbol(procedureRef); String procedureName = origCall.getProcedureName(); StatementCall copyCall = new StatementCall(null, procedureName, null); copyCall.setParametersByAssignment(true); - copyCall.setProcedure(procedure); + copyCall.setProcedure(procedureRef); addStatementToCurrentBlock(copyCall); - getCurrentBlock().setCallSuccessor(procedure.getLabel()); + getCurrentBlock().setCallSuccessor(procedure.getLabel().getRef()); if(!SymbolTypeBasic.VOID.equals(procedure.getReturnType())) { // Find return variable final version Label returnBlockLabel = procedure.getLabel("@return"); - ControlFlowBlock returnBlock = graph.getBlock(returnBlockLabel); + ControlFlowBlock returnBlock = graph.getBlock(returnBlockLabel.getRef()); VariableRef returnVarFinal = null; for (Statement statement : returnBlock.getStatements()) { if (statement instanceof StatementReturn) { diff --git a/src/dk/camelot64/kickc/passes/Pass1TypeInference.java b/src/dk/camelot64/kickc/passes/Pass1TypeInference.java index 3fcf9efca..2331cc03c 100644 --- a/src/dk/camelot64/kickc/passes/Pass1TypeInference.java +++ b/src/dk/camelot64/kickc/passes/Pass1TypeInference.java @@ -22,7 +22,9 @@ public class Pass1TypeInference { for (Statement statement : sequence.getStatements()) { if(statement instanceof StatementProcedureBegin) { StatementProcedureBegin procedureBegin = (StatementProcedureBegin) statement; - scopes.push(procedureBegin.getProcedure()); + ProcedureRef procedureRef = procedureBegin.getProcedure(); + Procedure procedure = (Procedure) programScope.getSymbol(procedureRef); + scopes.push(procedure); } else if(statement instanceof StatementProcedureEnd) { scopes.pop(); } else if (statement instanceof StatementAssignment) { @@ -54,7 +56,7 @@ public class Pass1TypeInference { if(lValue instanceof VariableRef) { String procedureName = call.getProcedureName(); Procedure procedure = scopes.peek().getProcedure(procedureName); - call.setProcedure(procedure); + call.setProcedure(procedure.getRef()); if(procedure.getParameters().size()!=call.getParameters().size()) { throw new RuntimeException("Wrong number of parameters in call. Expected " +procedure.getParameters().size()+". "+statement.toString()); } diff --git a/src/dk/camelot64/kickc/passes/Pass2AliasElimination.java b/src/dk/camelot64/kickc/passes/Pass2AliasElimination.java index 0f9cc7c7a..cd4bd32c3 100644 --- a/src/dk/camelot64/kickc/passes/Pass2AliasElimination.java +++ b/src/dk/camelot64/kickc/passes/Pass2AliasElimination.java @@ -179,9 +179,9 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { if (keep == null) { keep = var; } else { - if (isVersion(var)) { - if (isVersion(keep)) { - if (getScopeDepth(var) < getScopeDepth(keep)) { + if (var.isVersion()) { + if (keep.isVersion()) { + if (var.getScopeDepth() < keep.getScopeDepth()) { keep = var; } } else { @@ -193,19 +193,6 @@ public class Pass2AliasElimination extends Pass2SsaOptimization { return keep; } - private int getScopeDepth(VariableRef var) { - int depth = 0; - char[] chars = var.getFullName().toCharArray(); - for (char c : chars) { - if(c==':') depth++; - } - return depth/2; - } - - private boolean isVersion(VariableRef var) { - return var.getFullName().contains("#"); - } - public List getEliminateVars() { List eliminate = new ArrayList<>(); VariableRef keepVar = getKeepVar(); diff --git a/src/dk/camelot64/kickc/passes/Pass2AssertBlocks.java b/src/dk/camelot64/kickc/passes/Pass2AssertBlocks.java index d2fce524a..4142f927d 100644 --- a/src/dk/camelot64/kickc/passes/Pass2AssertBlocks.java +++ b/src/dk/camelot64/kickc/passes/Pass2AssertBlocks.java @@ -23,7 +23,7 @@ public class Pass2AssertBlocks extends Pass2SsaAssertion { this.graph = graph; } - private void assertBlock(Label blockLabel) throws AssertionFailed { + private void assertBlock(LabelRef blockLabel) throws AssertionFailed { if (blockLabel == null) { return; } @@ -53,7 +53,9 @@ public class Pass2AssertBlocks extends Pass2SsaAssertion { @Override public Void visitCall(StatementCall callLValue) { - assertBlock(callLValue.getProcedure().getLabel()); + ProcedureRef procedure = callLValue.getProcedure(); + LabelRef procLabelRef = procedure.getLabelRef(); + assertBlock(procLabelRef); return super.visitCall(callLValue); } diff --git a/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java b/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java index 827a33695..e3de49d78 100644 --- a/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java +++ b/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java @@ -71,8 +71,8 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion { private void addSymbol(Value symbol) { if (symbol instanceof Symbol) { symbols.add((Symbol) symbol); - } else if(symbol instanceof VariableRef) { - addSymbol(programScope.getVariable((VariableRef) symbol)); + } else if(symbol instanceof SymbolRef) { + addSymbol(programScope.getSymbol((SymbolRef) symbol)); } else if(symbol instanceof PointerDereferenceIndexed) { addSymbol(((PointerDereferenceIndexed) symbol).getPointer()); addSymbol(((PointerDereferenceIndexed) symbol).getIndex()); @@ -92,13 +92,17 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion { @Override public Void visitProcedureBegin(StatementProcedureBegin statement) { - symbols.add(statement.getProcedure()); + ProcedureRef procedureRef = statement.getProcedure(); + Procedure procedure = (Procedure) programScope.getSymbol(procedureRef); + symbols.add(procedure); return super.visitProcedureBegin(statement); } @Override public Void visitProcedureEnd(StatementProcedureEnd statement) { - symbols.add(statement.getProcedure()); + ProcedureRef procedureRef = statement.getProcedure(); + Procedure procedure = (Procedure) programScope.getSymbol(procedureRef); + symbols.add(procedure); return super.visitProcedureEnd(statement); } diff --git a/src/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java b/src/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java index 649c281c9..e2e7e837c 100644 --- a/src/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java +++ b/src/dk/camelot64/kickc/passes/Pass2CullEmptyBlocks.java @@ -26,7 +26,7 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization { // Replace all jumps (default/conditional/call) to @removeBlock with a jump to the default successor final List predecessors = getGraph().getPredecessors(removeBlock); for (ControlFlowBlock predecessor : predecessors) { - Map replace = new LinkedHashMap<>(); + Map replace = new LinkedHashMap<>(); replace.put(removeBlock.getLabel(), successor.getLabel()); if (removeBlock.getLabel().equals(predecessor.getDefaultSuccessor())) { predecessor.setDefaultSuccessor(successor.getLabel()); @@ -63,8 +63,10 @@ public class Pass2CullEmptyBlocks extends Pass2SsaOptimization { }; phiFixVisitor.visitBlock(successor); getGraph().getAllBlocks().remove(removeBlock); - removeBlock.getLabel().getScope().remove(removeBlock.getLabel()); - log.append("Culled Empty Block " + removeBlock.getLabel().getTypedName()); + LabelRef removeBlockLabelRef = removeBlock.getLabel(); + Label removeBlockLabel = (Label) getSymbols().getSymbol(removeBlockLabelRef); + removeBlockLabel.getScope().remove(removeBlockLabel); + log.append("Culled Empty Block " + removeBlockLabel.getTypedName()); } return remove.size()>0; } diff --git a/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java b/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java index 14f4386c5..059c97192 100644 --- a/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java +++ b/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java @@ -189,7 +189,7 @@ public abstract class Pass2SsaOptimization { * * @param replacements Variables that have alias values. */ - public void replaceLabels(final Map replacements) { + public void replaceLabels(final Map replacements) { ControlFlowGraphBaseVisitor visitor = getLabelReplaceVisitor(replacements); visitor.visitGraph(graph); } @@ -199,13 +199,13 @@ public abstract class Pass2SsaOptimization { * * @param replacements Variables that have alias values. */ - public void replaceLabels(ControlFlowBlock block, final Map replacements) { + public void replaceLabels(ControlFlowBlock block, final Map replacements) { ControlFlowGraphBaseVisitor visitor = getLabelReplaceVisitor(replacements); visitor.visitBlock(block); } /** Creates a visitor that can replace labels. */ - private ControlFlowGraphBaseVisitor getLabelReplaceVisitor(final Map replacements) { + private ControlFlowGraphBaseVisitor getLabelReplaceVisitor(final Map replacements) { return new ControlFlowGraphBaseVisitor() { @Override @@ -227,7 +227,7 @@ public abstract class Pass2SsaOptimization { @Override public Void visitPhi(StatementPhi phi) { for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) { - Label replacement = getReplacement(replacements, previousSymbol.getBlock()); + LabelRef replacement = getReplacement(replacements, previousSymbol.getBlock()); if (replacement != null) { previousSymbol.setBlock(replacement); } @@ -244,8 +244,8 @@ public abstract class Pass2SsaOptimization { * @param label The label to find a replacement for * @return The alias to use. Null if no replacement exists. */ - private static Label getReplacement(Map replacements, Label label) { - Label replacement = replacements.get(label); + private static LabelRef getReplacement(Map replacements, LabelRef label) { + LabelRef replacement = replacements.get(label); while (replacements.get(replacement) != null) { replacement = replacements.get(replacement); } diff --git a/src/dk/camelot64/kickc/test/TestCompilationOutput.java b/src/dk/camelot64/kickc/test/TestCompilationOutput.java index d60fe55b4..ab7806f91 100644 --- a/src/dk/camelot64/kickc/test/TestCompilationOutput.java +++ b/src/dk/camelot64/kickc/test/TestCompilationOutput.java @@ -61,8 +61,7 @@ public class TestCompilationOutput extends TestCase { refLines = loadReferenceLines(fileName, extension); } catch (Exception e) { writeOutputFile(fileName, extension, outputString); - System.out.println("Error loading reference."+e.getMessage()); - return; + fail("Error loading reference."+e.getMessage()); } // Split output into outLines List outLines = getOutLines(outputString); @@ -71,14 +70,12 @@ public class TestCompilationOutput extends TestCase { if(refLines.size()>i) { String refLine = refLines.get(i); if(!outLine.equals(refLine)) { - System.out.println( + writeOutputFile(fileName, extension, outputString); + fail( "Output does not match reference on line "+i+"\n"+ "Reference: "+refLine+"\n"+ "Output: "+outLine ); - writeOutputFile(fileName, extension, outputString); - System.out.println(); - return; } } }