diff --git a/src/dk/camelot64/kickc/Compiler.java b/src/dk/camelot64/kickc/Compiler.java index ed27f3818..b0e943e5a 100644 --- a/src/dk/camelot64/kickc/Compiler.java +++ b/src/dk/camelot64/kickc/Compiler.java @@ -49,6 +49,7 @@ public class Compiler { KickCParser.FileContext file = pass0ParseInput(input, log); Program program = pass1GenerateSSA(file, log); pass2OptimizeSSA(program, log); + pass3IntervalAnalysis(program, log); AsmProgram asmProgram = pass4GenerateAsm(program, log); pass5OptimizeAsm(asmProgram, log); @@ -84,8 +85,6 @@ public class Compiler { } public AsmProgram pass4GenerateAsm(Program program, CompileLog log) { - Pass4BlockSequencePlanner pass4BlockSequencePlanner = new Pass4BlockSequencePlanner(program); - pass4BlockSequencePlanner.plan(); Pass4RegisterAllocation pass4RegisterAllocation = new Pass4RegisterAllocation(program); pass4RegisterAllocation.allocate(); Pass4CodeGeneration pass4CodeGeneration = new Pass4CodeGeneration(program); @@ -96,6 +95,28 @@ public class Compiler { return asmProgram; } + + private void pass3IntervalAnalysis(Program program, CompileLog log) { + + Pass3BlockSequencePlanner pass3BlockSequencePlanner = new Pass3BlockSequencePlanner(program, log); + pass3BlockSequencePlanner.plan(); + + //Pass3PhiLifting pass3PhiLifting = new Pass3PhiLifting(program, log); + //pass3PhiLifting.perform(); + + log.append("CONTROL FLOW GRAPH - PHI LIFTED"); + log.append(program.getGraph().toString(program.getScope())); + + Pass3IdentifyAliveRanges pass3IdentifyAliveRanges = new Pass3IdentifyAliveRanges(program, log); + pass3IdentifyAliveRanges.findLiveRanges(); + + log.append("CONTROL FLOW GRAPH - LIVE RANGES"); + log.append(program.getGraph().toString(program.getScope())); + log.append("SYMBOLS - LIVE RANGES"); + log.append(program.getScope().getSymbolTableContents()); + + } + public void pass2OptimizeSSA(Program program, CompileLog log) { List optimizations = new ArrayList<>(); optimizations.add(new Pass2CullEmptyBlocks(program, log)); diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index bc641e6d2..435e905ec 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -120,19 +120,19 @@ public class AsmFragment { private String conditionalJumpSignature(StatementConditionalJump conditionalJump, ControlFlowBlock block, ControlFlowGraph graph) { StringBuilder signature = new StringBuilder(); - if (conditionalJump.getRValue1() != null) { - signature.append(bind(conditionalJump.getRValue1())); + if (conditionalJump.getrValue1() != null) { + signature.append(bind(conditionalJump.getrValue1())); } if (conditionalJump.getOperator() != null) { signature.append(getOperatorFragmentName(conditionalJump.getOperator())); } - if (conditionalJump.getRValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getRValue2()).getNumber() == 0) { + if (conditionalJump.getrValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue2()).getNumber() == 0) { signature.append("0"); - } else if (conditionalJump.getRValue2() instanceof ConstantBool) { - ConstantBool boolValue = (ConstantBool) conditionalJump.getRValue2(); + } else if (conditionalJump.getrValue2() instanceof ConstantBool) { + ConstantBool boolValue = (ConstantBool) conditionalJump.getrValue2(); signature.append(boolValue.toString()); } else{ - signature.append(bind(conditionalJump.getRValue2())); + signature.append(bind(conditionalJump.getrValue2())); } signature.append("_then_"); LabelRef destination = conditionalJump.getDestination(); diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraph.java b/src/dk/camelot64/kickc/icl/ControlFlowGraph.java index 56ae8d697..2e948394c 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraph.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraph.java @@ -40,7 +40,15 @@ public class ControlFlowGraph { @JsonIgnore public Collection getAllBlocks() { - return blocks.values(); + if(sequence!=null) { + ArrayList blocks = new ArrayList<>(); + for (LabelRef labelRef : sequence) { + blocks.add(getBlock(labelRef)); + } + return blocks; + } else { + return blocks.values(); + } } public void remove(LabelRef label) { @@ -137,7 +145,7 @@ public class ControlFlowGraph { public String toString(ProgramScope scope) { StringBuffer out = new StringBuffer(); - for (ControlFlowBlock block : blocks.values()) { + for (ControlFlowBlock block : getAllBlocks()) { out.append(block.toString(this, scope)); } return out.toString(); diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java b/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java index 64c8fa72c..9269a2ac0 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraphCopyVisitor.java @@ -137,9 +137,9 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor + * The definition of a variable being alive during a statement is that it is used after the statement by some later instruction in the flow. + * Note especially that a variable is not alive in the very last instruction that uses it. (Ie. in the statement x := y the variable y is not alive if it is not used again later. However in the preceding statement it is alive.) + */ +public class LiveRange { + + /** + * Sorted non-overlapping intervals. + */ + private List intervals; + + public static class LiveInterval { + + /** + * The statement index of the first statement where the variable is assigned. + */ + private int firstStatementIdx; + + /** + * The statement index of the las statement where the variable alive when the statement ends. + *
  • + * If the statement is in the middle of a block: + * The variable is always used in the following statement for assignment or calculation - but never after. + *
  • + * If the statement is the last in a block: + * The variable is available for use in the first statement of following blocks. There the interval may "continue" as another interval - or it may end if the variable is used in the phi-block, and then no more. + *
+ */ + private int lastStatementIdx; + + public LiveInterval(int firstStatementIdx, int lastStatementIdx) { + this.firstStatementIdx = firstStatementIdx; + this.lastStatementIdx = lastStatementIdx; + } + + public int getFirstStatementIdx() { + return firstStatementIdx; + } + + public int getLastStatementIdx() { + return lastStatementIdx; + } + } + + public LiveRange() { + this.intervals = new ArrayList<>(); + } + + /** + * Add a statement to the live range + * + * @param statement The statement to add + * @return true if the live range was modified by the addition. false otherwise + */ + public boolean add(Statement statement) { + return add(getIndex(statement)); + } + + private Integer getIndex(Statement statement) { + Integer index = statement.getIndex(); + if (index == null) { + throw new RuntimeException("Statement index not defined! Live Ranges only work after defining statement indexes (Pass3IdentifyAliveRanges.generateStatementIndexes)."); + } + return index; + } + + /** + * Add an index to the live range + * @param index The index to add + * @return true if the live range was modified. false otherwise + */ + public boolean add(int index) { + for (int i = 0; i < intervals.size(); i++) { + LiveInterval interval = intervals.get(i); + if (index < interval.firstStatementIdx - 1) { + // Add new interval before the current interval + intervals.add(i, new LiveInterval(index, index)); + return true; + } else if(index == interval.firstStatementIdx - 1) { + // Extend the current interval downward + interval.firstStatementIdx = index; + return true; + } else if(index <= interval.lastStatementIdx) { + // Already inside the interval + return false; + } else if(index == interval.lastStatementIdx+1) { + // Extend current interval upward - and check if next interval should be merged + interval.lastStatementIdx = index; + if(i=index) { + if(interval.firstStatementIdx<=index) { + return true; + } else { + return false; + } + } + } + return false; + } + + +} diff --git a/src/dk/camelot64/kickc/icl/ProgramScope.java b/src/dk/camelot64/kickc/icl/ProgramScope.java index a8051be77..f3952470a 100644 --- a/src/dk/camelot64/kickc/icl/ProgramScope.java +++ b/src/dk/camelot64/kickc/icl/ProgramScope.java @@ -11,6 +11,8 @@ public class ProgramScope extends Scope { private RegisterAllocation allocation; + private VariableLiveRanges liveRanges; + public ProgramScope() { super("", null); } @@ -48,6 +50,14 @@ public class ProgramScope extends Scope { return allocation; } + public void setLiveRanges(VariableLiveRanges liveRanges) { + this.liveRanges = liveRanges; + } + + public VariableLiveRanges getLiveRanges() { + return liveRanges; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/src/dk/camelot64/kickc/icl/Statement.java b/src/dk/camelot64/kickc/icl/Statement.java index 1187f4e92..662ebd64f 100644 --- a/src/dk/camelot64/kickc/icl/Statement.java +++ b/src/dk/camelot64/kickc/icl/Statement.java @@ -23,4 +23,9 @@ public interface Statement { String toString(ProgramScope scope); + /** Set the index of the statement. Indexes are used during live range analysis. */ + void setIndex(Integer idx); + + /** Get the index of the statement. Indexes are used during live range analysis. */ + Integer getIndex(); } diff --git a/src/dk/camelot64/kickc/icl/StatementAssignment.java b/src/dk/camelot64/kickc/icl/StatementAssignment.java index 5e5014a96..9d21a4b44 100644 --- a/src/dk/camelot64/kickc/icl/StatementAssignment.java +++ b/src/dk/camelot64/kickc/icl/StatementAssignment.java @@ -13,7 +13,7 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; * lValue := rValue1 <operator> rValue2 */ @JsonPropertyOrder({"lValue", "rValue1", "operator", "rValue2"}) -public class StatementAssignment implements StatementLValue { +public class StatementAssignment extends StatementBase implements StatementLValue { /** The variable being assigned a value by the statement. */ private LValue lValue; @@ -22,10 +22,15 @@ public class StatementAssignment implements StatementLValue { private RValue rValue2; public StatementAssignment(LValue lValue, RValue rValue2) { - this.lValue = lValue; - this.rValue1 = null; - this.operator = null; - this.rValue2 = rValue2; + this(lValue, null, null, rValue2, null); + } + + public StatementAssignment(LValue lValue, Operator operator, RValue rValue2) { + this(lValue, null, operator, rValue2, null); + } + + public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2) { + this(lValue, rValue1, operator, rValue2, null); } public StatementAssignment(Variable lValue, Variable rValue2) { @@ -41,19 +46,15 @@ public class StatementAssignment implements StatementLValue { @JsonProperty("lValue1") LValue lValue, @JsonProperty("rValue1") RValue rValue1, @JsonProperty("operator") Operator operator, - @JsonProperty("rValue2") RValue rValue2) { + @JsonProperty("rValue2") RValue rValue2, + @JsonProperty("index") Integer index) { + super(index); this.lValue = lValue; this.rValue1 = rValue1; this.operator = operator; this.rValue2 = rValue2; } - public StatementAssignment(LValue lValue, Operator operator, RValue rValue2) { - this.lValue = lValue; - this.rValue1 = null; - this.operator = operator; - this.rValue2 = rValue2; - } public LValue getlValue() { return lValue; @@ -95,16 +96,19 @@ public class StatementAssignment implements StatementLValue { @Override public String toString(ProgramScope scope) { return + super.idxString() + lValue.toString(scope) + " ← " + (rValue1==null?"":rValue1.toString(scope)+" ") + (operator==null?"":operator+" ") + - rValue2.toString(scope); + rValue2.toString(scope) + + super.aliveString(scope); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; StatementAssignment that = (StatementAssignment) o; @@ -116,7 +120,8 @@ public class StatementAssignment implements StatementLValue { @Override public int hashCode() { - int result = lValue.hashCode(); + int result = super.hashCode(); + result = 31 * result + lValue.hashCode(); result = 31 * result + (rValue1 != null ? rValue1.hashCode() : 0); result = 31 * result + (operator != null ? operator.hashCode() : 0); result = 31 * result + (rValue2 != null ? rValue2.hashCode() : 0); diff --git a/src/dk/camelot64/kickc/icl/StatementBase.java b/src/dk/camelot64/kickc/icl/StatementBase.java new file mode 100644 index 000000000..82b76cfe7 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/StatementBase.java @@ -0,0 +1,63 @@ +package dk.camelot64.kickc.icl; + +import java.util.List; + +/** Statement base class implementing shared properties and logic */ +public abstract class StatementBase implements Statement { + + private Integer index; + + public StatementBase(Integer index) { + this.index = index; + } + + @Override + public Integer getIndex() { + return index; + } + + @Override + public void setIndex(Integer index) { + this.index = index; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + StatementBase that = (StatementBase) o; + + return index != null ? index.equals(that.index) : that.index == null; + } + + @Override + public int hashCode() { + return index != null ? index.hashCode() : 0; + } + + public String idxString() { + return index==null?"":("["+index+"] "); + } + + @Override + public String toString() { + return toString(null); + } + + public String aliveString(ProgramScope scope) { + if(scope==null || scope.getLiveRanges()==null) { + return ""; + } + VariableLiveRanges liveRanges = scope.getLiveRanges(); + List alive = liveRanges.getAlive(this); + StringBuilder str = new StringBuilder(); + str.append(" [ "); + for (VariableRef variableRef : alive) { + str.append(variableRef.getFullName()); + str.append(" "); + } + str.append("]"); + return str.toString(); + } +} diff --git a/src/dk/camelot64/kickc/icl/StatementCall.java b/src/dk/camelot64/kickc/icl/StatementCall.java index 638b0aff8..2830157e7 100644 --- a/src/dk/camelot64/kickc/icl/StatementCall.java +++ b/src/dk/camelot64/kickc/icl/StatementCall.java @@ -11,17 +11,19 @@ import java.util.List; *
* Xi := call label param1 param2 param3 ... */ -public class StatementCall implements StatementLValue { +public class StatementCall extends StatementBase implements StatementLValue { - /** The variable being assigned a value by the call. Can be null. */ + /** + * 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 boolean parametersByAssignment; - public StatementCall( - LValue lValue, String procedureName, List parameters) { + public StatementCall(LValue lValue, String procedureName, List parameters) { + super(null); this.lValue = lValue; this.procedureName = procedureName; this.parameters = parameters; @@ -34,7 +36,9 @@ public class StatementCall implements StatementLValue { @JsonProperty("procedureName") String procedureName, @JsonProperty("procedure") ProcedureRef procedure, @JsonProperty("parameters") List parameters, - @JsonProperty("parametersByAssignment") boolean parametersByAssignment) { + @JsonProperty("parametersByAssignment") boolean parametersByAssignment, + @JsonProperty("index") Integer index) { + super(index); this.lValue = lValue; this.procedureName = procedureName; this.procedure = procedure; @@ -92,32 +96,29 @@ public class StatementCall implements StatementLValue { this.parametersByAssignment = true; } - @Override - public String toString() { - return toString(null); - } - @Override public String toString(ProgramScope scope) { StringBuilder res = new StringBuilder(); - if(lValue!=null) { + res.append(super.idxString()); + if (lValue != null) { res.append(lValue.toString(scope)); res.append(" ← "); } res.append("call "); - if(procedure!=null) { - res.append(procedure.getFullName()+ " "); - } else { + if (procedure != null) { + res.append(procedure.getFullName() + " "); + } else { res.append(procedureName + " "); } - if(parameters!=null) { + if (parameters != null) { for (RValue parameter : parameters) { res.append(parameter.toString(scope) + " "); } } - if(parametersByAssignment) { + if (parametersByAssignment) { res.append("param-assignment"); } + res.append(super.aliveString(scope)); return res.toString(); } @@ -125,6 +126,7 @@ public class StatementCall implements StatementLValue { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; StatementCall that = (StatementCall) o; @@ -137,7 +139,8 @@ public class StatementCall implements StatementLValue { @Override public int hashCode() { - int result = lValue != null ? lValue.hashCode() : 0; + int result = super.hashCode(); + result = 31 * result + (lValue != null ? lValue.hashCode() : 0); result = 31 * result + procedureName.hashCode(); result = 31 * result + (procedure != null ? procedure.hashCode() : 0); result = 31 * result + (parameters != null ? parameters.hashCode() : 0); diff --git a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java index ab4375d02..623668077 100644 --- a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java +++ b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java @@ -12,7 +12,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; * The condition may be a single boolean variable, or a comparison between two variables (==, <>, <, >, <=, >= ) * */ -public class StatementConditionalJump implements Statement { +public class StatementConditionalJump extends StatementBase { private RValue rValue1; private Operator operator; @@ -20,25 +20,36 @@ public class StatementConditionalJump implements Statement { private LabelRef destination; public StatementConditionalJump(RValue condition, LabelRef destination) { + super(null); this.rValue1 = null; this.operator = null; this.rValue2 = condition; this.destination = destination; } + public StatementConditionalJump( + RValue rValue1, + Operator operator, + RValue rValue2, + LabelRef destination) { + this(rValue1, operator, rValue2, destination, null); + } + @JsonCreator public StatementConditionalJump( @JsonProperty("rValue1") RValue rValue1, @JsonProperty("operator") Operator operator, @JsonProperty("rValue2") RValue rValue2, - @JsonProperty("destination") LabelRef destination) { + @JsonProperty("destination") LabelRef destination, + @JsonProperty("index") Integer index) { + super(index); this.rValue1 = rValue1; this.operator = operator; this.rValue2 = rValue2; this.destination = destination; } - public RValue getRValue1() { + public RValue getrValue1() { return rValue1; } @@ -46,7 +57,7 @@ public class StatementConditionalJump implements Statement { return operator; } - public RValue getRValue2() { + public RValue getrValue2() { return rValue2; } @@ -54,7 +65,7 @@ public class StatementConditionalJump implements Statement { return destination; } - public void setRValue1(RValue rValue1) { + public void setrValue1(RValue rValue1) { this.rValue1 = rValue1; } @@ -62,7 +73,7 @@ public class StatementConditionalJump implements Statement { this.operator = operator; } - public void setRValue2(RValue rValue2) { + public void setrValue2(RValue rValue2) { this.rValue2 = rValue2; } @@ -70,14 +81,10 @@ public class StatementConditionalJump implements Statement { this.destination = destination; } - @Override - public String toString() { - return toString(null); - } - @Override public String toString(ProgramScope scope) { StringBuilder out = new StringBuilder(); + out.append(super.idxString()); out.append("if("); if(rValue1!=null) { out.append(rValue1.toString(scope)); @@ -86,6 +93,7 @@ public class StatementConditionalJump implements Statement { out.append(rValue2.toString(scope)); out.append(") goto "); out.append(destination.getFullName()); + out.append(super.aliveString(scope)); return out.toString(); } @@ -93,6 +101,7 @@ public class StatementConditionalJump implements Statement { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; StatementConditionalJump that = (StatementConditionalJump) o; @@ -104,7 +113,8 @@ public class StatementConditionalJump implements Statement { @Override public int hashCode() { - int result = rValue1 != null ? rValue1.hashCode() : 0; + int result = super.hashCode(); + result = 31 * result + (rValue1 != null ? rValue1.hashCode() : 0); result = 31 * result + (operator != null ? operator.hashCode() : 0); result = 31 * result + (rValue2 != null ? rValue2.hashCode() : 0); result = 31 * result + destination.hashCode(); diff --git a/src/dk/camelot64/kickc/icl/StatementJump.java b/src/dk/camelot64/kickc/icl/StatementJump.java index 689b6b3eb..74f3a11b7 100644 --- a/src/dk/camelot64/kickc/icl/StatementJump.java +++ b/src/dk/camelot64/kickc/icl/StatementJump.java @@ -6,11 +6,12 @@ package dk.camelot64.kickc.icl; *
* goto XX */ -public class StatementJump implements Statement { +public class StatementJump extends StatementBase { private LabelRef destination; public StatementJump(LabelRef destination) { + super(null); this.destination = destination; } @@ -22,14 +23,9 @@ public class StatementJump implements Statement { this.destination = destination; } - @Override - public String toString() { - return toString(null); - } - @Override public String toString(ProgramScope scope) { - return "goto "+destination.getFullName(); + return super.idxString() + "goto " + destination.getFullName()+ super.aliveString(scope); } } diff --git a/src/dk/camelot64/kickc/icl/StatementLabel.java b/src/dk/camelot64/kickc/icl/StatementLabel.java index 500a8b6f9..56789d7a1 100644 --- a/src/dk/camelot64/kickc/icl/StatementLabel.java +++ b/src/dk/camelot64/kickc/icl/StatementLabel.java @@ -3,11 +3,12 @@ package dk.camelot64.kickc.icl; /** * Single Static Assignment Form Statement Jump target. */ -public class StatementLabel implements Statement { +public class StatementLabel extends StatementBase { private LabelRef label; public StatementLabel(LabelRef label) { + super(null); this.label = label; } @@ -15,14 +16,9 @@ public class StatementLabel implements Statement { return label; } - @Override - public String toString() { - return toString(null); - } - @Override public String toString(ProgramScope scope) { - return label.getFullName() + ":"; + return super.idxString() + label.getFullName() + ":"+super.aliveString(scope); } } diff --git a/src/dk/camelot64/kickc/icl/StatementPhiBlock.java b/src/dk/camelot64/kickc/icl/StatementPhiBlock.java index 608463fbe..2ee21ac7a 100644 --- a/src/dk/camelot64/kickc/icl/StatementPhiBlock.java +++ b/src/dk/camelot64/kickc/icl/StatementPhiBlock.java @@ -10,7 +10,7 @@ import java.util.*; * The Phi Block initializing the necessary SSA-variables of a predecessor. * The phi predecessor initializes a number of variables with different values depending on which predecessor control flow enters from. */ -public class StatementPhiBlock implements Statement { +public class StatementPhiBlock extends StatementBase { /** * Maps each phi-varible of the predecessor to a map from a predecessor predecessor to the rvalue of the variable. @@ -19,24 +19,17 @@ public class StatementPhiBlock implements Statement { @JsonCreator public StatementPhiBlock( - @JsonProperty("phiVariables") List phiVariables) { + @JsonProperty("phiVariables") List phiVariables, + @JsonProperty("index") Integer index) { + super(index); this.phiVariables = phiVariables; } public StatementPhiBlock() { + super(null); this.phiVariables = new ArrayList<>(); } - /** - * Get the ordered predecessor blocks where control can enter the predecessor. - * - * @return the predecessor blocks - */ - //public List getPredecessors() { - // return predecessors; - //} - - /** * Get the variables defined by the phi predecessor. * @@ -75,6 +68,7 @@ public class StatementPhiBlock implements Statement { List variables = new ArrayList<>(phiVariables); Collections.reverse(variables); for (PhiVariable phiVariable : variables) { + s.append(super.idxString()); s.append(phiVariable.getVariable().toString(scope)); s.append(" ← phi("); for (PhiRValue phiRValue : phiVariable.getValues()) { @@ -84,7 +78,9 @@ public class StatementPhiBlock implements Statement { RValue rValue = phiRValue.getrValue(); s.append(rValue==null?"null":rValue.toString(scope)); } - s.append(" )\n "); + s.append(" )"); + s.append(super.aliveString(scope)); + s.append("\n "); } if(s.length()>0) { return s.toString().substring(0, s.length() - 3); @@ -108,15 +104,18 @@ public class StatementPhiBlock implements Statement { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; StatementPhiBlock phiBlock = (StatementPhiBlock) o; - return phiVariables != null ? phiVariables.equals(phiBlock.phiVariables) : phiBlock.phiVariables == null; + return phiVariables.equals(phiBlock.phiVariables); } @Override public int hashCode() { - return phiVariables != null ? phiVariables.hashCode() : 0; + int result = super.hashCode(); + result = 31 * result + phiVariables.hashCode(); + return result; } /** diff --git a/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java b/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java index c30214a48..5760d88ca 100644 --- a/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java +++ b/src/dk/camelot64/kickc/icl/StatementProcedureBegin.java @@ -1,7 +1,7 @@ package dk.camelot64.kickc.icl; /** Procedure declaration in SSA */ -public class StatementProcedureBegin implements Statement { +public class StatementProcedureBegin extends StatementBase { private ProcedureRef procedure; @@ -13,6 +13,7 @@ public class StatementProcedureBegin implements Statement { } public StatementProcedureBegin(ProcedureRef procedure) { + super(null); this.procedure = procedure; } @@ -28,14 +29,9 @@ public class StatementProcedureBegin implements Statement { this.strategy = strategy; } - @Override - public String toString() { - return toString(null); - } - @Override public String toString(ProgramScope scope) { - return "proc " + procedure.toString(scope); + return super.idxString() + "proc " + procedure.toString(scope) + super.aliveString(scope); } } diff --git a/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java b/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java index 52c3444d3..2b7e8fa12 100644 --- a/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java +++ b/src/dk/camelot64/kickc/icl/StatementProcedureEnd.java @@ -1,11 +1,14 @@ package dk.camelot64.kickc.icl; -/** Procedure declaration in SSA */ -public class StatementProcedureEnd implements Statement { +/** + * Procedure declaration in SSA + */ +public class StatementProcedureEnd extends StatementBase { private ProcedureRef procedure; public StatementProcedureEnd(ProcedureRef procedure) { + super(null); this.procedure = procedure; } @@ -13,13 +16,8 @@ public class StatementProcedureEnd implements Statement { return procedure; } - @Override - public String toString() { - return toString(null); - } - @Override public String toString(ProgramScope scope) { - return "endproc // "+procedure.getFullName()+"()"; + return super.idxString() + "endproc // " + procedure.getFullName() + "()"+super.aliveString(scope); } } diff --git a/src/dk/camelot64/kickc/icl/StatementReturn.java b/src/dk/camelot64/kickc/icl/StatementReturn.java index f1f67c639..25c6c06de 100644 --- a/src/dk/camelot64/kickc/icl/StatementReturn.java +++ b/src/dk/camelot64/kickc/icl/StatementReturn.java @@ -6,13 +6,23 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** * Return Statement inside procedure in Single Static Assignment Form. */ -public class StatementReturn implements Statement { +public class StatementReturn extends StatementBase { - /** Return value. May be null if not returning a value. */ + /** + * Return value. May be null if not returning a value. + */ private RValue value; + public StatementReturn(RValue value) { + super(null); + this.value = value; + } + @JsonCreator - public StatementReturn( @JsonProperty("value") RValue value) { + StatementReturn( + @JsonProperty("value") RValue value, + @JsonProperty("index") Integer index) { + super(index); this.value = value; } @@ -24,20 +34,16 @@ public class StatementReturn implements Statement { this.value = value; } - @Override - public String toString() { - return toString(null); - } - @Override public String toString(ProgramScope scope) { - return "return " + (value == null ? "" : value.toString(scope)); + return super.idxString() + "return " + (value == null ? "" : value.toString(scope)) + super.aliveString(scope); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; StatementReturn that = (StatementReturn) o; @@ -46,6 +52,8 @@ public class StatementReturn implements Statement { @Override public int hashCode() { - return value != null ? value.hashCode() : 0; + int result = super.hashCode(); + result = 31 * result + (value != null ? value.hashCode() : 0); + return result; } } diff --git a/src/dk/camelot64/kickc/icl/VariableLiveRanges.java b/src/dk/camelot64/kickc/icl/VariableLiveRanges.java new file mode 100644 index 000000000..ecce3ab84 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/VariableLiveRanges.java @@ -0,0 +1,47 @@ +package dk.camelot64.kickc.icl; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +/** Live ranges for all variables. */ +public class VariableLiveRanges { + + private LinkedHashMap liveRanges; + + public VariableLiveRanges() { + this.liveRanges = new LinkedHashMap<>(); + } + + /** Add a single statement to the live range of a variable. + * + * @param variable The variable + * @param statement The statement to add + * @return true if a live range was modified by the addition + */ + public boolean addAlive(VariableRef variable, Statement statement) { + LiveRange liveRange = liveRanges.get(variable); + if (liveRange == null) { + liveRange = new LiveRange(); + liveRanges.put(variable, liveRange); + } + return liveRange.add(statement); + } + + /** + * Get all variables alive at a specific statement + * @param statement The statement + * @return List of all live variables. + */ + public List getAlive(Statement statement) { + ArrayList aliveVars = new ArrayList<>(); + for (VariableRef variable : liveRanges.keySet()) { + LiveRange liveRange = liveRanges.get(variable); + if(liveRange.contains(statement)) { + aliveVars.add(variable); + } + } + return aliveVars; + } + +} diff --git a/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java b/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java index 02d8cadbe..5629f2e5b 100644 --- a/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java +++ b/src/dk/camelot64/kickc/passes/Pass2AssertSymbols.java @@ -114,8 +114,8 @@ public class Pass2AssertSymbols extends Pass2SsaAssertion { @Override public Void visitConditionalJump(StatementConditionalJump conditionalJump) { - addSymbol(conditionalJump.getRValue1()); - addSymbol(conditionalJump.getRValue2()); + addSymbol(conditionalJump.getrValue1()); + addSymbol(conditionalJump.getrValue2()); addSymbol(conditionalJump.getDestination()); return super.visitConditionalJump(conditionalJump); } diff --git a/src/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java b/src/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java index a113099e0..d8c76b8a7 100644 --- a/src/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java +++ b/src/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java @@ -36,8 +36,8 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization { ControlFlowGraphBaseVisitor visitor = new ControlFlowGraphBaseVisitor() { @Override public Void visitConditionalJump(StatementConditionalJump conditionalJump) { - if(conditionalJump.getRValue1()==null && conditionalJump.getOperator()==null) { - RValue conditionRValue = conditionalJump.getRValue2(); + if(conditionalJump.getrValue1()==null && conditionalJump.getOperator()==null) { + RValue conditionRValue = conditionalJump.getrValue2(); if(conditionRValue instanceof VariableRef && usages.get(conditionRValue).size()==1) { VariableRef conditionVar = (VariableRef) conditionRValue; StatementAssignment conditionAssignment = assignments.get(conditionVar); @@ -52,9 +52,9 @@ public class Pass2ConditionalJumpSimplification extends Pass2SsaOptimization { case "=<": case ">=": case "=>": - conditionalJump.setRValue1(conditionAssignment.getrValue1()); + conditionalJump.setrValue1(conditionAssignment.getrValue1()); conditionalJump.setOperator(conditionAssignment.getOperator()); - conditionalJump.setRValue2(conditionAssignment.getrValue2()); + conditionalJump.setrValue2(conditionAssignment.getrValue2()); simpleConditionVars.add(conditionVar); log.append("Simple Condition " + conditionVar.toString(getSymbols()) + " " + conditionalJump.toString(getSymbols())); break; diff --git a/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java b/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java index b6541d7de..0fbd3dad3 100644 --- a/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java +++ b/src/dk/camelot64/kickc/passes/Pass2SsaOptimization.java @@ -107,11 +107,11 @@ public abstract class Pass2SsaOptimization { @Override public Void visitConditionalJump(StatementConditionalJump conditionalJump) { - if (getAlias(aliases, conditionalJump.getRValue1()) != null) { - conditionalJump.setRValue1(getAlias(aliases, conditionalJump.getRValue1())); + if (getAlias(aliases, conditionalJump.getrValue1()) != null) { + conditionalJump.setrValue1(getAlias(aliases, conditionalJump.getrValue1())); } - if (getAlias(aliases, conditionalJump.getRValue2()) != null) { - conditionalJump.setRValue2(getAlias(aliases, conditionalJump.getRValue2())); + if (getAlias(aliases, conditionalJump.getrValue2()) != null) { + conditionalJump.setrValue2(getAlias(aliases, conditionalJump.getrValue2())); } return null; } @@ -319,8 +319,8 @@ public abstract class Pass2SsaOptimization { @Override public Void visitConditionalJump(StatementConditionalJump conditionalJump) { - addUsage(conditionalJump.getRValue1(), conditionalJump); - addUsage(conditionalJump.getRValue2(), conditionalJump); + addUsage(conditionalJump.getrValue1(), conditionalJump); + addUsage(conditionalJump.getrValue2(), conditionalJump); return null; } diff --git a/src/dk/camelot64/kickc/passes/Pass4BlockSequencePlanner.java b/src/dk/camelot64/kickc/passes/Pass3BlockSequencePlanner.java similarity index 75% rename from src/dk/camelot64/kickc/passes/Pass4BlockSequencePlanner.java rename to src/dk/camelot64/kickc/passes/Pass3BlockSequencePlanner.java index 1eb8cd956..b47b4c142 100644 --- a/src/dk/camelot64/kickc/passes/Pass4BlockSequencePlanner.java +++ b/src/dk/camelot64/kickc/passes/Pass3BlockSequencePlanner.java @@ -1,5 +1,6 @@ package dk.camelot64.kickc.passes; +import dk.camelot64.kickc.CompileLog; import dk.camelot64.kickc.icl.*; import java.util.ArrayList; @@ -7,14 +8,16 @@ import java.util.List; import java.util.Stack; /** Plan the optimal sequence for the blocks of the control flow graph */ -public class Pass4BlockSequencePlanner { +public class Pass3BlockSequencePlanner { private ControlFlowGraph graph; private ProgramScope scope; + private CompileLog log; - public Pass4BlockSequencePlanner(Program program) { + public Pass3BlockSequencePlanner(Program program, CompileLog log) { this.graph = program.getGraph(); this.scope = program.getScope(); + this.log = log; } public void plan() { @@ -46,5 +49,14 @@ public class Pass4BlockSequencePlanner { } } graph.setSequence(sequence); + + StringBuilder entry = new StringBuilder(); + entry.append("Block Sequence Planned "); + for (LabelRef labelRef : sequence) { + entry.append(labelRef.getFullName() + " "); + + } + log.append(entry.toString()); + } } diff --git a/src/dk/camelot64/kickc/passes/Pass3IdentifyAliveRanges.java b/src/dk/camelot64/kickc/passes/Pass3IdentifyAliveRanges.java new file mode 100644 index 000000000..789f37688 --- /dev/null +++ b/src/dk/camelot64/kickc/passes/Pass3IdentifyAliveRanges.java @@ -0,0 +1,368 @@ +package dk.camelot64.kickc.passes; + +/** + * Identify the alive intervals for all variables. Add the intervals to the ProgramScope. + */ + +import dk.camelot64.kickc.CompileLog; +import dk.camelot64.kickc.icl.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Pass3IdentifyAliveRanges { + + private final Program program; + private final CompileLog log; + + public Pass3IdentifyAliveRanges(Program program, CompileLog log) { + this.program = program; + this.log = log; + } + + public void findLiveRanges() { + generateStatementIndexes(); + VariableLiveRanges liveRanges = initializeLiveRanges(); + program.getScope().setLiveRanges(liveRanges); + //log.append("CONTROL FLOW GRAPH - LIVE RANGES"); + //log.append(program.getGraph().toString(program.getScope())); + boolean propagating; + do { + propagating = propagateLiveRanges(liveRanges); + program.getScope().setLiveRanges(liveRanges); + log.append("Propagating live ranges..."); + //log.append("CONTROL FLOW GRAPH - LIVE RANGES"); + //log.append(program.getGraph().toString(program.getScope())); + } while (propagating); + program.getScope().setLiveRanges(liveRanges); + } + + + /** + * Create index numbers for all statements in the control flow graph. + */ + private void generateStatementIndexes() { + int currentIdx = 0; + for (ControlFlowBlock block : program.getGraph().getAllBlocks()) { + for (Statement statement : block.getStatements()) { + statement.setIndex(currentIdx++); + } + } + } + + /** + * Create initial live ranges for all variables used in the program. + * The initial live ranges include only the statements preceding a usage of a variable. The live ranges will be extended iteratively afterwards. + * + * @return The initial live ranges. + */ + private VariableLiveRanges initializeLiveRanges() { + LiveRangeInitializer liveRangeInitializer = new LiveRangeInitializer(program); + return liveRangeInitializer.initialize(); + } + + private static class LiveRangeInitializer extends ControlFlowGraphBaseVisitor { + + private final Program program; + private VariableLiveRanges liveRanges; + + /** + * Contains the previous statement through the iteration of each block. null if this statement is the first in the block. + */ + private Statement previousStatement; + /** + * Contains the current block through the iteration. Used to find previous statement(s) when at the start of a block. + */ + private ControlFlowBlock currentBlock; + + public LiveRangeInitializer(Program program) { + this.program = program; + this.liveRanges = new VariableLiveRanges(); + } + + public VariableLiveRanges initialize() { + this.visitGraph(program.getGraph()); + return liveRanges; + } + + @Override + public Void visitBlock(ControlFlowBlock block) { + this.currentBlock = block; + this.previousStatement = null; + return super.visitBlock(block); + } + + @Override + public Void visitStatement(Statement statement) { + super.visitStatement(statement); + this.previousStatement = statement; + return null; + } + + private void addInitialLiveRange(RValue rValue) { + if (rValue == null) { + return; + } else if (rValue instanceof Constant) { + return; + } else if (rValue instanceof PointerDereferenceSimple) { + addInitialLiveRange(((PointerDereferenceSimple) rValue).getPointer()); + } else if (rValue instanceof PointerDereferenceIndexed) { + addInitialLiveRange(((PointerDereferenceIndexed) rValue).getPointer()); + addInitialLiveRange(((PointerDereferenceIndexed) rValue).getIndex()); + } else if (rValue instanceof VariableRef) { + if (previousStatement != null) { + // Inside a block - add live range to previous statement + liveRanges.addAlive((VariableRef) rValue, previousStatement); + } else { + // At start of block without a phi block - add live range at end of all previous blocks + List predecessors = program.getGraph().getPredecessors(currentBlock); + for (ControlFlowBlock predecessor : predecessors) { + List predecessorStatements = predecessor.getStatements(); + Statement predecessorLastStatement = predecessorStatements.get(predecessorStatements.size() - 1); + liveRanges.addAlive((VariableRef) rValue, predecessorLastStatement); + } + } + } else { + throw new RuntimeException("Unhandled RValue type " + rValue); + } + } + + @Override + public Void visitPhiBlock(StatementPhiBlock phi) { + for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) { + for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { + if (phiRValue.getrValue() instanceof Constant) { + continue; + } else { + LabelRef predecessorRef = phiRValue.getPredecessor(); + ControlFlowBlock predecessor = program.getGraph().getBlock(predecessorRef); + List predecessorStatements = predecessor.getStatements(); + Statement predecessorLastStatement = predecessorStatements.get(predecessorStatements.size() - 1); + liveRanges.addAlive((VariableRef) phiRValue.getrValue(), predecessorLastStatement); + } + } + } + return null; + } + + @Override + public Void visitCall(StatementCall callLValue) { + if (callLValue.getlValue() instanceof PointerDereferenceIndexed) { + addInitialLiveRange(((PointerDereferenceIndexed) callLValue.getlValue()).getPointer()); + addInitialLiveRange(((PointerDereferenceIndexed) callLValue.getlValue()).getIndex()); + } else if (callLValue.getlValue() instanceof PointerDereferenceSimple) { + addInitialLiveRange(((PointerDereferenceSimple) callLValue.getlValue()).getPointer()); + } + if (callLValue.getParameters() != null) { + for (RValue parameter : callLValue.getParameters()) { + addInitialLiveRange(parameter); + } + } + return null; + } + + @Override + public Void visitReturn(StatementReturn aReturn) { + addInitialLiveRange(aReturn.getValue()); + return null; + } + + @Override + public Void visitAssignment(StatementAssignment assignment) { + if (assignment.getlValue() instanceof PointerDereferenceIndexed) { + addInitialLiveRange(((PointerDereferenceIndexed) assignment.getlValue()).getPointer()); + addInitialLiveRange(((PointerDereferenceIndexed) assignment.getlValue()).getIndex()); + } else if (assignment.getlValue() instanceof PointerDereferenceSimple) { + addInitialLiveRange(((PointerDereferenceSimple) assignment.getlValue()).getPointer()); + } + addInitialLiveRange(assignment.getrValue1()); + addInitialLiveRange(assignment.getrValue2()); + return null; + } + + @Override + public Void visitConditionalJump(StatementConditionalJump conditionalJump) { + addInitialLiveRange(conditionalJump.getrValue1()); + addInitialLiveRange(conditionalJump.getrValue2()); + return null; + } + + } + + /** + * Propagate live ranges to previous statements until reaching the definition of the variable. + * + * @return true if any propagation was done. (and more propagation is necessary to complete the live ranges) + */ + private boolean propagateLiveRanges(VariableLiveRanges liveRanges) { + LiveRangePropagator liveRangePropagator = new LiveRangePropagator(program, liveRanges); + return liveRangePropagator.propagate(); + } + + private static class LiveRangePropagator extends ControlFlowGraphBaseVisitor { + + /** + * The program. + */ + private Program program; + + /** + * The variable live ranges being propagated. + */ + private VariableLiveRanges liveRanges; + + /** + * Has anything been modified. + */ + private boolean modified; + + /** + * Contains the previous statement through the iteration of each block. null if this statement is the first in the block. + */ + private Statement previousStatement; + + /** + * Contains the current block through the iteration. Used to find previous statement(s) when at the start of a block. + */ + private ControlFlowBlock currentBlock; + + public LiveRangePropagator(Program program, VariableLiveRanges liveRanges) { + this.program = program; + this.liveRanges = liveRanges; + this.modified = false; + } + + public boolean propagate() { + this.visitGraph(program.getGraph()); + return modified; + } + + @Override + public Void visitBlock(ControlFlowBlock block) { + this.currentBlock = block; + this.previousStatement = null; + return super.visitBlock(block); + } + + @Override + public Void visitStatement(Statement statement) { + super.visitStatement(statement); + this.previousStatement = statement; + return null; + } + + /** + * Propagate variable live ranges backward from a statement to a previous statement + * + * @param statement The current statement + * @param previous The previous statement + * @param defined The lValues assigned in the current statement (will not be propagated) + */ + private void propagate(Statement statement, List previous, List defined) { + List alive = liveRanges.getAlive(statement); + if (defined != null) { + for (LValue lValue : defined) { + if (lValue instanceof VariableRef) { + // Remove the defined variable + alive.remove(lValue); + } + } + } + // Add all non-defined alive vars to all previous statement + for (VariableRef var : alive) { + for (Statement prev : previous) { + modified |= liveRanges.addAlive(var, prev); + } + } + } + + private List getPreviousStatements() { + if (previousStatement != null) { + // Inside a block + return Arrays.asList(previousStatement); + } else { + // At start of block - add last statement of all previous blocks + return getPreviousStatements(this.currentBlock); + } + } + + private ArrayList getPreviousStatements(ControlFlowBlock block) { + ArrayList statements = new ArrayList<>(); + List predecessors = program.getGraph().getPredecessors(block); + for (ControlFlowBlock predecessor : predecessors) { + List predecessorStatements = predecessor.getStatements(); + if (predecessorStatements.size() == 0) { + // Predecessor has no statements - go further back! + statements.addAll(getPreviousStatements(predecessor)); + } else { + // Add last statement from predecessor + Statement predecessorLastStatement = predecessorStatements.get(predecessorStatements.size() - 1); + statements.add(predecessorLastStatement); + } + } + return statements; + } + + @Override + public Void visitPhiBlock(StatementPhiBlock phi) { + List defined = new ArrayList<>(); + for (StatementPhiBlock.PhiVariable phiVariable : phi.getPhiVariables()) { + defined.add(phiVariable.getVariable()); + } + propagate(phi, getPreviousStatements(), defined); + return null; + } + + @Override + public Void visitCall(StatementCall callLValue) { + if (callLValue.getlValue() != null) { + propagate(callLValue, getPreviousStatements(), Arrays.asList(callLValue.getlValue())); + } + return null; + } + + @Override + public Void visitAssignment(StatementAssignment assignment) { + if (assignment.getlValue() != null) { + propagate(assignment, getPreviousStatements(), Arrays.asList(assignment.getlValue())); + } + return null; + } + + @Override + public Void visitConditionalJump(StatementConditionalJump conditionalJump) { + propagate(conditionalJump, getPreviousStatements(), new ArrayList()); + return null; + } + + @Override + public Void visitJump(StatementJump jump) { + propagate(jump, getPreviousStatements(), new ArrayList()); + return null; + } + + @Override + public Void visitReturn(StatementReturn aReturn) { + propagate(aReturn, getPreviousStatements(), new ArrayList()); + return null; + } + + @Override + public Void visitProcedureBegin(StatementProcedureBegin statement) { + throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + statement); + } + + @Override + public Void visitProcedureEnd(StatementProcedureEnd statement) { + throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + statement); + } + + @Override + public Void visitJumpTarget(StatementLabel jumpTarget) { + throw new RuntimeException("Statement not supported during live range propagation. Should be eliminated in earlier phase. " + jumpTarget); + } + } + + +} diff --git a/src/dk/camelot64/kickc/passes/Pass3PhiLifting.java b/src/dk/camelot64/kickc/passes/Pass3PhiLifting.java new file mode 100644 index 000000000..958eeef41 --- /dev/null +++ b/src/dk/camelot64/kickc/passes/Pass3PhiLifting.java @@ -0,0 +1,60 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.CompileLog; +import dk.camelot64.kickc.icl.*; + +import java.util.Collection; +import java.util.List; + +/** + * Perform PhiLifting to greatly reduce overlapping of alive intervals for variables. + * PhiLifting introduces a large number of new virtual variables (one for each rvalue in phi-functions). + * Most of these are eliminated again by the PhiMemCoalesce pass. + *

+ * See http://compilers.cs.ucla.edu/fernando/projects/soc/reports/short_tech.pdf + */ +public class Pass3PhiLifting { + + private final Program program; + + private final CompileLog log; + + public Pass3PhiLifting(Program program, CompileLog log) { + this.program = program; + this.log = log; + } + + public void perform() { + ControlFlowGraph graph = program.getGraph(); + ProgramScope programScope = program.getScope(); + Collection blocks = graph.getAllBlocks(); + for (ControlFlowBlock block : blocks) { + if (block.hasPhiBlock()) { + StatementPhiBlock phiBlock = block.getPhiBlock(); + for (StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) { + for (StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { + if (!(phiRValue.getrValue() instanceof Constant)) { + LabelRef predecessorRef = phiRValue.getPredecessor(); + ControlFlowBlock predecessorBlock = graph.getBlock(predecessorRef); + Symbol predecessorSymbol = programScope.getSymbol(predecessorRef); + VariableIntermediate newVar = predecessorSymbol.getScope().addVariableIntermediate(); + Symbol phiLValue = programScope.getSymbol(phiVariable.getVariable()); + newVar.setType(phiLValue.getType()); + newVar.setInferredType(true); + List predecessorStatements = predecessorBlock.getStatements(); + Statement lastPredecessorStatement = predecessorStatements.get(predecessorStatements.size() - 1); + StatementAssignment newAssignment = new StatementAssignment(newVar, phiRValue.getrValue()); + if (lastPredecessorStatement instanceof StatementConditionalJump || lastPredecessorStatement instanceof StatementCall) { + predecessorStatements.add(predecessorStatements.size() - 1, newAssignment); + } else { + predecessorBlock.addStatement(newAssignment); + } + phiRValue.setrValue(newVar.getRef()); + } + } + } + } + } + } + +} diff --git a/src/dk/camelot64/kickc/test/ReferenceHelper.java b/src/dk/camelot64/kickc/test/ReferenceHelper.java new file mode 100644 index 000000000..c08ebd6e4 --- /dev/null +++ b/src/dk/camelot64/kickc/test/ReferenceHelper.java @@ -0,0 +1,96 @@ +package dk.camelot64.kickc.test; + +import java.io.*; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +/** Helper for handling reference files and output files in tests. */ +public class ReferenceHelper { + + private static Path tempDir; + + static { + try { + tempDir = Files.createTempDirectory("kickc-output"); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private String refPath; + + public ReferenceHelper(String refPath) { + this.refPath = refPath; + } + + public boolean testOutput( + String fileName, + String extension, + String outputString) throws IOException, URISyntaxException { + // Read reference file + List refLines = null; + try { + refLines = loadReferenceLines(fileName, extension); + } catch (Exception e) { + writeOutputFile(fileName, extension, outputString); + System.out.println("Reference file not found "+refPath+fileName+extension); + return false; + } + // Split output into outLines + List outLines = getOutLines(outputString); + for (int i = 0; i < outLines.size(); i++) { + String outLine = outLines.get(i); + if(refLines.size()>i) { + String refLine = refLines.get(i); + if(!outLine.equals(refLine)) { + writeOutputFile(fileName, extension, outputString); + System.out.println( + "Output does not match reference on line "+i+"\n"+ + "Reference: "+refLine+"\n"+ + "Output: "+outLine + ); + return false; + } + } + } + return true; + } + + private List getOutLines(String outputString) throws IOException { + BufferedReader rdr = new BufferedReader(new StringReader(outputString)); + List outLines = new ArrayList<>(); + for (String line = rdr.readLine(); line != null; line = rdr.readLine()) { + outLines.add(line); + } + rdr.close(); + return outLines; + } + + private List loadReferenceLines(String fileName, String extension) throws URISyntaxException, IOException { + String refFile = refPath+fileName+extension; + ClassLoader classLoader = this.getClass().getClassLoader(); + URL refResource = classLoader.getResource(refFile); + URI refURI = refResource.toURI(); + return Files.readAllLines(Paths.get(refURI), Charset.defaultCharset()); + } + + private void writeOutputFile(String fileName, String extension, String outputString) throws IOException { + // Write output file + File file = new File(tempDir.toFile(), fileName + extension); + FileOutputStream outputStream = new FileOutputStream(file); + OutputStreamWriter writer = new OutputStreamWriter(outputStream); + writer.write(outputString); + writer.close(); + outputStream.close(); + System.out.println("Output written to " + file.getAbsolutePath()); + } + + +} diff --git a/src/dk/camelot64/kickc/test/TestCompilationOutput.java b/src/dk/camelot64/kickc/test/TestCompilationOutput.java index 71d45401d..a3fa837d8 100644 --- a/src/dk/camelot64/kickc/test/TestCompilationOutput.java +++ b/src/dk/camelot64/kickc/test/TestCompilationOutput.java @@ -16,17 +16,19 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; -/** Compile a number of source files and compare the resulting assembler with expected output*/ +/** + * Compile a number of source files and compare the resulting assembler with expected output + */ public class TestCompilationOutput extends TestCase { - private Path tempDir; - private String testPath; - private String refPath; + ReferenceHelper helper; + + String testPath; public TestCompilationOutput() throws IOException { testPath = "src/dk/camelot64/kickc/test/"; - refPath = "dk/camelot64/kickc/test/ref/"; - tempDir = Files.createTempDirectory("kickc-output"); + helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/"); + } public void testFlipper() throws IOException, URISyntaxException { @@ -56,80 +58,19 @@ public class TestCompilationOutput extends TestCase { private void testFile(String fileName) throws IOException, URISyntaxException { String inputPath = testPath + fileName + ".kc"; - System.out.println("Testing output for "+inputPath); + System.out.println("Testing output for " + inputPath); CharStream input = CharStreams.fromFileName(inputPath); Compiler compiler = new Compiler(); Compiler.CompilationResult output = compiler.compile(input); boolean success = true; - success &= testOutput(fileName, ".asm", output.getAsmProgram().toString(false)); - success &= testOutput(fileName, ".sym", output.getSymbols().getSymbolTableContents()); - success &= testOutput(fileName, ".cfg", output.getGraph().toString(output.getSymbols())); - success &= testOutput(fileName, ".log", output.getLog().toString()); - if(!success) { + success &= helper.testOutput(fileName, ".asm", output.getAsmProgram().toString(false)); + success &= helper.testOutput(fileName, ".sym", output.getSymbols().getSymbolTableContents()); + success &= helper.testOutput(fileName, ".cfg", output.getGraph().toString(output.getSymbols())); + success &= helper.testOutput(fileName, ".log", output.getLog().toString()); + if (!success) { fail("Output does not match reference!"); } } - private boolean testOutput( - String fileName, - String extension, - String outputString) throws IOException, URISyntaxException { - // Read reference file - List refLines = null; - try { - refLines = loadReferenceLines(fileName, extension); - } catch (Exception e) { - writeOutputFile(fileName, extension, outputString); - System.out.println("Reference file not found "+refPath+fileName+extension); - return false; - } - // Split output into outLines - List outLines = getOutLines(outputString); - for (int i = 0; i < outLines.size(); i++) { - String outLine = outLines.get(i); - if(refLines.size()>i) { - String refLine = refLines.get(i); - if(!outLine.equals(refLine)) { - writeOutputFile(fileName, extension, outputString); - System.out.println( - "Output does not match reference on line "+i+"\n"+ - "Reference: "+refLine+"\n"+ - "Output: "+outLine - ); - return false; - } - } - } - return true; - } - - private List getOutLines(String outputString) throws IOException { - BufferedReader rdr = new BufferedReader(new StringReader(outputString)); - List outLines = new ArrayList<>(); - for (String line = rdr.readLine(); line != null; line = rdr.readLine()) { - outLines.add(line); - } - rdr.close(); - return outLines; - } - - private List loadReferenceLines(String fileName, String extension) throws URISyntaxException, IOException { - String refFile = refPath+fileName+extension; - ClassLoader classLoader = this.getClass().getClassLoader(); - URL refResource = classLoader.getResource(refFile); - URI refURI = refResource.toURI(); - return Files.readAllLines(Paths.get(refURI), Charset.defaultCharset()); - } - - private void writeOutputFile(String fileName, String extension, String outputString) throws IOException { - // Write output file - File file = new File(tempDir.toFile(), fileName + extension); - FileOutputStream outputStream = new FileOutputStream(file); - OutputStreamWriter writer = new OutputStreamWriter(outputStream); - writer.write(outputString); - writer.close(); - outputStream.close(); - System.out.println("Output written to " + file.getAbsolutePath()); - } } \ No newline at end of file diff --git a/src/dk/camelot64/kickc/test/TestIclJson.java b/src/dk/camelot64/kickc/test/TestIclJson.java index 1038309b9..18b281c98 100644 --- a/src/dk/camelot64/kickc/test/TestIclJson.java +++ b/src/dk/camelot64/kickc/test/TestIclJson.java @@ -32,7 +32,7 @@ public class TestIclJson extends TestCase { scope.addVariable("v3", new SymbolTypeArray(SymbolTypeBasic.WORD, 4)); scope.addLabel("main"); scope.addLabelIntermediate(); - String json = "{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"v1\":{\"@type\":\"variable_unversioned\",\"name\":\"v1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"v1#0\":{\"@type\":\"variable_versioned\",\"name\":\"v1#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"v1\",\"inferredType\":false},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"var\"},\"inferredType\":false},\"v2\":{\"@type\":\"variable_unversioned\",\"name\":\"v2\",\"type\":{\"@type\":\"pointer\",\"elementType\":{\"@type\":\"basic\",\"typeName\":\"byte\"}},\"nextVersionNumber\":0,\"inferredType\":false},\"v3\":{\"@type\":\"variable_unversioned\",\"name\":\"v3\",\"type\":{\"@type\":\"array\",\"elementType\":{\"@type\":\"basic\",\"typeName\":\"word\"},\"size\":4},\"nextVersionNumber\":0,\"inferredType\":false},\"main\":{\"@type\":\"label\",\"name\":\"main\",\"intermediate\":false},\"@1\":{\"@type\":\"label\",\"name\":\"@1\",\"intermediate\":true}},\"intermediateVarCount\":1,\"intermediateLabelCount\":2,\"allocation\":null}"; + String json = "{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"v1\":{\"@type\":\"variable_unversioned\",\"name\":\"v1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"v1#0\":{\"@type\":\"variable_versioned\",\"name\":\"v1#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"v1\",\"inferredType\":false},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"var\"},\"inferredType\":false},\"v2\":{\"@type\":\"variable_unversioned\",\"name\":\"v2\",\"type\":{\"@type\":\"pointer\",\"elementType\":{\"@type\":\"basic\",\"typeName\":\"byte\"}},\"nextVersionNumber\":0,\"inferredType\":false},\"v3\":{\"@type\":\"variable_unversioned\",\"name\":\"v3\",\"type\":{\"@type\":\"array\",\"elementType\":{\"@type\":\"basic\",\"typeName\":\"word\"},\"size\":4},\"nextVersionNumber\":0,\"inferredType\":false},\"main\":{\"@type\":\"label\",\"name\":\"main\",\"intermediate\":false},\"@1\":{\"@type\":\"label\",\"name\":\"@1\",\"intermediate\":true}},\"intermediateVarCount\":1,\"intermediateLabelCount\":2,\"allocation\":null,\"liveRanges\":null}"; assertJsonSerialization(scope, json, Scope.class); } @@ -44,7 +44,7 @@ public class TestIclJson extends TestCase { parameters.add(new VariableUnversioned("p1", procedure, SymbolTypeBasic.BYTE)); parameters.add(new VariableUnversioned("p2", procedure, SymbolTypeBasic.BOOLEAN)); procedure.setParameters(parameters); - String json = "{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"main\":{\"@type\":\"procedure\",\"name\":\"main\",\"parameterNames\":[\"p1\",\"p2\"],\"symbols\":{\"v2\":{\"@type\":\"variable_unversioned\",\"name\":\"v2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false},\"p1\":{\"@type\":\"variable_unversioned\",\"name\":\"p1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false},\"p2\":{\"@type\":\"variable_unversioned\",\"name\":\"p2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"boolean\"},\"nextVersionNumber\":0,\"inferredType\":false}},\"intermediateVarCount\":0,\"intermediateLabelCount\":1,\"returnType\":{\"@type\":\"basic\",\"typeName\":\"void\"}}},\"intermediateVarCount\":0,\"intermediateLabelCount\":1,\"allocation\":null}"; + String json = "{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"main\":{\"@type\":\"procedure\",\"name\":\"main\",\"parameterNames\":[\"p1\",\"p2\"],\"symbols\":{\"v2\":{\"@type\":\"variable_unversioned\",\"name\":\"v2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false},\"p1\":{\"@type\":\"variable_unversioned\",\"name\":\"p1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":0,\"inferredType\":false},\"p2\":{\"@type\":\"variable_unversioned\",\"name\":\"p2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"boolean\"},\"nextVersionNumber\":0,\"inferredType\":false}},\"intermediateVarCount\":0,\"intermediateLabelCount\":1,\"returnType\":{\"@type\":\"basic\",\"typeName\":\"void\"}}},\"intermediateVarCount\":0,\"intermediateLabelCount\":1,\"allocation\":null,\"liveRanges\":null}"; assertJsonSerialization(scope, json, Scope.class); } @@ -53,10 +53,20 @@ public class TestIclJson extends TestCase { VariableUnversioned v2 = new VariableUnversioned("v2", null, SymbolTypeBasic.BYTE); VariableUnversioned v3 = new VariableUnversioned("v3", null, SymbolTypeBasic.BYTE); StatementAssignment statement = new StatementAssignment(v1.getRef(), v2.getRef(), new Operator("+"), v3.getRef()); - String json = "{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"v1\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"v2\"},\"operator\":{\"operator\":\"+\"},\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"v3\"}}"; + String json = "{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"v1\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"v2\"},\"operator\":{\"operator\":\"+\"},\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"v3\"},\"index\":null}"; assertJsonSerialization(statement, json, Statement.class); } + public void testJsonStmtCondJump() throws IOException { + VariableUnversioned v1 = new VariableUnversioned("v1", null, SymbolTypeBasic.BYTE); + VariableUnversioned v2 = new VariableUnversioned("v2", null, SymbolTypeBasic.BYTE); + Label l1 = new Label("l1", null, false); + Statement statement = new StatementConditionalJump(v1.getRef(), new Operator("+"), v2.getRef(), l1.getRef()); + String json = "{\"@type\":\"cond\",\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"v1\"},\"operator\":{\"operator\":\"+\"},\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"v2\"},\"destination\":{\"@type\":\"labelref\",\"fullName\":\"l1\"},\"index\":null}"; + assertJsonSerialization(statement, json, Statement.class); + } + + public void testJsonStmtPhiBlock() throws IOException { VariableUnversioned v1 = new VariableUnversioned("v1", null, SymbolTypeBasic.BYTE); VariableUnversioned v2 = new VariableUnversioned("v2", null, SymbolTypeBasic.BYTE); @@ -67,7 +77,7 @@ public class TestIclJson extends TestCase { StatementPhiBlock.PhiVariable phiVariable = statement.addPhiVariable(v1.getRef()); phiVariable.setrValue(b1.getRef(), v2.getRef()); phiVariable.setrValue(b2.getRef(), v3.getRef()); - String json = "{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"v1\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"B1\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"v2\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"B2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"v3\"}}]}]}"; + String json = "{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"v1\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"B1\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"v2\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"B2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"v3\"}}]}],\"index\":null}"; assertJsonSerialization(statement, json, Statement.class); } @@ -77,7 +87,7 @@ public class TestIclJson extends TestCase { CompileLog log = new CompileLog(); KickCParser.FileContext file = compiler.pass0ParseInput(new ANTLRInputStream(minProgram), log); Program program = compiler.pass1GenerateSSA(file, log); - String json = "{\"scope\":{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"b\":{\"@type\":\"variable_unversioned\",\"name\":\"b\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"c\":{\"@type\":\"variable_unversioned\",\"name\":\"c\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"@BEGIN\":{\"@type\":\"label\",\"name\":\"@BEGIN\",\"intermediate\":false},\"@END\":{\"@type\":\"label\",\"name\":\"@END\",\"intermediate\":false},\"b#0\":{\"@type\":\"variable_versioned\",\"name\":\"b#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"b\",\"inferredType\":false},\"c#0\":{\"@type\":\"variable_versioned\",\"name\":\"c#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"c\",\"inferredType\":false}},\"intermediateVarCount\":0,\"intermediateLabelCount\":1,\"allocation\":null},\"graph\":{\"blocks\":{\"@BEGIN\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"statements\":[{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"b#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":0}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"c#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"b#0\"}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"@END\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"statements\":[],\"defaultSuccessor\":null,\"conditionalSuccessor\":null,\"callSuccessor\":null}},\"firstBlockRef\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"sequence\":null}}"; + String json = "{\"scope\":{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"b\":{\"@type\":\"variable_unversioned\",\"name\":\"b\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"c\":{\"@type\":\"variable_unversioned\",\"name\":\"c\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"@BEGIN\":{\"@type\":\"label\",\"name\":\"@BEGIN\",\"intermediate\":false},\"@END\":{\"@type\":\"label\",\"name\":\"@END\",\"intermediate\":false},\"b#0\":{\"@type\":\"variable_versioned\",\"name\":\"b#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"b\",\"inferredType\":false},\"c#0\":{\"@type\":\"variable_versioned\",\"name\":\"c#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"c\",\"inferredType\":false}},\"intermediateVarCount\":0,\"intermediateLabelCount\":1,\"allocation\":null,\"liveRanges\":null},\"graph\":{\"blocks\":{\"@BEGIN\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"statements\":[{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"b#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":0},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"c#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"b#0\"},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"@END\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"statements\":[],\"defaultSuccessor\":null,\"conditionalSuccessor\":null,\"callSuccessor\":null}},\"firstBlockRef\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"sequence\":null}}"; assertJsonSerialization(program, json, Program.class); } @@ -91,7 +101,7 @@ public class TestIclJson extends TestCase { CompileLog log = new CompileLog(); KickCParser.FileContext file = compiler.pass0ParseInput(new ANTLRInputStream(minProgram), log); Program program = compiler.pass1GenerateSSA(file, log); - String json = "{\"scope\":{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"s1\":{\"@type\":\"variable_unversioned\",\"name\":\"s1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"s2\":{\"@type\":\"variable_unversioned\",\"name\":\"s2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"$1\":{\"@type\":\"variable_intermediate\",\"name\":\"$1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"sum\":{\"@type\":\"procedure\",\"name\":\"sum\",\"parameterNames\":[\"a\",\"b\"],\"symbols\":{\"@return\":{\"@type\":\"label\",\"name\":\"@return\",\"intermediate\":false},\"return\":{\"@type\":\"variable_unversioned\",\"name\":\"return\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":7,\"inferredType\":false},\"a\":{\"@type\":\"variable_unversioned\",\"name\":\"a\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":3,\"inferredType\":false},\"b\":{\"@type\":\"variable_unversioned\",\"name\":\"b\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":3,\"inferredType\":false},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"a#0\":{\"@type\":\"variable_versioned\",\"name\":\"a#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"a\",\"inferredType\":false},\"b#0\":{\"@type\":\"variable_versioned\",\"name\":\"b#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"b\",\"inferredType\":false},\"return#0\":{\"@type\":\"variable_versioned\",\"name\":\"return#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"a#1\":{\"@type\":\"variable_versioned\",\"name\":\"a#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"a\",\"inferredType\":false},\"b#1\":{\"@type\":\"variable_versioned\",\"name\":\"b#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"b\",\"inferredType\":false},\"return#1\":{\"@type\":\"variable_versioned\",\"name\":\"return#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"return#2\":{\"@type\":\"variable_versioned\",\"name\":\"return#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"return#3\":{\"@type\":\"variable_versioned\",\"name\":\"return#3\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"return#4\":{\"@type\":\"variable_versioned\",\"name\":\"return#4\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"return#5\":{\"@type\":\"variable_versioned\",\"name\":\"return#5\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"a#2\":{\"@type\":\"variable_versioned\",\"name\":\"a#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"a\",\"inferredType\":false},\"b#2\":{\"@type\":\"variable_versioned\",\"name\":\"b#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"b\",\"inferredType\":false},\"return#6\":{\"@type\":\"variable_versioned\",\"name\":\"return#6\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false}},\"intermediateVarCount\":1,\"intermediateLabelCount\":2,\"returnType\":{\"@type\":\"basic\",\"typeName\":\"byte\"}},\"@BEGIN\":{\"@type\":\"label\",\"name\":\"@BEGIN\",\"intermediate\":false},\"@END\":{\"@type\":\"label\",\"name\":\"@END\",\"intermediate\":false},\"@2\":{\"@type\":\"label\",\"name\":\"@2\",\"intermediate\":true},\"@3\":{\"@type\":\"label\",\"name\":\"@3\",\"intermediate\":true},\"s1#0\":{\"@type\":\"variable_versioned\",\"name\":\"s1#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"s1\",\"inferredType\":false},\"s2#0\":{\"@type\":\"variable_versioned\",\"name\":\"s2#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"s2\",\"inferredType\":false}},\"intermediateVarCount\":2,\"intermediateLabelCount\":4,\"allocation\":null},\"graph\":{\"blocks\":{\"@BEGIN\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"statements\":[{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::a#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":1}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::b#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":2}},{\"@type\":\"call\",\"lValue\":null,\"procedureName\":\"sum\",\"procedure\":{\"@type\":\"procref\",\"fullName\":\"sum\"},\"parameters\":null,\"parametersByAssignment\":true},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#3\"}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"conditionalSuccessor\":null,\"callSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"sum\"}},\"@2\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::return#4\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#0\"}}]}]},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#4\"}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"s1#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$0\"}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::a#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":9}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::b#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":13}},{\"@type\":\"call\",\"lValue\":null,\"procedureName\":\"sum\",\"procedure\":{\"@type\":\"procref\",\"fullName\":\"sum\"},\"parameters\":null,\"parametersByAssignment\":true},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#3\"}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@3\"},\"conditionalSuccessor\":null,\"callSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"sum\"}},\"@3\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@3\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::return#5\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#1\"}}]}]},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#5\"}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"s2#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$1\"}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"sum\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"sum\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::a#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::a#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::a#0\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::b#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::b#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::b#0\"}}]}]},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::$0\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"sum::a#2\"},\"operator\":{\"operator\":\"+\"},\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::b#2\"}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#2\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::$0\"}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"sum::@return\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"sum::@return\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"sum::@return\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::return#6\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"sum\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#2\"}}]}]},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#3\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#6\"}},{\"@type\":\"return\",\"value\":{\"@type\":\"varref\",\"fullName\":\"sum::return#3\"}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@RETURN\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"@END\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"statements\":[],\"defaultSuccessor\":null,\"conditionalSuccessor\":null,\"callSuccessor\":null}},\"firstBlockRef\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"sequence\":null}}"; + String json = "{\"scope\":{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"s1\":{\"@type\":\"variable_unversioned\",\"name\":\"s1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"s2\":{\"@type\":\"variable_unversioned\",\"name\":\"s2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":1,\"inferredType\":false},\"$1\":{\"@type\":\"variable_intermediate\",\"name\":\"$1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"sum\":{\"@type\":\"procedure\",\"name\":\"sum\",\"parameterNames\":[\"a\",\"b\"],\"symbols\":{\"@return\":{\"@type\":\"label\",\"name\":\"@return\",\"intermediate\":false},\"return\":{\"@type\":\"variable_unversioned\",\"name\":\"return\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":7,\"inferredType\":false},\"a\":{\"@type\":\"variable_unversioned\",\"name\":\"a\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":3,\"inferredType\":false},\"b\":{\"@type\":\"variable_unversioned\",\"name\":\"b\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":3,\"inferredType\":false},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"a#0\":{\"@type\":\"variable_versioned\",\"name\":\"a#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"a\",\"inferredType\":false},\"b#0\":{\"@type\":\"variable_versioned\",\"name\":\"b#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"b\",\"inferredType\":false},\"return#0\":{\"@type\":\"variable_versioned\",\"name\":\"return#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"a#1\":{\"@type\":\"variable_versioned\",\"name\":\"a#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"a\",\"inferredType\":false},\"b#1\":{\"@type\":\"variable_versioned\",\"name\":\"b#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"b\",\"inferredType\":false},\"return#1\":{\"@type\":\"variable_versioned\",\"name\":\"return#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"return#2\":{\"@type\":\"variable_versioned\",\"name\":\"return#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"return#3\":{\"@type\":\"variable_versioned\",\"name\":\"return#3\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"return#4\":{\"@type\":\"variable_versioned\",\"name\":\"return#4\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"return#5\":{\"@type\":\"variable_versioned\",\"name\":\"return#5\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false},\"a#2\":{\"@type\":\"variable_versioned\",\"name\":\"a#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"a\",\"inferredType\":false},\"b#2\":{\"@type\":\"variable_versioned\",\"name\":\"b#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"b\",\"inferredType\":false},\"return#6\":{\"@type\":\"variable_versioned\",\"name\":\"return#6\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"return\",\"inferredType\":false}},\"intermediateVarCount\":1,\"intermediateLabelCount\":2,\"returnType\":{\"@type\":\"basic\",\"typeName\":\"byte\"}},\"@BEGIN\":{\"@type\":\"label\",\"name\":\"@BEGIN\",\"intermediate\":false},\"@END\":{\"@type\":\"label\",\"name\":\"@END\",\"intermediate\":false},\"@2\":{\"@type\":\"label\",\"name\":\"@2\",\"intermediate\":true},\"@3\":{\"@type\":\"label\",\"name\":\"@3\",\"intermediate\":true},\"s1#0\":{\"@type\":\"variable_versioned\",\"name\":\"s1#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"s1\",\"inferredType\":false},\"s2#0\":{\"@type\":\"variable_versioned\",\"name\":\"s2#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"s2\",\"inferredType\":false}},\"intermediateVarCount\":2,\"intermediateLabelCount\":4,\"allocation\":null,\"liveRanges\":null},\"graph\":{\"blocks\":{\"@BEGIN\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"statements\":[{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::a#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":1},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::b#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":2},\"index\":null},{\"@type\":\"call\",\"lValue\":null,\"procedureName\":\"sum\",\"procedure\":{\"@type\":\"procref\",\"fullName\":\"sum\"},\"parameters\":null,\"parametersByAssignment\":true,\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#3\"},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"conditionalSuccessor\":null,\"callSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"sum\"}},\"@2\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::return#4\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#0\"}}]}],\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#4\"},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"s1#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$0\"},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::a#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":9},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::b#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":13},\"index\":null},{\"@type\":\"call\",\"lValue\":null,\"procedureName\":\"sum\",\"procedure\":{\"@type\":\"procref\",\"fullName\":\"sum\"},\"parameters\":null,\"parametersByAssignment\":true,\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#3\"},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@3\"},\"conditionalSuccessor\":null,\"callSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"sum\"}},\"@3\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@3\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::return#5\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#1\"}}]}],\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#5\"},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"s2#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$1\"},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"sum\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"sum\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::a#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::a#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::a#0\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::b#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::b#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::b#0\"}}]}],\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::$0\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"sum::a#2\"},\"operator\":{\"operator\":\"+\"},\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::b#2\"},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#2\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::$0\"},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"sum::@return\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"sum::@return\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"sum::@return\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"sum::return#6\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"sum\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#2\"}}]}],\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"sum::return#3\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"sum::return#6\"},\"index\":null},{\"@type\":\"return\",\"value\":{\"@type\":\"varref\",\"fullName\":\"sum::return#3\"},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@RETURN\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"@END\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"statements\":[],\"defaultSuccessor\":null,\"conditionalSuccessor\":null,\"callSuccessor\":null}},\"firstBlockRef\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"sequence\":null}}"; assertJsonSerialization(program, json, Program.class); } @@ -102,7 +112,7 @@ public class TestIclJson extends TestCase { CompileLog log = new CompileLog(); KickCParser.FileContext file = compiler.pass0ParseInput(new ANTLRInputStream(minProgram), log); Program program = compiler.pass1GenerateSSA(file, log); - String json = "{\"scope\":{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"n1\":{\"@type\":\"variable_unversioned\",\"name\":\"n1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":4,\"inferredType\":false},\"n2\":{\"@type\":\"variable_unversioned\",\"name\":\"n2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":4,\"inferredType\":false},\"i\":{\"@type\":\"variable_unversioned\",\"name\":\"i\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":4,\"inferredType\":false},\"fib\":{\"@type\":\"variable_unversioned\",\"name\":\"fib\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":2,\"inferredType\":false},\"@1\":{\"@type\":\"label\",\"name\":\"@1\",\"intermediate\":true},\"@2\":{\"@type\":\"label\",\"name\":\"@2\",\"intermediate\":true},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"boolean\"},\"inferredType\":true},\"$1\":{\"@type\":\"variable_intermediate\",\"name\":\"$1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"$2\":{\"@type\":\"variable_intermediate\",\"name\":\"$2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"@BEGIN\":{\"@type\":\"label\",\"name\":\"@BEGIN\",\"intermediate\":false},\"@END\":{\"@type\":\"label\",\"name\":\"@END\",\"intermediate\":false},\"n1#0\":{\"@type\":\"variable_versioned\",\"name\":\"n1#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n1\",\"inferredType\":false},\"n2#0\":{\"@type\":\"variable_versioned\",\"name\":\"n2#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n2\",\"inferredType\":false},\"i#0\":{\"@type\":\"variable_versioned\",\"name\":\"i#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"i\",\"inferredType\":false},\"fib#0\":{\"@type\":\"variable_versioned\",\"name\":\"fib#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"fib\",\"inferredType\":false},\"fib#1\":{\"@type\":\"variable_versioned\",\"name\":\"fib#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"fib\",\"inferredType\":false},\"n1#1\":{\"@type\":\"variable_versioned\",\"name\":\"n1#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n1\",\"inferredType\":false},\"n2#1\":{\"@type\":\"variable_versioned\",\"name\":\"n2#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n2\",\"inferredType\":false},\"i#1\":{\"@type\":\"variable_versioned\",\"name\":\"i#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"i\",\"inferredType\":false},\"i#2\":{\"@type\":\"variable_versioned\",\"name\":\"i#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"i\",\"inferredType\":false},\"n1#2\":{\"@type\":\"variable_versioned\",\"name\":\"n1#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n1\",\"inferredType\":false},\"n2#2\":{\"@type\":\"variable_versioned\",\"name\":\"n2#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n2\",\"inferredType\":false},\"i#3\":{\"@type\":\"variable_versioned\",\"name\":\"i#3\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"i\",\"inferredType\":false},\"n1#3\":{\"@type\":\"variable_versioned\",\"name\":\"n1#3\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n1\",\"inferredType\":false},\"n2#3\":{\"@type\":\"variable_versioned\",\"name\":\"n2#3\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n2\",\"inferredType\":false}},\"intermediateVarCount\":3,\"intermediateLabelCount\":7,\"allocation\":null},\"graph\":{\"blocks\":{\"@BEGIN\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"statements\":[{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"n1#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":0}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"n2#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":1}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"i#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":12}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"fib#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":0}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"@1\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"i#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"i#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"i#0\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"n1#3\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n1#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n1#0\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"n2#3\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n2#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n2#0\"}}]}]},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$0\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"i#2\"},\"operator\":{\"operator\":\">\"},\"rValue2\":{\"@type\":\"integer\",\"number\":0}},{\"@type\":\"cond\",\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$0\"},\"destination\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rvalue1\":null,\"rvalue2\":{\"@type\":\"varref\",\"fullName\":\"$0\"}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"conditionalSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"callSuccessor\":null},\"@2\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"n1#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n1#3\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"n2#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n2#3\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"i#3\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"i#2\"}}]}]},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$1\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"n1#2\"},\"operator\":{\"operator\":\"+\"},\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"n2#2\"}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"fib#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$1\"}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"n1#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"n2#2\"}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"n2#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"fib#1\"}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$2\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"i#3\"},\"operator\":{\"operator\":\"-\"},\"rValue2\":{\"@type\":\"integer\",\"number\":1}},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"i#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$2\"}}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"@END\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"statements\":[],\"defaultSuccessor\":null,\"conditionalSuccessor\":null,\"callSuccessor\":null}},\"firstBlockRef\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"sequence\":null}}"; + String json = "{\"scope\":{\"@type\":\"program\",\"name\":\"\",\"symbols\":{\"n1\":{\"@type\":\"variable_unversioned\",\"name\":\"n1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":4,\"inferredType\":false},\"n2\":{\"@type\":\"variable_unversioned\",\"name\":\"n2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":4,\"inferredType\":false},\"i\":{\"@type\":\"variable_unversioned\",\"name\":\"i\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":4,\"inferredType\":false},\"fib\":{\"@type\":\"variable_unversioned\",\"name\":\"fib\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"nextVersionNumber\":2,\"inferredType\":false},\"@1\":{\"@type\":\"label\",\"name\":\"@1\",\"intermediate\":true},\"@2\":{\"@type\":\"label\",\"name\":\"@2\",\"intermediate\":true},\"$0\":{\"@type\":\"variable_intermediate\",\"name\":\"$0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"boolean\"},\"inferredType\":true},\"$1\":{\"@type\":\"variable_intermediate\",\"name\":\"$1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"$2\":{\"@type\":\"variable_intermediate\",\"name\":\"$2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"inferredType\":true},\"@BEGIN\":{\"@type\":\"label\",\"name\":\"@BEGIN\",\"intermediate\":false},\"@END\":{\"@type\":\"label\",\"name\":\"@END\",\"intermediate\":false},\"n1#0\":{\"@type\":\"variable_versioned\",\"name\":\"n1#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n1\",\"inferredType\":false},\"n2#0\":{\"@type\":\"variable_versioned\",\"name\":\"n2#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n2\",\"inferredType\":false},\"i#0\":{\"@type\":\"variable_versioned\",\"name\":\"i#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"i\",\"inferredType\":false},\"fib#0\":{\"@type\":\"variable_versioned\",\"name\":\"fib#0\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"fib\",\"inferredType\":false},\"fib#1\":{\"@type\":\"variable_versioned\",\"name\":\"fib#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"fib\",\"inferredType\":false},\"n1#1\":{\"@type\":\"variable_versioned\",\"name\":\"n1#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n1\",\"inferredType\":false},\"n2#1\":{\"@type\":\"variable_versioned\",\"name\":\"n2#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n2\",\"inferredType\":false},\"i#1\":{\"@type\":\"variable_versioned\",\"name\":\"i#1\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"i\",\"inferredType\":false},\"i#2\":{\"@type\":\"variable_versioned\",\"name\":\"i#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"i\",\"inferredType\":false},\"n1#2\":{\"@type\":\"variable_versioned\",\"name\":\"n1#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n1\",\"inferredType\":false},\"n2#2\":{\"@type\":\"variable_versioned\",\"name\":\"n2#2\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n2\",\"inferredType\":false},\"i#3\":{\"@type\":\"variable_versioned\",\"name\":\"i#3\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"i\",\"inferredType\":false},\"n1#3\":{\"@type\":\"variable_versioned\",\"name\":\"n1#3\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n1\",\"inferredType\":false},\"n2#3\":{\"@type\":\"variable_versioned\",\"name\":\"n2#3\",\"type\":{\"@type\":\"basic\",\"typeName\":\"byte\"},\"versionOfName\":\"n2\",\"inferredType\":false}},\"intermediateVarCount\":3,\"intermediateLabelCount\":7,\"allocation\":null,\"liveRanges\":null},\"graph\":{\"blocks\":{\"@BEGIN\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"statements\":[{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"n1#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":0},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"n2#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":1},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"i#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":12},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"fib#0\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"integer\",\"number\":0},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"@1\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"i#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"i#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"i#0\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"n1#3\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n1#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n1#0\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"n2#3\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n2#1\"}},{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n2#0\"}}]}],\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$0\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"i#2\"},\"operator\":{\"operator\":\">\"},\"rValue2\":{\"@type\":\"integer\",\"number\":0},\"index\":null},{\"@type\":\"cond\",\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$0\"},\"destination\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"conditionalSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"callSuccessor\":null},\"@2\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@2\"},\"statements\":[{\"@type\":\"phiblock\",\"phiVariables\":[{\"variable\":{\"@type\":\"varref\",\"fullName\":\"n1#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n1#3\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"n2#2\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"n2#3\"}}]},{\"variable\":{\"@type\":\"varref\",\"fullName\":\"i#3\"},\"values\":[{\"predecessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"rValue\":{\"@type\":\"varref\",\"fullName\":\"i#2\"}}]}],\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$1\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"n1#2\"},\"operator\":{\"operator\":\"+\"},\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"n2#2\"},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"fib#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$1\"},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"n1#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"n2#2\"},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"n2#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"fib#1\"},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"$2\"},\"rValue1\":{\"@type\":\"varref\",\"fullName\":\"i#3\"},\"operator\":{\"operator\":\"-\"},\"rValue2\":{\"@type\":\"integer\",\"number\":1},\"index\":null},{\"@type\":\"assign\",\"lValue\":{\"@type\":\"varref\",\"fullName\":\"i#1\"},\"rValue1\":null,\"operator\":null,\"rValue2\":{\"@type\":\"varref\",\"fullName\":\"$2\"},\"index\":null}],\"defaultSuccessor\":{\"@type\":\"labelref\",\"fullName\":\"@1\"},\"conditionalSuccessor\":null,\"callSuccessor\":null},\"@END\":{\"label\":{\"@type\":\"labelref\",\"fullName\":\"@END\"},\"statements\":[],\"defaultSuccessor\":null,\"conditionalSuccessor\":null,\"callSuccessor\":null}},\"firstBlockRef\":{\"@type\":\"labelref\",\"fullName\":\"@BEGIN\"},\"sequence\":null}}"; assertJsonSerialization(program, json, Program.class); } diff --git a/src/dk/camelot64/kickc/test/ref/bresenham.cfg b/src/dk/camelot64/kickc/test/ref/bresenham.cfg index bcf651b28..248f2b457 100644 --- a/src/dk/camelot64/kickc/test/ref/bresenham.cfg +++ b/src/dk/camelot64/kickc/test/ref/bresenham.cfg @@ -1,25 +1,25 @@ @BEGIN: from to:@1 @1: from @3 @BEGIN - (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) - (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) 12 ) - (byte) x#2 ← phi( @3/(byte) x#1 @BEGIN/(byte) 0 ) - (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(word) 1024 ) - *((byte*) cursor#3) ← (byte) 81 - (byte) x#1 ← (byte) x#2 + (byte) 1 - (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 - (byte) e#1 ← (byte) e#3 + (byte) 24 - if((byte) 39<(byte) e#1) goto @2 - to:@3 -@2: from @1 - (byte) y#1 ← (byte) y#2 + (byte) 1 - (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 - (byte) e#2 ← (byte) e#1 - (byte) 39 + [0] (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) 12 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte) x#2 ← phi( @3/(byte) x#1 @BEGIN/(byte) 0 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(word) 1024 ) [ cursor#3 x#2 e#3 y#2 ] + [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] + [2] (byte) x#1 ← (byte) x#2 + (byte) 1 [ x#1 cursor#3 e#3 y#2 ] + [3] (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 [ x#1 e#3 cursor#1 y#2 ] + [4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ x#1 e#1 cursor#1 y#2 ] + [5] if((byte) 39<(byte) e#1) goto @2 [ x#1 e#1 cursor#1 y#2 ] to:@3 @3: from @1 @2 - (byte) y#4 ← phi( @1/(byte) y#2 @2/(byte) y#1 ) - (byte) e#5 ← phi( @1/(byte) e#1 @2/(byte) e#2 ) - (byte*) cursor#5 ← phi( @1/(byte*) cursor#1 @2/(byte*) cursor#2 ) - if((byte) x#1<(byte) 40) goto @1 + [6] (byte) y#4 ← phi( @1/(byte) y#2 @2/(byte) y#1 ) [ cursor#5 x#1 e#5 y#4 ] + [6] (byte) e#5 ← phi( @1/(byte) e#1 @2/(byte) e#2 ) [ cursor#5 x#1 e#5 y#4 ] + [6] (byte*) cursor#5 ← phi( @1/(byte*) cursor#1 @2/(byte*) cursor#2 ) [ cursor#5 x#1 e#5 y#4 ] + [7] if((byte) x#1<(byte) 40) goto @1 [ cursor#5 x#1 e#5 y#4 ] to:@END @END: from @3 +@2: from @1 + [8] (byte) y#1 ← (byte) y#2 + (byte) 1 [ x#1 e#1 cursor#1 y#1 ] + [9] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ x#1 e#1 cursor#2 y#1 ] + [10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] + to:@3 diff --git a/src/dk/camelot64/kickc/test/ref/bresenham.log b/src/dk/camelot64/kickc/test/ref/bresenham.log index 5f3cd4688..c8cd8c9d9 100644 --- a/src/dk/camelot64/kickc/test/ref/bresenham.log +++ b/src/dk/camelot64/kickc/test/ref/bresenham.log @@ -843,6 +843,99 @@ Multiple usages for variable. Not optimizing sub-constant (byte) y#2 Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 Multiple usages for variable. Not optimizing sub-constant (byte) y#2 Multiple usages for variable. Not optimizing sub-constant (byte*) cursor#1 +Block Sequence Planned @BEGIN @1 @3 @END @2 +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + to:@1 +@1: from @3 @BEGIN + (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) + (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) 12 ) + (byte) x#2 ← phi( @3/(byte) x#1 @BEGIN/(byte) 0 ) + (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(word) 1024 ) + *((byte*) cursor#3) ← (byte) 81 + (byte) x#1 ← (byte) x#2 + (byte) 1 + (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 + (byte) e#1 ← (byte) e#3 + (byte) 24 + if((byte) 39<(byte) e#1) goto @2 + to:@3 +@3: from @1 @2 + (byte) y#4 ← phi( @1/(byte) y#2 @2/(byte) y#1 ) + (byte) e#5 ← phi( @1/(byte) e#1 @2/(byte) e#2 ) + (byte*) cursor#5 ← phi( @1/(byte*) cursor#1 @2/(byte*) cursor#2 ) + if((byte) x#1<(byte) 40) goto @1 + to:@END +@END: from @3 +@2: from @1 + (byte) y#1 ← (byte) y#2 + (byte) 1 + (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 + (byte) e#2 ← (byte) e#1 - (byte) 39 + to:@3 + +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + to:@1 +@1: from @3 @BEGIN + [0] (byte) y#2 ← phi( @3/(byte) y#4 @BEGIN/(byte) 0 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte) e#3 ← phi( @3/(byte) e#5 @BEGIN/(byte) 12 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte) x#2 ← phi( @3/(byte) x#1 @BEGIN/(byte) 0 ) [ cursor#3 x#2 e#3 y#2 ] + [0] (byte*) cursor#3 ← phi( @3/(byte*) cursor#5 @BEGIN/(word) 1024 ) [ cursor#3 x#2 e#3 y#2 ] + [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] + [2] (byte) x#1 ← (byte) x#2 + (byte) 1 [ x#1 cursor#3 e#3 y#2 ] + [3] (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 [ x#1 e#3 cursor#1 y#2 ] + [4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ x#1 e#1 cursor#1 y#2 ] + [5] if((byte) 39<(byte) e#1) goto @2 [ x#1 e#1 cursor#1 y#2 ] + to:@3 +@3: from @1 @2 + [6] (byte) y#4 ← phi( @1/(byte) y#2 @2/(byte) y#1 ) [ cursor#5 x#1 e#5 y#4 ] + [6] (byte) e#5 ← phi( @1/(byte) e#1 @2/(byte) e#2 ) [ cursor#5 x#1 e#5 y#4 ] + [6] (byte*) cursor#5 ← phi( @1/(byte*) cursor#1 @2/(byte*) cursor#2 ) [ cursor#5 x#1 e#5 y#4 ] + [7] if((byte) x#1<(byte) 40) goto @1 [ cursor#5 x#1 e#5 y#4 ] + to:@END +@END: from @3 +@2: from @1 + [8] (byte) y#1 ← (byte) y#2 + (byte) 1 [ x#1 e#1 cursor#1 y#1 ] + [9] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ x#1 e#1 cursor#2 y#1 ] + [10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] + to:@3 + +SYMBOLS - LIVE RANGES +(label) @1 +(label) @2 +(label) @3 +(label) @BEGIN +(label) @END +(byte[1000]) SCREEN +(byte) STAR +(byte*) cursor +(byte*) cursor#1 +(byte*) cursor#2 +(byte*) cursor#3 +(byte*) cursor#5 +(byte) e +(byte) e#1 +(byte) e#2 +(byte) e#3 +(byte) e#5 +(byte) x +(byte) x#1 +(byte) x#2 +(byte) x0 +(byte) x1 +(byte) xd +(byte) y +(byte) y#1 +(byte) y#2 +(byte) y#4 +(byte) y0 +(byte) y1 +(byte) yd + INITIAL ASM BBEGIN: B1_from_BBEGIN: @@ -878,16 +971,16 @@ B1_from_B3: sta 10+1 jmp B1 B1: - // *((byte*) cursor#3) ← (byte) 81 // zpiby1=coby1 + // [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] // zpiby1=coby1 ldy #0 lda #81 sta (10),y - // (byte) x#1 ← (byte) x#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [2] (byte) x#1 ← (byte) x#2 + (byte) 1 [ x#1 cursor#3 e#3 y#2 ] // zpby1=zpby2_plus_1 lda 12 clc adc #1 sta 2 - // (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 // zpptrby1=zpptrby2_plus_1 + // [3] (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 [ x#1 e#3 cursor#1 y#2 ] // zpptrby1=zpptrby2_plus_1 lda 10 clc adc #1 @@ -895,12 +988,12 @@ B1: lda 10+1 adc #0 sta 3+1 - // (byte) e#1 ← (byte) e#3 + (byte) 24 // zpby1=zpby2_plus_coby1 + // [4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ x#1 e#1 cursor#1 y#2 ] // zpby1=zpby2_plus_coby1 lda 13 clc adc #24 sta 5 - // if((byte) 39<(byte) e#1) goto @2 // coby1_lt_zpby1_then_la1 + // [5] if((byte) 39<(byte) e#1) goto @2 [ x#1 e#1 cursor#1 y#2 ] // coby1_lt_zpby1_then_la1 lda #39 cmp 5 bcc B2 @@ -918,19 +1011,19 @@ B3_from_B1: sta 15+1 jmp B3 B3: - // if((byte) x#1<(byte) 40) goto @1 // zpby1_lt_coby1_then_la1 + // [7] if((byte) x#1<(byte) 40) goto @1 [ cursor#5 x#1 e#5 y#4 ] // zpby1_lt_coby1_then_la1 lda 2 cmp #40 bcc B1_from_B3 jmp BEND BEND: B2: - // (byte) y#1 ← (byte) y#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [8] (byte) y#1 ← (byte) y#2 + (byte) 1 [ x#1 e#1 cursor#1 y#1 ] // zpby1=zpby2_plus_1 lda 14 clc adc #1 sta 6 - // (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 // zpptrby1=zpptrby2_plus_coby1 + // [9] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ x#1 e#1 cursor#2 y#1 ] // zpptrby1=zpptrby2_plus_coby1 lda #40 clc adc 3 @@ -938,7 +1031,7 @@ B2: lda #0 adc 3+1 sta 7+1 - // (byte) e#2 ← (byte) e#1 - (byte) 39 // zpby1=zpby2_minus_coby1 + // [10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] // zpby1=zpby2_minus_coby1 lda 5 sec sbc #39 @@ -960,7 +1053,7 @@ B3_from_B2: Removing instruction jmp B1 Removing instruction jmp B3 Removing instruction jmp BEND -Succesful ASM optimization Pass4NextJumpElimination +Succesful ASM optimization Pass5NextJumpElimination ASSEMBLER BBEGIN: B1_from_BBEGIN: @@ -995,16 +1088,16 @@ B1_from_B3: lda 15+1 sta 10+1 B1: - // *((byte*) cursor#3) ← (byte) 81 // zpiby1=coby1 + // [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] // zpiby1=coby1 ldy #0 lda #81 sta (10),y - // (byte) x#1 ← (byte) x#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [2] (byte) x#1 ← (byte) x#2 + (byte) 1 [ x#1 cursor#3 e#3 y#2 ] // zpby1=zpby2_plus_1 lda 12 clc adc #1 sta 2 - // (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 // zpptrby1=zpptrby2_plus_1 + // [3] (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 [ x#1 e#3 cursor#1 y#2 ] // zpptrby1=zpptrby2_plus_1 lda 10 clc adc #1 @@ -1012,12 +1105,12 @@ B1: lda 10+1 adc #0 sta 3+1 - // (byte) e#1 ← (byte) e#3 + (byte) 24 // zpby1=zpby2_plus_coby1 + // [4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ x#1 e#1 cursor#1 y#2 ] // zpby1=zpby2_plus_coby1 lda 13 clc adc #24 sta 5 - // if((byte) 39<(byte) e#1) goto @2 // coby1_lt_zpby1_then_la1 + // [5] if((byte) 39<(byte) e#1) goto @2 [ x#1 e#1 cursor#1 y#2 ] // coby1_lt_zpby1_then_la1 lda #39 cmp 5 bcc B2 @@ -1034,18 +1127,18 @@ B3_from_B1: lda 3+1 sta 15+1 B3: - // if((byte) x#1<(byte) 40) goto @1 // zpby1_lt_coby1_then_la1 + // [7] if((byte) x#1<(byte) 40) goto @1 [ cursor#5 x#1 e#5 y#4 ] // zpby1_lt_coby1_then_la1 lda 2 cmp #40 bcc B1_from_B3 BEND: B2: - // (byte) y#1 ← (byte) y#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [8] (byte) y#1 ← (byte) y#2 + (byte) 1 [ x#1 e#1 cursor#1 y#1 ] // zpby1=zpby2_plus_1 lda 14 clc adc #1 sta 6 - // (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 // zpptrby1=zpptrby2_plus_coby1 + // [9] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ x#1 e#1 cursor#2 y#1 ] // zpptrby1=zpptrby2_plus_coby1 lda #40 clc adc 3 @@ -1053,7 +1146,7 @@ B2: lda #0 adc 3+1 sta 7+1 - // (byte) e#2 ← (byte) e#1 - (byte) 39 // zpby1=zpby2_minus_coby1 + // [10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] // zpby1=zpby2_minus_coby1 lda 5 sec sbc #39 @@ -1138,16 +1231,16 @@ B1_from_B3: lda 15+1 sta 10+1 B1: - // *((byte*) cursor#3) ← (byte) 81 // zpiby1=coby1 + // [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] // zpiby1=coby1 ldy #0 lda #81 sta (10),y - // (byte) x#1 ← (byte) x#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [2] (byte) x#1 ← (byte) x#2 + (byte) 1 [ x#1 cursor#3 e#3 y#2 ] // zpby1=zpby2_plus_1 lda 12 clc adc #1 sta 2 - // (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 // zpptrby1=zpptrby2_plus_1 + // [3] (byte*) cursor#1 ← (byte*) cursor#3 + (byte) 1 [ x#1 e#3 cursor#1 y#2 ] // zpptrby1=zpptrby2_plus_1 lda 10 clc adc #1 @@ -1155,12 +1248,12 @@ B1: lda 10+1 adc #0 sta 3+1 - // (byte) e#1 ← (byte) e#3 + (byte) 24 // zpby1=zpby2_plus_coby1 + // [4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ x#1 e#1 cursor#1 y#2 ] // zpby1=zpby2_plus_coby1 lda 13 clc adc #24 sta 5 - // if((byte) 39<(byte) e#1) goto @2 // coby1_lt_zpby1_then_la1 + // [5] if((byte) 39<(byte) e#1) goto @2 [ x#1 e#1 cursor#1 y#2 ] // coby1_lt_zpby1_then_la1 lda #39 cmp 5 bcc B2 @@ -1177,18 +1270,18 @@ B3_from_B1: lda 3+1 sta 15+1 B3: - // if((byte) x#1<(byte) 40) goto @1 // zpby1_lt_coby1_then_la1 + // [7] if((byte) x#1<(byte) 40) goto @1 [ cursor#5 x#1 e#5 y#4 ] // zpby1_lt_coby1_then_la1 lda 2 cmp #40 bcc B1_from_B3 BEND: B2: - // (byte) y#1 ← (byte) y#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [8] (byte) y#1 ← (byte) y#2 + (byte) 1 [ x#1 e#1 cursor#1 y#1 ] // zpby1=zpby2_plus_1 lda 14 clc adc #1 sta 6 - // (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 // zpptrby1=zpptrby2_plus_coby1 + // [9] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ x#1 e#1 cursor#2 y#1 ] // zpptrby1=zpptrby2_plus_coby1 lda #40 clc adc 3 @@ -1196,7 +1289,7 @@ B2: lda #0 adc 3+1 sta 7+1 - // (byte) e#2 ← (byte) e#1 - (byte) 39 // zpby1=zpby2_minus_coby1 + // [10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] // zpby1=zpby2_minus_coby1 lda 5 sec sbc #39 diff --git a/src/dk/camelot64/kickc/test/ref/flipper-rex2.cfg b/src/dk/camelot64/kickc/test/ref/flipper-rex2.cfg index c33f368e7..0c747e813 100644 --- a/src/dk/camelot64/kickc/test/ref/flipper-rex2.cfg +++ b/src/dk/camelot64/kickc/test/ref/flipper-rex2.cfg @@ -1,100 +1,100 @@ @BEGIN: from - call main param-assignment + [0] call main param-assignment [ ] to:@END +@END: from @BEGIN main: from @BEGIN - call prepare param-assignment + [1] call prepare param-assignment [ ] to:main::@3 main::@3: from main main::@11 main::@3 main::@6 - (byte) main::c#2 ← phi( main/(byte) 25 main::@11/(byte) 25 main::@6/(byte) main::c#1 ) - (byte~) main::$1 ← * (word) 53266 - if((byte~) main::$1!=(byte) 254) goto main::@3 + [2] (byte) main::c#2 ← phi( main/(byte) 25 main::@11/(byte) 25 main::@6/(byte) main::c#1 ) [ main::c#2 ] + [3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ] + [4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ] to:main::@4 main::@4: from main::@3 main::@4 - (byte~) main::$3 ← * (word) 53266 - if((byte~) main::$3!=(byte) 255) goto main::@4 + [5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ] + [6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ] to:main::@6 main::@6: from main::@4 - (byte) main::c#1 ← -- (byte) main::c#2 - if((byte) main::c#1!=(byte) 0) goto main::@3 + [7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ] + [8] if((byte) main::c#1!=(byte) 0) goto main::@3 [ main::c#1 ] to:main::@7 main::@7: from main::@6 - call flip param-assignment + [9] call flip param-assignment [ ] to:main::@10 main::@10: from main::@7 - call plot param-assignment + [10] call plot param-assignment [ ] to:main::@11 main::@11: from main::@10 - if(true) goto main::@3 + [11] if(true) goto main::@3 [ ] to:main::@return main::@return: from main::@11 - return - to:@RETURN -prepare: from main - to:prepare::@1 -prepare::@1: from prepare prepare::@1 - (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@1/(byte) prepare::i#1 ) - *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 - (byte) prepare::i#1 ← ++ (byte) prepare::i#2 - if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 - to:prepare::@return -prepare::@return: from prepare::@1 - return - to:@RETURN -flip: from main::@7 - to:flip::@1 -flip::@1: from flip flip::@4 - (byte) flip::r#2 ← phi( flip/(byte) 16 flip::@4/(byte) flip::r#1 ) - (byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@4/(byte) flip::dstIdx#2 ) - (byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@4/(byte) flip::srcIdx#1 ) - to:flip::@2 -flip::@2: from flip::@1 flip::@2 - (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 ) - (byte) flip::dstIdx#3 ← phi( flip::@1/(byte) flip::dstIdx#5 flip::@2/(byte) flip::dstIdx#1 ) - (byte) flip::srcIdx#2 ← phi( flip::@1/(byte) flip::srcIdx#3 flip::@2/(byte) flip::srcIdx#1 ) - (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 - *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 - (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 - (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 - (byte) flip::c#1 ← -- (byte) flip::c#2 - if((byte) flip::c#1!=(byte) 0) goto flip::@2 - to:flip::@4 -flip::@4: from flip::@2 - (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 - (byte) flip::r#1 ← -- (byte) flip::r#2 - if((byte) flip::r#1!=(byte) 0) goto flip::@1 - to:flip::@3 -flip::@3: from flip::@3 flip::@4 - (byte) flip::i#2 ← phi( flip::@3/(byte) flip::i#1 flip::@4/(byte) 0 ) - (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 - *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 - (byte) flip::i#1 ← ++ (byte) flip::i#2 - if((byte) flip::i#1!=(byte) 0) goto flip::@3 - to:flip::@return -flip::@return: from flip::@3 - return + [12] return [ ] to:@RETURN plot: from main::@10 to:plot::@1 plot::@1: from plot plot::@3 - (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) - (byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@3/(byte*) plot::line#1 ) - (byte) plot::i#3 ← phi( plot/(byte) 0 plot::@3/(byte) plot::i#1 ) + [13] (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) [ plot::i#3 plot::line#2 plot::y#2 ] + [13] (byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@3/(byte*) plot::line#1 ) [ plot::i#3 plot::line#2 plot::y#2 ] + [13] (byte) plot::i#3 ← phi( plot/(byte) 0 plot::@3/(byte) plot::i#1 ) [ plot::i#3 plot::line#2 plot::y#2 ] to:plot::@2 plot::@2: from plot::@1 plot::@2 - (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 ) - (byte) plot::i#2 ← phi( plot::@1/(byte) plot::i#3 plot::@2/(byte) plot::i#1 ) - (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 - *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 - (byte) plot::i#1 ← ++ (byte) plot::i#2 - (byte) plot::x#1 ← ++ (byte) plot::x#2 - if((byte) plot::x#1<(byte) 16) goto plot::@2 + [14] (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 ) [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [14] (byte) plot::i#2 ← phi( plot::@1/(byte) plot::i#3 plot::@2/(byte) plot::i#1 ) [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [15] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ] + [16] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [17] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::i#1 plot::line#2 plot::x#2 plot::y#2 ] + [18] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] + [19] if((byte) plot::x#1<(byte) 16) goto plot::@2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] to:plot::@3 plot::@3: from plot::@2 - (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 - (byte) plot::y#1 ← -- (byte) plot::y#2 - if((byte) plot::y#1!=(byte) 0) goto plot::@1 + [20] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::i#1 plot::line#1 plot::y#2 ] + [21] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::i#1 plot::line#1 plot::y#1 ] + [22] if((byte) plot::y#1!=(byte) 0) goto plot::@1 [ plot::i#1 plot::line#1 plot::y#1 ] to:plot::@return plot::@return: from plot::@3 - return + [23] return [ ] + to:@RETURN +flip: from main::@7 + to:flip::@1 +flip::@1: from flip flip::@4 + [24] (byte) flip::r#2 ← phi( flip/(byte) 16 flip::@4/(byte) flip::r#1 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + [24] (byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@4/(byte) flip::dstIdx#2 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + [24] (byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@4/(byte) flip::srcIdx#1 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + to:flip::@2 +flip::@2: from flip::@1 flip::@2 + [25] (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [25] (byte) flip::dstIdx#3 ← phi( flip::@1/(byte) flip::dstIdx#5 flip::@2/(byte) flip::dstIdx#1 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [25] (byte) flip::srcIdx#2 ← phi( flip::@1/(byte) flip::srcIdx#3 flip::@2/(byte) flip::srcIdx#1 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [26] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ] + [27] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [28] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::srcIdx#1 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [29] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#2 flip::r#2 ] + [30] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] + [31] if((byte) flip::c#1!=(byte) 0) goto flip::@2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] + to:flip::@4 +flip::@4: from flip::@2 + [32] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#2 ] + [33] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] + [34] if((byte) flip::r#1!=(byte) 0) goto flip::@1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] + to:flip::@3 +flip::@3: from flip::@3 flip::@4 + [35] (byte) flip::i#2 ← phi( flip::@3/(byte) flip::i#1 flip::@4/(byte) 0 ) [ flip::i#2 ] + [36] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ] + [37] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ] + [38] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ] + [39] if((byte) flip::i#1!=(byte) 0) goto flip::@3 [ flip::i#1 ] + to:flip::@return +flip::@return: from flip::@3 + [40] return [ ] + to:@RETURN +prepare: from main + to:prepare::@1 +prepare::@1: from prepare prepare::@1 + [41] (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@1/(byte) prepare::i#1 ) [ prepare::i#2 ] + [42] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ] + [43] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ] + [44] if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 [ prepare::i#1 ] + to:prepare::@return +prepare::@return: from prepare::@1 + [45] return [ ] to:@RETURN -@END: from @BEGIN diff --git a/src/dk/camelot64/kickc/test/ref/flipper-rex2.log b/src/dk/camelot64/kickc/test/ref/flipper-rex2.log index a1f10027c..867154f34 100644 --- a/src/dk/camelot64/kickc/test/ref/flipper-rex2.log +++ b/src/dk/camelot64/kickc/test/ref/flipper-rex2.log @@ -3309,6 +3309,296 @@ Multiple usages for variable. Not optimizing sub-constant (byte) flip::srcIdx#2 Multiple usages for variable. Not optimizing sub-constant (byte) flip::i#2 Multiple usages for variable. Not optimizing sub-constant (byte) flip::i#2 Multiple usages for variable. Not optimizing sub-constant (byte) plot::i#2 +Block Sequence Planned @BEGIN @END main main::@3 main::@4 main::@6 main::@7 main::@10 main::@11 main::@return plot plot::@1 plot::@2 plot::@3 plot::@return flip flip::@1 flip::@2 flip::@4 flip::@3 flip::@return prepare prepare::@1 prepare::@return +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + call main param-assignment + to:@END +@END: from @BEGIN +main: from @BEGIN + call prepare param-assignment + to:main::@3 +main::@3: from main main::@11 main::@3 main::@6 + (byte) main::c#2 ← phi( main/(byte) 25 main::@6/(byte) main::c#1 main::@11/(byte) 25 ) + (byte~) main::$1 ← * (word) 53266 + if((byte~) main::$1!=(byte) 254) goto main::@3 + to:main::@4 +main::@4: from main::@3 main::@4 + (byte~) main::$3 ← * (word) 53266 + if((byte~) main::$3!=(byte) 255) goto main::@4 + to:main::@6 +main::@6: from main::@4 + (byte) main::c#1 ← -- (byte) main::c#2 + if((byte) main::c#1!=(byte) 0) goto main::@3 + to:main::@7 +main::@7: from main::@6 + call flip param-assignment + to:main::@10 +main::@10: from main::@7 + call plot param-assignment + to:main::@11 +main::@11: from main::@10 + if(true) goto main::@3 + to:main::@return +main::@return: from main::@11 + return + to:@RETURN +plot: from main::@10 + to:plot::@1 +plot::@1: from plot plot::@3 + (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) + (byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@3/(byte*) plot::line#1 ) + (byte) plot::i#3 ← phi( plot/(byte) 0 plot::@3/(byte) plot::i#1 ) + to:plot::@2 +plot::@2: from plot::@1 plot::@2 + (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 ) + (byte) plot::i#2 ← phi( plot::@1/(byte) plot::i#3 plot::@2/(byte) plot::i#1 ) + (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 + *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 + (byte) plot::i#1 ← ++ (byte) plot::i#2 + (byte) plot::x#1 ← ++ (byte) plot::x#2 + if((byte) plot::x#1<(byte) 16) goto plot::@2 + to:plot::@3 +plot::@3: from plot::@2 + (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 + (byte) plot::y#1 ← -- (byte) plot::y#2 + if((byte) plot::y#1!=(byte) 0) goto plot::@1 + to:plot::@return +plot::@return: from plot::@3 + return + to:@RETURN +flip: from main::@7 + to:flip::@1 +flip::@1: from flip flip::@4 + (byte) flip::r#2 ← phi( flip/(byte) 16 flip::@4/(byte) flip::r#1 ) + (byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@4/(byte) flip::dstIdx#2 ) + (byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@4/(byte) flip::srcIdx#1 ) + to:flip::@2 +flip::@2: from flip::@1 flip::@2 + (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 ) + (byte) flip::dstIdx#3 ← phi( flip::@1/(byte) flip::dstIdx#5 flip::@2/(byte) flip::dstIdx#1 ) + (byte) flip::srcIdx#2 ← phi( flip::@1/(byte) flip::srcIdx#3 flip::@2/(byte) flip::srcIdx#1 ) + (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 + *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 + (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 + (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 + (byte) flip::c#1 ← -- (byte) flip::c#2 + if((byte) flip::c#1!=(byte) 0) goto flip::@2 + to:flip::@4 +flip::@4: from flip::@2 + (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 + (byte) flip::r#1 ← -- (byte) flip::r#2 + if((byte) flip::r#1!=(byte) 0) goto flip::@1 + to:flip::@3 +flip::@3: from flip::@3 flip::@4 + (byte) flip::i#2 ← phi( flip::@3/(byte) flip::i#1 flip::@4/(byte) 0 ) + (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 + *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 + (byte) flip::i#1 ← ++ (byte) flip::i#2 + if((byte) flip::i#1!=(byte) 0) goto flip::@3 + to:flip::@return +flip::@return: from flip::@3 + return + to:@RETURN +prepare: from main + to:prepare::@1 +prepare::@1: from prepare prepare::@1 + (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@1/(byte) prepare::i#1 ) + *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 + (byte) prepare::i#1 ← ++ (byte) prepare::i#2 + if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 + to:prepare::@return +prepare::@return: from prepare::@1 + return + to:@RETURN + +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + [0] call main param-assignment [ ] + to:@END +@END: from @BEGIN +main: from @BEGIN + [1] call prepare param-assignment [ ] + to:main::@3 +main::@3: from main main::@11 main::@3 main::@6 + [2] (byte) main::c#2 ← phi( main/(byte) 25 main::@6/(byte) main::c#1 main::@11/(byte) 25 ) [ main::c#2 ] + [3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ] + [4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ] + to:main::@4 +main::@4: from main::@3 main::@4 + [5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ] + [6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ] + to:main::@6 +main::@6: from main::@4 + [7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ] + [8] if((byte) main::c#1!=(byte) 0) goto main::@3 [ main::c#1 ] + to:main::@7 +main::@7: from main::@6 + [9] call flip param-assignment [ ] + to:main::@10 +main::@10: from main::@7 + [10] call plot param-assignment [ ] + to:main::@11 +main::@11: from main::@10 + [11] if(true) goto main::@3 [ ] + to:main::@return +main::@return: from main::@11 + [12] return [ ] + to:@RETURN +plot: from main::@10 + to:plot::@1 +plot::@1: from plot plot::@3 + [13] (byte) plot::y#2 ← phi( plot/(byte) 16 plot::@3/(byte) plot::y#1 ) [ plot::i#3 plot::line#2 plot::y#2 ] + [13] (byte*) plot::line#2 ← phi( plot/(word) 1236 plot::@3/(byte*) plot::line#1 ) [ plot::i#3 plot::line#2 plot::y#2 ] + [13] (byte) plot::i#3 ← phi( plot/(byte) 0 plot::@3/(byte) plot::i#1 ) [ plot::i#3 plot::line#2 plot::y#2 ] + to:plot::@2 +plot::@2: from plot::@1 plot::@2 + [14] (byte) plot::x#2 ← phi( plot::@1/(byte) 0 plot::@2/(byte) plot::x#1 ) [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [14] (byte) plot::i#2 ← phi( plot::@1/(byte) plot::i#3 plot::@2/(byte) plot::i#1 ) [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [15] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ] + [16] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] + [17] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::i#1 plot::line#2 plot::x#2 plot::y#2 ] + [18] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] + [19] if((byte) plot::x#1<(byte) 16) goto plot::@2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] + to:plot::@3 +plot::@3: from plot::@2 + [20] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::i#1 plot::line#1 plot::y#2 ] + [21] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::i#1 plot::line#1 plot::y#1 ] + [22] if((byte) plot::y#1!=(byte) 0) goto plot::@1 [ plot::i#1 plot::line#1 plot::y#1 ] + to:plot::@return +plot::@return: from plot::@3 + [23] return [ ] + to:@RETURN +flip: from main::@7 + to:flip::@1 +flip::@1: from flip flip::@4 + [24] (byte) flip::r#2 ← phi( flip/(byte) 16 flip::@4/(byte) flip::r#1 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + [24] (byte) flip::dstIdx#5 ← phi( flip/(byte) 15 flip::@4/(byte) flip::dstIdx#2 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + [24] (byte) flip::srcIdx#3 ← phi( flip/(byte) 0 flip::@4/(byte) flip::srcIdx#1 ) [ flip::srcIdx#3 flip::dstIdx#5 flip::r#2 ] + to:flip::@2 +flip::@2: from flip::@1 flip::@2 + [25] (byte) flip::c#2 ← phi( flip::@1/(byte) 16 flip::@2/(byte) flip::c#1 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [25] (byte) flip::dstIdx#3 ← phi( flip::@1/(byte) flip::dstIdx#5 flip::@2/(byte) flip::dstIdx#1 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [25] (byte) flip::srcIdx#2 ← phi( flip::@1/(byte) flip::srcIdx#3 flip::@2/(byte) flip::srcIdx#1 ) [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [26] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ] + [27] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [28] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::srcIdx#1 flip::dstIdx#3 flip::c#2 flip::r#2 ] + [29] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#2 flip::r#2 ] + [30] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] + [31] if((byte) flip::c#1!=(byte) 0) goto flip::@2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] + to:flip::@4 +flip::@4: from flip::@2 + [32] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#2 ] + [33] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] + [34] if((byte) flip::r#1!=(byte) 0) goto flip::@1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] + to:flip::@3 +flip::@3: from flip::@3 flip::@4 + [35] (byte) flip::i#2 ← phi( flip::@3/(byte) flip::i#1 flip::@4/(byte) 0 ) [ flip::i#2 ] + [36] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ] + [37] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ] + [38] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ] + [39] if((byte) flip::i#1!=(byte) 0) goto flip::@3 [ flip::i#1 ] + to:flip::@return +flip::@return: from flip::@3 + [40] return [ ] + to:@RETURN +prepare: from main + to:prepare::@1 +prepare::@1: from prepare prepare::@1 + [41] (byte) prepare::i#2 ← phi( prepare/(byte) 0 prepare::@1/(byte) prepare::i#1 ) [ prepare::i#2 ] + [42] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ] + [43] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ] + [44] if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 [ prepare::i#1 ] + to:prepare::@return +prepare::@return: from prepare::@1 + [45] return [ ] + to:@RETURN + +SYMBOLS - LIVE RANGES +(label) @BEGIN +(label) @END +(byte*) RASTER +(byte[1000]) SCREEN +(byte[256]) buffer1 +(byte[256]) buffer2 +(void()) flip() +(byte~) flip::$0 +(byte~) flip::$4 +(label) flip::@1 +(label) flip::@2 +(label) flip::@3 +(label) flip::@4 +(label) flip::@return +(byte) flip::c +(byte) flip::c#1 +(byte) flip::c#2 +(byte) flip::dstIdx +(byte) flip::dstIdx#1 +(byte) flip::dstIdx#2 +(byte) flip::dstIdx#3 +(byte) flip::dstIdx#5 +(byte) flip::i +(byte) flip::i#1 +(byte) flip::i#2 +(byte) flip::r +(byte) flip::r#1 +(byte) flip::r#2 +(byte) flip::srcIdx +(byte) flip::srcIdx#1 +(byte) flip::srcIdx#2 +(byte) flip::srcIdx#3 + +(void()) main() +(byte~) main::$1 +(byte~) main::$3 +(label) main::@10 +(label) main::@11 +(label) main::@3 +(label) main::@4 +(label) main::@6 +(label) main::@7 +(label) main::@return +(byte) main::c +(byte) main::c#1 +(byte) main::c#2 + +(void()) plot() +(byte~) plot::$3 +(label) plot::@1 +(label) plot::@2 +(label) plot::@3 +(label) plot::@return +(byte) plot::i +(byte) plot::i#1 +(byte) plot::i#2 +(byte) plot::i#3 +(byte*) plot::line +(byte*) plot::line#1 +(byte*) plot::line#2 +(byte) plot::x +(byte) plot::x#1 +(byte) plot::x#2 +(byte) plot::y +(byte) plot::y#1 +(byte) plot::y#2 + +(void()) prepare() +(label) prepare::@1 +(label) prepare::@return +(byte) prepare::i +(byte) prepare::i#1 +(byte) prepare::i#2 + + INITIAL ASM BBEGIN: jsr main @@ -3330,23 +3620,23 @@ main__B3_from_B6: // (byte) main::c#2 = (byte) main::c#1 // register copy jmp main__B3 main__B3: - // (byte~) main::$1 ← * (word) 53266 // aby=_star_cowo1 + // [3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$1!=(byte) 254) goto main::@3 // aby_neq_coby1_then_la1 + // [4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #254 bne main__B3_from_B3 jmp main__B4 main__B4: - // (byte~) main::$3 ← * (word) 53266 // aby=_star_cowo1 + // [5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$3!=(byte) 255) goto main::@4 // aby_neq_coby1_then_la1 + // [6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #255 bne main__main__B4 jmp main__B6 main__B6: - // (byte) main::c#1 ← -- (byte) main::c#2 // xby=_dec_xby + // [7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ] // xby=_dec_xby dex - // if((byte) main::c#1!=(byte) 0) goto main::@3 // xby_neq_0_then_la1 + // [8] if((byte) main::c#1!=(byte) 0) goto main::@3 [ main::c#1 ] // xby_neq_0_then_la1 cpx #0 bne main__B3_from_B6 jmp main__B7 @@ -3357,7 +3647,7 @@ main__B10: jsr plot jmp main__B11 main__B11: - // if(true) goto main::@3 // true_then_la1 + // [11] if(true) goto main::@3 [ ] // true_then_la1 jmp main__B3_from_B11 jmp main__Breturn main__Breturn: @@ -3391,20 +3681,20 @@ plot__B2_from_B2: // (byte) plot::i#2 = (byte) plot::i#1 // register copy jmp plot__B2 plot__B2: - // (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 // aby=cowo1_staridx_xby + // [15] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 // ptr_zpptrby1_yby=aby + // [16] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] // ptr_zpptrby1_yby=aby sta (101),y - // (byte) plot::i#1 ← ++ (byte) plot::i#2 // xby=_inc_xby + // [17] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::i#1 plot::line#2 plot::x#2 plot::y#2 ] // xby=_inc_xby inx - // (byte) plot::x#1 ← ++ (byte) plot::x#2 // yby=_inc_yby + // [18] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby=_inc_yby iny - // if((byte) plot::x#1<(byte) 16) goto plot::@2 // yby_lt_coby1_then_la1 + // [19] if((byte) plot::x#1<(byte) 16) goto plot::@2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby_lt_coby1_then_la1 cpy #16 bcc plot__B2_from_B2 jmp plot__B3 plot__B3: - // (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 // zpptrby1=zpptrby1_plus_coby1 + // [20] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::i#1 plot::line#1 plot::y#2 ] // zpptrby1=zpptrby1_plus_coby1 lda 101 clc adc #40 @@ -3412,9 +3702,9 @@ plot__B3: bcc !+ inc 101+1 !: - // (byte) plot::y#1 ← -- (byte) plot::y#2 // zpby1=_dec_zpby1 + // [21] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1=_dec_zpby1 dec 100 - // if((byte) plot::y#1!=(byte) 0) goto plot::@1 // zpby1_neq_0_then_la1 + // [22] if((byte) plot::y#1!=(byte) 0) goto plot::@1 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1_neq_0_then_la1 lda 100 bne plot__B1_from_B3 jmp plot__Breturn @@ -3449,29 +3739,29 @@ flip__B2_from_B2: // (byte) flip::srcIdx#2 = (byte) flip::srcIdx#1 // register copy jmp flip__B2 flip__B2: - // (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 // aby=cowo1_staridx_xby + // [26] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 // ptr_cowo1_yby=aby + // [27] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] // ptr_cowo1_yby=aby sta 4352,y - // (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 // xby=_inc_xby + // [28] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::srcIdx#1 flip::dstIdx#3 flip::c#2 flip::r#2 ] // xby=_inc_xby inx - // (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 // yby=yby_plus_coby1 + // [29] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#2 flip::r#2 ] // yby=yby_plus_coby1 tya clc adc #16 tay - // (byte) flip::c#1 ← -- (byte) flip::c#2 // zpby1=_dec_zpby1 + // [30] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1=_dec_zpby1 dec 103 - // if((byte) flip::c#1!=(byte) 0) goto flip::@2 // zpby1_neq_0_then_la1 + // [31] if((byte) flip::c#1!=(byte) 0) goto flip::@2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1_neq_0_then_la1 lda 103 bne flip__B2_from_B2 jmp flip__B4 flip__B4: - // (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 // yby=_dec_yby + // [32] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#2 ] // yby=_dec_yby dey - // (byte) flip::r#1 ← -- (byte) flip::r#2 // zpby1=_dec_zpby1 + // [33] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1=_dec_zpby1 dec 104 - // if((byte) flip::r#1!=(byte) 0) goto flip::@1 // zpby1_neq_0_then_la1 + // [34] if((byte) flip::r#1!=(byte) 0) goto flip::@1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1_neq_0_then_la1 lda 104 bne flip__B1_from_B4 flip__B3_from_B4: @@ -3482,13 +3772,13 @@ flip__B3_from_B3: // (byte) flip::i#2 = (byte) flip::i#1 // register copy jmp flip__B3 flip__B3: - // (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 // aby=cowo1_staridx_xby + // [36] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ] // aby=cowo1_staridx_xby lda 4352,x - // *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 // ptr_cowo1_xby=aby + // [37] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ] // ptr_cowo1_xby=aby sta 4096,x - // (byte) flip::i#1 ← ++ (byte) flip::i#2 // xby=_inc_xby + // [38] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ] // xby=_inc_xby inx - // if((byte) flip::i#1!=(byte) 0) goto flip::@3 // xby_neq_0_then_la1 + // [39] if((byte) flip::i#1!=(byte) 0) goto flip::@3 [ flip::i#1 ] // xby_neq_0_then_la1 cpx #0 bne flip__B3_from_B3 jmp flip__Breturn @@ -3503,12 +3793,12 @@ prepare__B1_from_B1: // (byte) prepare::i#2 = (byte) prepare::i#1 // register copy jmp prepare__B1 prepare__B1: - // *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 // ptr_cowo1_xby=xby + // [42] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ] // ptr_cowo1_xby=xby txa sta 4096,x - // (byte) prepare::i#1 ← ++ (byte) prepare::i#2 // xby=_inc_xby + // [43] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ] // xby=_inc_xby inx - // if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 // xby_neq_0_then_la1 + // [44] if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 [ prepare::i#1 ] // xby_neq_0_then_la1 cpx #0 bne prepare__B1_from_B1 jmp prepare__Breturn @@ -3534,7 +3824,7 @@ Removing instruction jmp flip__B3 Removing instruction jmp flip__Breturn Removing instruction jmp prepare__B1 Removing instruction jmp prepare__Breturn -Succesful ASM optimization Pass4NextJumpElimination +Succesful ASM optimization Pass5NextJumpElimination ASSEMBLER BBEGIN: jsr main @@ -3554,21 +3844,21 @@ main__B3_from_B3: main__B3_from_B6: // (byte) main::c#2 = (byte) main::c#1 // register copy main__B3: - // (byte~) main::$1 ← * (word) 53266 // aby=_star_cowo1 + // [3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$1!=(byte) 254) goto main::@3 // aby_neq_coby1_then_la1 + // [4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #254 bne main__B3_from_B3 main__B4: - // (byte~) main::$3 ← * (word) 53266 // aby=_star_cowo1 + // [5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$3!=(byte) 255) goto main::@4 // aby_neq_coby1_then_la1 + // [6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #255 bne main__main__B4 main__B6: - // (byte) main::c#1 ← -- (byte) main::c#2 // xby=_dec_xby + // [7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ] // xby=_dec_xby dex - // if((byte) main::c#1!=(byte) 0) goto main::@3 // xby_neq_0_then_la1 + // [8] if((byte) main::c#1!=(byte) 0) goto main::@3 [ main::c#1 ] // xby_neq_0_then_la1 cpx #0 bne main__B3_from_B6 main__B7: @@ -3576,7 +3866,7 @@ main__B7: main__B10: jsr plot main__B11: - // if(true) goto main::@3 // true_then_la1 + // [11] if(true) goto main::@3 [ ] // true_then_la1 jmp main__B3_from_B11 main__Breturn: rts @@ -3607,19 +3897,19 @@ plot__B2_from_B2: // (byte) plot::x#2 = (byte) plot::x#1 // register copy // (byte) plot::i#2 = (byte) plot::i#1 // register copy plot__B2: - // (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 // aby=cowo1_staridx_xby + // [15] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 // ptr_zpptrby1_yby=aby + // [16] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] // ptr_zpptrby1_yby=aby sta (101),y - // (byte) plot::i#1 ← ++ (byte) plot::i#2 // xby=_inc_xby + // [17] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::i#1 plot::line#2 plot::x#2 plot::y#2 ] // xby=_inc_xby inx - // (byte) plot::x#1 ← ++ (byte) plot::x#2 // yby=_inc_yby + // [18] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby=_inc_yby iny - // if((byte) plot::x#1<(byte) 16) goto plot::@2 // yby_lt_coby1_then_la1 + // [19] if((byte) plot::x#1<(byte) 16) goto plot::@2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby_lt_coby1_then_la1 cpy #16 bcc plot__B2_from_B2 plot__B3: - // (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 // zpptrby1=zpptrby1_plus_coby1 + // [20] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::i#1 plot::line#1 plot::y#2 ] // zpptrby1=zpptrby1_plus_coby1 lda 101 clc adc #40 @@ -3627,9 +3917,9 @@ plot__B3: bcc !+ inc 101+1 !: - // (byte) plot::y#1 ← -- (byte) plot::y#2 // zpby1=_dec_zpby1 + // [21] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1=_dec_zpby1 dec 100 - // if((byte) plot::y#1!=(byte) 0) goto plot::@1 // zpby1_neq_0_then_la1 + // [22] if((byte) plot::y#1!=(byte) 0) goto plot::@1 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1_neq_0_then_la1 lda 100 bne plot__B1_from_B3 plot__Breturn: @@ -3661,28 +3951,28 @@ flip__B2_from_B2: // (byte) flip::dstIdx#3 = (byte) flip::dstIdx#1 // register copy // (byte) flip::srcIdx#2 = (byte) flip::srcIdx#1 // register copy flip__B2: - // (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 // aby=cowo1_staridx_xby + // [26] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 // ptr_cowo1_yby=aby + // [27] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] // ptr_cowo1_yby=aby sta 4352,y - // (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 // xby=_inc_xby + // [28] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::srcIdx#1 flip::dstIdx#3 flip::c#2 flip::r#2 ] // xby=_inc_xby inx - // (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 // yby=yby_plus_coby1 + // [29] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#2 flip::r#2 ] // yby=yby_plus_coby1 tya clc adc #16 tay - // (byte) flip::c#1 ← -- (byte) flip::c#2 // zpby1=_dec_zpby1 + // [30] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1=_dec_zpby1 dec 103 - // if((byte) flip::c#1!=(byte) 0) goto flip::@2 // zpby1_neq_0_then_la1 + // [31] if((byte) flip::c#1!=(byte) 0) goto flip::@2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1_neq_0_then_la1 lda 103 bne flip__B2_from_B2 flip__B4: - // (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 // yby=_dec_yby + // [32] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#2 ] // yby=_dec_yby dey - // (byte) flip::r#1 ← -- (byte) flip::r#2 // zpby1=_dec_zpby1 + // [33] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1=_dec_zpby1 dec 104 - // if((byte) flip::r#1!=(byte) 0) goto flip::@1 // zpby1_neq_0_then_la1 + // [34] if((byte) flip::r#1!=(byte) 0) goto flip::@1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1_neq_0_then_la1 lda 104 bne flip__B1_from_B4 flip__B3_from_B4: @@ -3692,13 +3982,13 @@ flip__B3_from_B4: flip__B3_from_B3: // (byte) flip::i#2 = (byte) flip::i#1 // register copy flip__B3: - // (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 // aby=cowo1_staridx_xby + // [36] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ] // aby=cowo1_staridx_xby lda 4352,x - // *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 // ptr_cowo1_xby=aby + // [37] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ] // ptr_cowo1_xby=aby sta 4096,x - // (byte) flip::i#1 ← ++ (byte) flip::i#2 // xby=_inc_xby + // [38] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ] // xby=_inc_xby inx - // if((byte) flip::i#1!=(byte) 0) goto flip::@3 // xby_neq_0_then_la1 + // [39] if((byte) flip::i#1!=(byte) 0) goto flip::@3 [ flip::i#1 ] // xby_neq_0_then_la1 cpx #0 bne flip__B3_from_B3 flip__Breturn: @@ -3711,12 +4001,12 @@ prepare__B1_from_prepare: prepare__B1_from_B1: // (byte) prepare::i#2 = (byte) prepare::i#1 // register copy prepare__B1: - // *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 // ptr_cowo1_xby=xby + // [42] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ] // ptr_cowo1_xby=xby txa sta 4096,x - // (byte) prepare::i#1 ← ++ (byte) prepare::i#2 // xby=_inc_xby + // [43] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ] // xby=_inc_xby inx - // if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 // xby_neq_0_then_la1 + // [44] if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 [ prepare::i#1 ] // xby_neq_0_then_la1 cpx #0 bne prepare__B1_from_B1 prepare__Breturn: @@ -3729,7 +4019,7 @@ Removing instruction jmp flip__B1 Removing instruction jmp flip__B2 Removing instruction jmp flip__B3 Removing instruction jmp prepare__B1 -Succesful ASM optimization Pass4NextJumpElimination +Succesful ASM optimization Pass5NextJumpElimination ASSEMBLER BBEGIN: jsr main @@ -3748,21 +4038,21 @@ main__B3_from_B3: main__B3_from_B6: // (byte) main::c#2 = (byte) main::c#1 // register copy main__B3: - // (byte~) main::$1 ← * (word) 53266 // aby=_star_cowo1 + // [3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$1!=(byte) 254) goto main::@3 // aby_neq_coby1_then_la1 + // [4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #254 bne main__B3_from_B3 main__B4: - // (byte~) main::$3 ← * (word) 53266 // aby=_star_cowo1 + // [5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$3!=(byte) 255) goto main::@4 // aby_neq_coby1_then_la1 + // [6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #255 bne main__main__B4 main__B6: - // (byte) main::c#1 ← -- (byte) main::c#2 // xby=_dec_xby + // [7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ] // xby=_dec_xby dex - // if((byte) main::c#1!=(byte) 0) goto main::@3 // xby_neq_0_then_la1 + // [8] if((byte) main::c#1!=(byte) 0) goto main::@3 [ main::c#1 ] // xby_neq_0_then_la1 cpx #0 bne main__B3_from_B6 main__B7: @@ -3770,7 +4060,7 @@ main__B7: main__B10: jsr plot main__B11: - // if(true) goto main::@3 // true_then_la1 + // [11] if(true) goto main::@3 [ ] // true_then_la1 jmp main__B3_from_B11 main__Breturn: rts @@ -3799,19 +4089,19 @@ plot__B2_from_B2: // (byte) plot::x#2 = (byte) plot::x#1 // register copy // (byte) plot::i#2 = (byte) plot::i#1 // register copy plot__B2: - // (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 // aby=cowo1_staridx_xby + // [15] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 // ptr_zpptrby1_yby=aby + // [16] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] // ptr_zpptrby1_yby=aby sta (101),y - // (byte) plot::i#1 ← ++ (byte) plot::i#2 // xby=_inc_xby + // [17] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::i#1 plot::line#2 plot::x#2 plot::y#2 ] // xby=_inc_xby inx - // (byte) plot::x#1 ← ++ (byte) plot::x#2 // yby=_inc_yby + // [18] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby=_inc_yby iny - // if((byte) plot::x#1<(byte) 16) goto plot::@2 // yby_lt_coby1_then_la1 + // [19] if((byte) plot::x#1<(byte) 16) goto plot::@2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby_lt_coby1_then_la1 cpy #16 bcc plot__B2_from_B2 plot__B3: - // (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 // zpptrby1=zpptrby1_plus_coby1 + // [20] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::i#1 plot::line#1 plot::y#2 ] // zpptrby1=zpptrby1_plus_coby1 lda 101 clc adc #40 @@ -3819,9 +4109,9 @@ plot__B3: bcc !+ inc 101+1 !: - // (byte) plot::y#1 ← -- (byte) plot::y#2 // zpby1=_dec_zpby1 + // [21] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1=_dec_zpby1 dec 100 - // if((byte) plot::y#1!=(byte) 0) goto plot::@1 // zpby1_neq_0_then_la1 + // [22] if((byte) plot::y#1!=(byte) 0) goto plot::@1 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1_neq_0_then_la1 lda 100 bne plot__B1_from_B3 plot__Breturn: @@ -3851,28 +4141,28 @@ flip__B2_from_B2: // (byte) flip::dstIdx#3 = (byte) flip::dstIdx#1 // register copy // (byte) flip::srcIdx#2 = (byte) flip::srcIdx#1 // register copy flip__B2: - // (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 // aby=cowo1_staridx_xby + // [26] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 // ptr_cowo1_yby=aby + // [27] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] // ptr_cowo1_yby=aby sta 4352,y - // (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 // xby=_inc_xby + // [28] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::srcIdx#1 flip::dstIdx#3 flip::c#2 flip::r#2 ] // xby=_inc_xby inx - // (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 // yby=yby_plus_coby1 + // [29] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#2 flip::r#2 ] // yby=yby_plus_coby1 tya clc adc #16 tay - // (byte) flip::c#1 ← -- (byte) flip::c#2 // zpby1=_dec_zpby1 + // [30] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1=_dec_zpby1 dec 103 - // if((byte) flip::c#1!=(byte) 0) goto flip::@2 // zpby1_neq_0_then_la1 + // [31] if((byte) flip::c#1!=(byte) 0) goto flip::@2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1_neq_0_then_la1 lda 103 bne flip__B2_from_B2 flip__B4: - // (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 // yby=_dec_yby + // [32] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#2 ] // yby=_dec_yby dey - // (byte) flip::r#1 ← -- (byte) flip::r#2 // zpby1=_dec_zpby1 + // [33] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1=_dec_zpby1 dec 104 - // if((byte) flip::r#1!=(byte) 0) goto flip::@1 // zpby1_neq_0_then_la1 + // [34] if((byte) flip::r#1!=(byte) 0) goto flip::@1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1_neq_0_then_la1 lda 104 bne flip__B1_from_B4 flip__B3_from_B4: @@ -3881,13 +4171,13 @@ flip__B3_from_B4: flip__B3_from_B3: // (byte) flip::i#2 = (byte) flip::i#1 // register copy flip__B3: - // (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 // aby=cowo1_staridx_xby + // [36] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ] // aby=cowo1_staridx_xby lda 4352,x - // *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 // ptr_cowo1_xby=aby + // [37] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ] // ptr_cowo1_xby=aby sta 4096,x - // (byte) flip::i#1 ← ++ (byte) flip::i#2 // xby=_inc_xby + // [38] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ] // xby=_inc_xby inx - // if((byte) flip::i#1!=(byte) 0) goto flip::@3 // xby_neq_0_then_la1 + // [39] if((byte) flip::i#1!=(byte) 0) goto flip::@3 [ flip::i#1 ] // xby_neq_0_then_la1 cpx #0 bne flip__B3_from_B3 flip__Breturn: @@ -3899,19 +4189,19 @@ prepare__B1_from_prepare: prepare__B1_from_B1: // (byte) prepare::i#2 = (byte) prepare::i#1 // register copy prepare__B1: - // *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 // ptr_cowo1_xby=xby + // [42] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ] // ptr_cowo1_xby=xby txa sta 4096,x - // (byte) prepare::i#1 ← ++ (byte) prepare::i#2 // xby=_inc_xby + // [43] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ] // xby=_inc_xby inx - // if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 // xby_neq_0_then_la1 + // [44] if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 [ prepare::i#1 ] // xby_neq_0_then_la1 cpx #0 bne prepare__B1_from_B1 prepare__Breturn: rts Removing instruction jmp main__B3 -Succesful ASM optimization Pass4NextJumpElimination +Succesful ASM optimization Pass5NextJumpElimination ASSEMBLER BBEGIN: jsr main @@ -3929,21 +4219,21 @@ main__B3_from_B3: main__B3_from_B6: // (byte) main::c#2 = (byte) main::c#1 // register copy main__B3: - // (byte~) main::$1 ← * (word) 53266 // aby=_star_cowo1 + // [3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$1!=(byte) 254) goto main::@3 // aby_neq_coby1_then_la1 + // [4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #254 bne main__B3_from_B3 main__B4: - // (byte~) main::$3 ← * (word) 53266 // aby=_star_cowo1 + // [5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$3!=(byte) 255) goto main::@4 // aby_neq_coby1_then_la1 + // [6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #255 bne main__main__B4 main__B6: - // (byte) main::c#1 ← -- (byte) main::c#2 // xby=_dec_xby + // [7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ] // xby=_dec_xby dex - // if((byte) main::c#1!=(byte) 0) goto main::@3 // xby_neq_0_then_la1 + // [8] if((byte) main::c#1!=(byte) 0) goto main::@3 [ main::c#1 ] // xby_neq_0_then_la1 cpx #0 bne main__B3_from_B6 main__B7: @@ -3951,7 +4241,7 @@ main__B7: main__B10: jsr plot main__B11: - // if(true) goto main::@3 // true_then_la1 + // [11] if(true) goto main::@3 [ ] // true_then_la1 jmp main__B3_from_B11 main__Breturn: rts @@ -3980,19 +4270,19 @@ plot__B2_from_B2: // (byte) plot::x#2 = (byte) plot::x#1 // register copy // (byte) plot::i#2 = (byte) plot::i#1 // register copy plot__B2: - // (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 // aby=cowo1_staridx_xby + // [15] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 // ptr_zpptrby1_yby=aby + // [16] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] // ptr_zpptrby1_yby=aby sta (101),y - // (byte) plot::i#1 ← ++ (byte) plot::i#2 // xby=_inc_xby + // [17] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::i#1 plot::line#2 plot::x#2 plot::y#2 ] // xby=_inc_xby inx - // (byte) plot::x#1 ← ++ (byte) plot::x#2 // yby=_inc_yby + // [18] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby=_inc_yby iny - // if((byte) plot::x#1<(byte) 16) goto plot::@2 // yby_lt_coby1_then_la1 + // [19] if((byte) plot::x#1<(byte) 16) goto plot::@2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby_lt_coby1_then_la1 cpy #16 bcc plot__B2_from_B2 plot__B3: - // (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 // zpptrby1=zpptrby1_plus_coby1 + // [20] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::i#1 plot::line#1 plot::y#2 ] // zpptrby1=zpptrby1_plus_coby1 lda 101 clc adc #40 @@ -4000,9 +4290,9 @@ plot__B3: bcc !+ inc 101+1 !: - // (byte) plot::y#1 ← -- (byte) plot::y#2 // zpby1=_dec_zpby1 + // [21] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1=_dec_zpby1 dec 100 - // if((byte) plot::y#1!=(byte) 0) goto plot::@1 // zpby1_neq_0_then_la1 + // [22] if((byte) plot::y#1!=(byte) 0) goto plot::@1 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1_neq_0_then_la1 lda 100 bne plot__B1_from_B3 plot__Breturn: @@ -4032,28 +4322,28 @@ flip__B2_from_B2: // (byte) flip::dstIdx#3 = (byte) flip::dstIdx#1 // register copy // (byte) flip::srcIdx#2 = (byte) flip::srcIdx#1 // register copy flip__B2: - // (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 // aby=cowo1_staridx_xby + // [26] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 // ptr_cowo1_yby=aby + // [27] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] // ptr_cowo1_yby=aby sta 4352,y - // (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 // xby=_inc_xby + // [28] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::srcIdx#1 flip::dstIdx#3 flip::c#2 flip::r#2 ] // xby=_inc_xby inx - // (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 // yby=yby_plus_coby1 + // [29] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#2 flip::r#2 ] // yby=yby_plus_coby1 tya clc adc #16 tay - // (byte) flip::c#1 ← -- (byte) flip::c#2 // zpby1=_dec_zpby1 + // [30] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1=_dec_zpby1 dec 103 - // if((byte) flip::c#1!=(byte) 0) goto flip::@2 // zpby1_neq_0_then_la1 + // [31] if((byte) flip::c#1!=(byte) 0) goto flip::@2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1_neq_0_then_la1 lda 103 bne flip__B2_from_B2 flip__B4: - // (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 // yby=_dec_yby + // [32] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#2 ] // yby=_dec_yby dey - // (byte) flip::r#1 ← -- (byte) flip::r#2 // zpby1=_dec_zpby1 + // [33] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1=_dec_zpby1 dec 104 - // if((byte) flip::r#1!=(byte) 0) goto flip::@1 // zpby1_neq_0_then_la1 + // [34] if((byte) flip::r#1!=(byte) 0) goto flip::@1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1_neq_0_then_la1 lda 104 bne flip__B1_from_B4 flip__B3_from_B4: @@ -4062,13 +4352,13 @@ flip__B3_from_B4: flip__B3_from_B3: // (byte) flip::i#2 = (byte) flip::i#1 // register copy flip__B3: - // (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 // aby=cowo1_staridx_xby + // [36] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ] // aby=cowo1_staridx_xby lda 4352,x - // *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 // ptr_cowo1_xby=aby + // [37] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ] // ptr_cowo1_xby=aby sta 4096,x - // (byte) flip::i#1 ← ++ (byte) flip::i#2 // xby=_inc_xby + // [38] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ] // xby=_inc_xby inx - // if((byte) flip::i#1!=(byte) 0) goto flip::@3 // xby_neq_0_then_la1 + // [39] if((byte) flip::i#1!=(byte) 0) goto flip::@3 [ flip::i#1 ] // xby_neq_0_then_la1 cpx #0 bne flip__B3_from_B3 flip__Breturn: @@ -4080,12 +4370,12 @@ prepare__B1_from_prepare: prepare__B1_from_B1: // (byte) prepare::i#2 = (byte) prepare::i#1 // register copy prepare__B1: - // *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 // ptr_cowo1_xby=xby + // [42] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ] // ptr_cowo1_xby=xby txa sta 4096,x - // (byte) prepare::i#1 ← ++ (byte) prepare::i#2 // xby=_inc_xby + // [43] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ] // xby=_inc_xby inx - // if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 // xby_neq_0_then_la1 + // [44] if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 [ prepare::i#1 ] // xby_neq_0_then_la1 cpx #0 bne prepare__B1_from_B1 prepare__Breturn: @@ -4184,21 +4474,21 @@ main__B3_from_B3: main__B3_from_B6: // (byte) main::c#2 = (byte) main::c#1 // register copy main__B3: - // (byte~) main::$1 ← * (word) 53266 // aby=_star_cowo1 + // [3] (byte~) main::$1 ← * (word) 53266 [ main::$1 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$1!=(byte) 254) goto main::@3 // aby_neq_coby1_then_la1 + // [4] if((byte~) main::$1!=(byte) 254) goto main::@3 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #254 bne main__B3_from_B3 main__B4: - // (byte~) main::$3 ← * (word) 53266 // aby=_star_cowo1 + // [5] (byte~) main::$3 ← * (word) 53266 [ main::$3 main::c#2 ] // aby=_star_cowo1 lda 53266 - // if((byte~) main::$3!=(byte) 255) goto main::@4 // aby_neq_coby1_then_la1 + // [6] if((byte~) main::$3!=(byte) 255) goto main::@4 [ main::c#2 ] // aby_neq_coby1_then_la1 cmp #255 bne main__main__B4 main__B6: - // (byte) main::c#1 ← -- (byte) main::c#2 // xby=_dec_xby + // [7] (byte) main::c#1 ← -- (byte) main::c#2 [ main::c#1 ] // xby=_dec_xby dex - // if((byte) main::c#1!=(byte) 0) goto main::@3 // xby_neq_0_then_la1 + // [8] if((byte) main::c#1!=(byte) 0) goto main::@3 [ main::c#1 ] // xby_neq_0_then_la1 cpx #0 bne main__B3_from_B6 main__B7: @@ -4206,7 +4496,7 @@ main__B7: main__B10: jsr plot main__B11: - // if(true) goto main::@3 // true_then_la1 + // [11] if(true) goto main::@3 [ ] // true_then_la1 jmp main__B3_from_B11 main__Breturn: rts @@ -4235,19 +4525,19 @@ plot__B2_from_B2: // (byte) plot::x#2 = (byte) plot::x#1 // register copy // (byte) plot::i#2 = (byte) plot::i#1 // register copy plot__B2: - // (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 // aby=cowo1_staridx_xby + // [15] (byte~) plot::$3 ← (word) 4096 *idx (byte) plot::i#2 [ plot::i#2 plot::line#2 plot::x#2 plot::$3 plot::y#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 // ptr_zpptrby1_yby=aby + // [16] *((byte*) plot::line#2 + (byte) plot::x#2) ← (byte~) plot::$3 [ plot::i#2 plot::line#2 plot::x#2 plot::y#2 ] // ptr_zpptrby1_yby=aby sta (101),y - // (byte) plot::i#1 ← ++ (byte) plot::i#2 // xby=_inc_xby + // [17] (byte) plot::i#1 ← ++ (byte) plot::i#2 [ plot::i#1 plot::line#2 plot::x#2 plot::y#2 ] // xby=_inc_xby inx - // (byte) plot::x#1 ← ++ (byte) plot::x#2 // yby=_inc_yby + // [18] (byte) plot::x#1 ← ++ (byte) plot::x#2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby=_inc_yby iny - // if((byte) plot::x#1<(byte) 16) goto plot::@2 // yby_lt_coby1_then_la1 + // [19] if((byte) plot::x#1<(byte) 16) goto plot::@2 [ plot::i#1 plot::x#1 plot::line#2 plot::y#2 ] // yby_lt_coby1_then_la1 cpy #16 bcc plot__B2_from_B2 plot__B3: - // (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 // zpptrby1=zpptrby1_plus_coby1 + // [20] (byte*) plot::line#1 ← (byte*) plot::line#2 + (byte) 40 [ plot::i#1 plot::line#1 plot::y#2 ] // zpptrby1=zpptrby1_plus_coby1 lda 101 clc adc #40 @@ -4255,9 +4545,9 @@ plot__B3: bcc !+ inc 101+1 !: - // (byte) plot::y#1 ← -- (byte) plot::y#2 // zpby1=_dec_zpby1 + // [21] (byte) plot::y#1 ← -- (byte) plot::y#2 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1=_dec_zpby1 dec 100 - // if((byte) plot::y#1!=(byte) 0) goto plot::@1 // zpby1_neq_0_then_la1 + // [22] if((byte) plot::y#1!=(byte) 0) goto plot::@1 [ plot::i#1 plot::line#1 plot::y#1 ] // zpby1_neq_0_then_la1 lda 100 bne plot__B1_from_B3 plot__Breturn: @@ -4287,28 +4577,28 @@ flip__B2_from_B2: // (byte) flip::dstIdx#3 = (byte) flip::dstIdx#1 // register copy // (byte) flip::srcIdx#2 = (byte) flip::srcIdx#1 // register copy flip__B2: - // (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 // aby=cowo1_staridx_xby + // [26] (byte~) flip::$0 ← (word) 4096 *idx (byte) flip::srcIdx#2 [ flip::srcIdx#2 flip::dstIdx#3 flip::$0 flip::c#2 flip::r#2 ] // aby=cowo1_staridx_xby lda 4096,x - // *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 // ptr_cowo1_yby=aby + // [27] *((word) 4352 + (byte) flip::dstIdx#3) ← (byte~) flip::$0 [ flip::srcIdx#2 flip::dstIdx#3 flip::c#2 flip::r#2 ] // ptr_cowo1_yby=aby sta 4352,y - // (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 // xby=_inc_xby + // [28] (byte) flip::srcIdx#1 ← ++ (byte) flip::srcIdx#2 [ flip::srcIdx#1 flip::dstIdx#3 flip::c#2 flip::r#2 ] // xby=_inc_xby inx - // (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 // yby=yby_plus_coby1 + // [29] (byte) flip::dstIdx#1 ← (byte) flip::dstIdx#3 + (byte) 16 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#2 flip::r#2 ] // yby=yby_plus_coby1 tya clc adc #16 tay - // (byte) flip::c#1 ← -- (byte) flip::c#2 // zpby1=_dec_zpby1 + // [30] (byte) flip::c#1 ← -- (byte) flip::c#2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1=_dec_zpby1 dec 103 - // if((byte) flip::c#1!=(byte) 0) goto flip::@2 // zpby1_neq_0_then_la1 + // [31] if((byte) flip::c#1!=(byte) 0) goto flip::@2 [ flip::srcIdx#1 flip::dstIdx#1 flip::c#1 flip::r#2 ] // zpby1_neq_0_then_la1 lda 103 bne flip__B2_from_B2 flip__B4: - // (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 // yby=_dec_yby + // [32] (byte) flip::dstIdx#2 ← -- (byte) flip::dstIdx#1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#2 ] // yby=_dec_yby dey - // (byte) flip::r#1 ← -- (byte) flip::r#2 // zpby1=_dec_zpby1 + // [33] (byte) flip::r#1 ← -- (byte) flip::r#2 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1=_dec_zpby1 dec 104 - // if((byte) flip::r#1!=(byte) 0) goto flip::@1 // zpby1_neq_0_then_la1 + // [34] if((byte) flip::r#1!=(byte) 0) goto flip::@1 [ flip::srcIdx#1 flip::dstIdx#2 flip::r#1 ] // zpby1_neq_0_then_la1 lda 104 bne flip__B1_from_B4 flip__B3_from_B4: @@ -4317,13 +4607,13 @@ flip__B3_from_B4: flip__B3_from_B3: // (byte) flip::i#2 = (byte) flip::i#1 // register copy flip__B3: - // (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 // aby=cowo1_staridx_xby + // [36] (byte~) flip::$4 ← (word) 4352 *idx (byte) flip::i#2 [ flip::i#2 flip::$4 ] // aby=cowo1_staridx_xby lda 4352,x - // *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 // ptr_cowo1_xby=aby + // [37] *((word) 4096 + (byte) flip::i#2) ← (byte~) flip::$4 [ flip::i#2 ] // ptr_cowo1_xby=aby sta 4096,x - // (byte) flip::i#1 ← ++ (byte) flip::i#2 // xby=_inc_xby + // [38] (byte) flip::i#1 ← ++ (byte) flip::i#2 [ flip::i#1 ] // xby=_inc_xby inx - // if((byte) flip::i#1!=(byte) 0) goto flip::@3 // xby_neq_0_then_la1 + // [39] if((byte) flip::i#1!=(byte) 0) goto flip::@3 [ flip::i#1 ] // xby_neq_0_then_la1 cpx #0 bne flip__B3_from_B3 flip__Breturn: @@ -4335,12 +4625,12 @@ prepare__B1_from_prepare: prepare__B1_from_B1: // (byte) prepare::i#2 = (byte) prepare::i#1 // register copy prepare__B1: - // *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 // ptr_cowo1_xby=xby + // [42] *((word) 4096 + (byte) prepare::i#2) ← (byte) prepare::i#2 [ prepare::i#2 ] // ptr_cowo1_xby=xby txa sta 4096,x - // (byte) prepare::i#1 ← ++ (byte) prepare::i#2 // xby=_inc_xby + // [43] (byte) prepare::i#1 ← ++ (byte) prepare::i#2 [ prepare::i#1 ] // xby=_inc_xby inx - // if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 // xby_neq_0_then_la1 + // [44] if((byte) prepare::i#1!=(byte) 0) goto prepare::@1 [ prepare::i#1 ] // xby_neq_0_then_la1 cpx #0 bne prepare__B1_from_B1 prepare__Breturn: diff --git a/src/dk/camelot64/kickc/test/ref/loopmin.cfg b/src/dk/camelot64/kickc/test/ref/loopmin.cfg index 9bafd3893..b779acca0 100644 --- a/src/dk/camelot64/kickc/test/ref/loopmin.cfg +++ b/src/dk/camelot64/kickc/test/ref/loopmin.cfg @@ -1,16 +1,16 @@ @BEGIN: from to:@1 @1: from @3 @BEGIN - (byte) s#2 ← phi( @3/(byte) s#4 @BEGIN/(byte) 0 ) - (byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 ) - if((byte) i#2>(byte) 5) goto @2 - to:@3 -@2: from @1 - (byte) s#1 ← (byte) s#2 + (byte) i#2 + [0] (byte) s#2 ← phi( @3/(byte) s#4 @BEGIN/(byte) 0 ) [ i#2 s#2 ] + [0] (byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 ) [ i#2 s#2 ] + [1] if((byte) i#2>(byte) 5) goto @2 [ i#2 s#2 ] to:@3 @3: from @1 @2 - (byte) s#4 ← phi( @1/(byte) s#2 @2/(byte) s#1 ) - (byte) i#1 ← -- (byte) i#2 - if((byte) i#1>(byte) 0) goto @1 + [2] (byte) s#4 ← phi( @1/(byte) s#2 @2/(byte) s#1 ) [ s#4 i#2 ] + [3] (byte) i#1 ← -- (byte) i#2 [ i#1 s#4 ] + [4] if((byte) i#1>(byte) 0) goto @1 [ i#1 s#4 ] to:@END @END: from @3 +@2: from @1 + [5] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ] + to:@3 diff --git a/src/dk/camelot64/kickc/test/ref/loopmin.log b/src/dk/camelot64/kickc/test/ref/loopmin.log index f5ca4c72a..91d370a10 100644 --- a/src/dk/camelot64/kickc/test/ref/loopmin.log +++ b/src/dk/camelot64/kickc/test/ref/loopmin.log @@ -251,6 +251,60 @@ CONTROL FLOW GRAPH to:@END @END: from @3 +Block Sequence Planned @BEGIN @1 @3 @END @2 +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + to:@1 +@1: from @3 @BEGIN + (byte) s#2 ← phi( @3/(byte) s#4 @BEGIN/(byte) 0 ) + (byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 ) + if((byte) i#2>(byte) 5) goto @2 + to:@3 +@3: from @1 @2 + (byte) s#4 ← phi( @1/(byte) s#2 @2/(byte) s#1 ) + (byte) i#1 ← -- (byte) i#2 + if((byte) i#1>(byte) 0) goto @1 + to:@END +@END: from @3 +@2: from @1 + (byte) s#1 ← (byte) s#2 + (byte) i#2 + to:@3 + +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + to:@1 +@1: from @3 @BEGIN + [0] (byte) s#2 ← phi( @3/(byte) s#4 @BEGIN/(byte) 0 ) [ i#2 s#2 ] + [0] (byte) i#2 ← phi( @3/(byte) i#1 @BEGIN/(byte) 10 ) [ i#2 s#2 ] + [1] if((byte) i#2>(byte) 5) goto @2 [ i#2 s#2 ] + to:@3 +@3: from @1 @2 + [2] (byte) s#4 ← phi( @1/(byte) s#2 @2/(byte) s#1 ) [ s#4 i#2 ] + [3] (byte) i#1 ← -- (byte) i#2 [ i#1 s#4 ] + [4] if((byte) i#1>(byte) 0) goto @1 [ i#1 s#4 ] + to:@END +@END: from @3 +@2: from @1 + [5] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ] + to:@3 + +SYMBOLS - LIVE RANGES +(label) @1 +(label) @2 +(label) @3 +(label) @BEGIN +(label) @END +(byte) i +(byte) i#1 +(byte) i#2 +(byte) s +(byte) s#1 +(byte) s#2 +(byte) s#4 + INITIAL ASM BBEGIN: B1_from_BBEGIN: @@ -270,7 +324,7 @@ B1_from_B3: sta 4 jmp B1 B1: - // if((byte) i#2>(byte) 5) goto @2 // zpby1_gt_coby1_then_la1 + // [1] if((byte) i#2>(byte) 5) goto @2 [ i#2 s#2 ] // zpby1_gt_coby1_then_la1 lda 4 cmp #5 beq !+ @@ -282,17 +336,17 @@ B3_from_B1: sta 6 jmp B3 B3: - // (byte) i#1 ← -- (byte) i#2 // zpby1=_dec_zpby2 + // [3] (byte) i#1 ← -- (byte) i#2 [ i#1 s#4 ] // zpby1=_dec_zpby2 lda 4 sta 3 dec 3 - // if((byte) i#1>(byte) 0) goto @1 // zpby1_gt_0_then_la1 + // [4] if((byte) i#1>(byte) 0) goto @1 [ i#1 s#4 ] // zpby1_gt_0_then_la1 lda 3 bne B1_from_B3 jmp BEND BEND: B2: - // (byte) s#1 ← (byte) s#2 + (byte) i#2 // zpby1=zpby2_plus_zpby3 + // [5] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ] // zpby1=zpby2_plus_zpby3 lda 5 clc adc 4 @@ -306,7 +360,7 @@ B3_from_B2: Removing instruction jmp B1 Removing instruction jmp B3 Removing instruction jmp BEND -Succesful ASM optimization Pass4NextJumpElimination +Succesful ASM optimization Pass5NextJumpElimination ASSEMBLER BBEGIN: B1_from_BBEGIN: @@ -325,7 +379,7 @@ B1_from_B3: lda 3 sta 4 B1: - // if((byte) i#2>(byte) 5) goto @2 // zpby1_gt_coby1_then_la1 + // [1] if((byte) i#2>(byte) 5) goto @2 [ i#2 s#2 ] // zpby1_gt_coby1_then_la1 lda 4 cmp #5 beq !+ @@ -336,16 +390,16 @@ B3_from_B1: lda 5 sta 6 B3: - // (byte) i#1 ← -- (byte) i#2 // zpby1=_dec_zpby2 + // [3] (byte) i#1 ← -- (byte) i#2 [ i#1 s#4 ] // zpby1=_dec_zpby2 lda 4 sta 3 dec 3 - // if((byte) i#1>(byte) 0) goto @1 // zpby1_gt_0_then_la1 + // [4] if((byte) i#1>(byte) 0) goto @1 [ i#1 s#4 ] // zpby1_gt_0_then_la1 lda 3 bne B1_from_B3 BEND: B2: - // (byte) s#1 ← (byte) s#2 + (byte) i#2 // zpby1=zpby2_plus_zpby3 + // [5] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ] // zpby1=zpby2_plus_zpby3 lda 5 clc adc 4 @@ -388,7 +442,7 @@ B1_from_B3: lda 3 sta 4 B1: - // if((byte) i#2>(byte) 5) goto @2 // zpby1_gt_coby1_then_la1 + // [1] if((byte) i#2>(byte) 5) goto @2 [ i#2 s#2 ] // zpby1_gt_coby1_then_la1 lda 4 cmp #5 beq !+ @@ -399,16 +453,16 @@ B3_from_B1: lda 5 sta 6 B3: - // (byte) i#1 ← -- (byte) i#2 // zpby1=_dec_zpby2 + // [3] (byte) i#1 ← -- (byte) i#2 [ i#1 s#4 ] // zpby1=_dec_zpby2 lda 4 sta 3 dec 3 - // if((byte) i#1>(byte) 0) goto @1 // zpby1_gt_0_then_la1 + // [4] if((byte) i#1>(byte) 0) goto @1 [ i#1 s#4 ] // zpby1_gt_0_then_la1 lda 3 bne B1_from_B3 BEND: B2: - // (byte) s#1 ← (byte) s#2 + (byte) i#2 // zpby1=zpby2_plus_zpby3 + // [5] (byte) s#1 ← (byte) s#2 + (byte) i#2 [ i#2 s#1 ] // zpby1=zpby2_plus_zpby3 lda 5 clc adc 4 diff --git a/src/dk/camelot64/kickc/test/ref/minus.cfg b/src/dk/camelot64/kickc/test/ref/minus.cfg index d9093fdd5..5fe9d1bf2 100644 --- a/src/dk/camelot64/kickc/test/ref/minus.cfg +++ b/src/dk/camelot64/kickc/test/ref/minus.cfg @@ -1,11 +1,11 @@ @BEGIN: from to:@1 @1: from @1 @BEGIN - (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) - (byte~) $0 ← (byte) 2 + (byte) i#2 - (byte~) $1 ← (byte~) $0 + (byte) 2 - *((word) 4352 + (byte) i#2) ← (byte~) $1 - (byte) i#1 ← (byte) i#2 + (byte) 1 - if((byte) i#1<(byte) 10) goto @1 + [0] (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) [ i#2 ] + [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] + [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] + [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] + [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] to:@END @END: from @1 diff --git a/src/dk/camelot64/kickc/test/ref/minus.log b/src/dk/camelot64/kickc/test/ref/minus.log index 9eec356ba..1dfcdd912 100644 --- a/src/dk/camelot64/kickc/test/ref/minus.log +++ b/src/dk/camelot64/kickc/test/ref/minus.log @@ -206,6 +206,46 @@ Multiple usages for variable. Not optimizing sub-constant (byte) i#2 Multiple usages for variable. Not optimizing sub-constant (byte) i#2 Multiple usages for variable. Not optimizing sub-constant (byte) i#2 Multiple usages for variable. Not optimizing sub-constant (byte) i#2 +Block Sequence Planned @BEGIN @1 @END +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + to:@1 +@1: from @1 @BEGIN + (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) + (byte~) $0 ← (byte) 2 + (byte) i#2 + (byte~) $1 ← (byte~) $0 + (byte) 2 + *((word) 4352 + (byte) i#2) ← (byte~) $1 + (byte) i#1 ← (byte) i#2 + (byte) 1 + if((byte) i#1<(byte) 10) goto @1 + to:@END +@END: from @1 + +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + to:@1 +@1: from @1 @BEGIN + [0] (byte) i#2 ← phi( @1/(byte) i#1 @BEGIN/(byte) 5 ) [ i#2 ] + [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] + [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] + [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] + [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] + [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] + to:@END +@END: from @1 + +SYMBOLS - LIVE RANGES +(byte~) $0 +(byte~) $1 +(label) @1 +(label) @BEGIN +(label) @END +(byte) i +(byte) i#1 +(byte) i#2 +(byte[16]) p + INITIAL ASM BBEGIN: B1_from_BBEGIN: @@ -219,26 +259,26 @@ B1_from_B1: sta 5 jmp B1 B1: - // (byte~) $0 ← (byte) 2 + (byte) i#2 // zpby1=coby1_plus_zpby2 + // [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] // zpby1=coby1_plus_zpby2 lda #2 clc adc 5 sta 2 - // (byte~) $1 ← (byte~) $0 + (byte) 2 // zpby1=zpby2_plus_coby1 + // [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] // zpby1=zpby2_plus_coby1 lda 2 clc adc #2 sta 3 - // *((word) 4352 + (byte) i#2) ← (byte~) $1 // ptr_cowo1_zpby1=zpby2 + // [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 lda 3 ldy 5 sta 4352,y - // (byte) i#1 ← (byte) i#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby2_plus_1 lda 5 clc adc #1 sta 4 - // if((byte) i#1<(byte) 10) goto @1 // zpby1_lt_coby1_then_la1 + // [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 lda 4 cmp #10 bcc B1_from_B1 @@ -247,7 +287,7 @@ BEND: Removing instruction jmp B1 Removing instruction jmp BEND -Succesful ASM optimization Pass4NextJumpElimination +Succesful ASM optimization Pass5NextJumpElimination ASSEMBLER BBEGIN: B1_from_BBEGIN: @@ -260,26 +300,26 @@ B1_from_B1: lda 4 sta 5 B1: - // (byte~) $0 ← (byte) 2 + (byte) i#2 // zpby1=coby1_plus_zpby2 + // [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] // zpby1=coby1_plus_zpby2 lda #2 clc adc 5 sta 2 - // (byte~) $1 ← (byte~) $0 + (byte) 2 // zpby1=zpby2_plus_coby1 + // [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] // zpby1=zpby2_plus_coby1 lda 2 clc adc #2 sta 3 - // *((word) 4352 + (byte) i#2) ← (byte~) $1 // ptr_cowo1_zpby1=zpby2 + // [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 lda 3 ldy 5 sta 4352,y - // (byte) i#1 ← (byte) i#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby2_plus_1 lda 5 clc adc #1 sta 4 - // if((byte) i#1<(byte) 10) goto @1 // zpby1_lt_coby1_then_la1 + // [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 lda 4 cmp #10 bcc B1_from_B1 @@ -308,26 +348,26 @@ B1_from_B1: lda 4 sta 5 B1: - // (byte~) $0 ← (byte) 2 + (byte) i#2 // zpby1=coby1_plus_zpby2 + // [1] (byte~) $0 ← (byte) 2 + (byte) i#2 [ i#2 $0 ] // zpby1=coby1_plus_zpby2 lda #2 clc adc 5 sta 2 - // (byte~) $1 ← (byte~) $0 + (byte) 2 // zpby1=zpby2_plus_coby1 + // [2] (byte~) $1 ← (byte~) $0 + (byte) 2 [ i#2 $1 ] // zpby1=zpby2_plus_coby1 lda 2 clc adc #2 sta 3 - // *((word) 4352 + (byte) i#2) ← (byte~) $1 // ptr_cowo1_zpby1=zpby2 + // [3] *((word) 4352 + (byte) i#2) ← (byte~) $1 [ i#2 ] // ptr_cowo1_zpby1=zpby2 lda 3 ldy 5 sta 4352,y - // (byte) i#1 ← (byte) i#2 + (byte) 1 // zpby1=zpby2_plus_1 + // [4] (byte) i#1 ← (byte) i#2 + (byte) 1 [ i#1 ] // zpby1=zpby2_plus_1 lda 5 clc adc #1 sta 4 - // if((byte) i#1<(byte) 10) goto @1 // zpby1_lt_coby1_then_la1 + // [5] if((byte) i#1<(byte) 10) goto @1 [ i#1 ] // zpby1_lt_coby1_then_la1 lda 4 cmp #10 bcc B1_from_B1 diff --git a/src/dk/camelot64/kickc/test/ref/summin.cfg b/src/dk/camelot64/kickc/test/ref/summin.cfg index e5cbd8300..9ef1b4012 100644 --- a/src/dk/camelot64/kickc/test/ref/summin.cfg +++ b/src/dk/camelot64/kickc/test/ref/summin.cfg @@ -1,15 +1,15 @@ @BEGIN: from - call sum param-assignment + [0] call sum param-assignment [ ] to:@2 @2: from @BEGIN - call sum param-assignment + [1] call sum param-assignment [ ] to:@END +@END: from @2 sum: from @2 @BEGIN - (byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 ) - (byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 ) - (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 + [2] (byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 ) [ sum::a#2 sum::b#2 ] + [2] (byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 ) [ sum::a#2 sum::b#2 ] + [3] (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 [ s1#0 ] to:sum::@return sum::@return: from sum - return (byte) s1#0 + [4] return (byte) s1#0 [ ] to:@RETURN -@END: from @2 diff --git a/src/dk/camelot64/kickc/test/ref/summin.log b/src/dk/camelot64/kickc/test/ref/summin.log index e42dc8d9a..e74dad11d 100644 --- a/src/dk/camelot64/kickc/test/ref/summin.log +++ b/src/dk/camelot64/kickc/test/ref/summin.log @@ -240,6 +240,58 @@ sum::@return: from sum to:@RETURN @END: from @2 +Block Sequence Planned @BEGIN @2 @END sum sum::@return +CONTROL FLOW GRAPH - PHI LIFTED +@BEGIN: from + call sum param-assignment + to:@2 +@2: from @BEGIN + call sum param-assignment + to:@END +@END: from @2 +sum: from @2 @BEGIN + (byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 ) + (byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 ) + (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 + to:sum::@return +sum::@return: from sum + return (byte) s1#0 + to:@RETURN + +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES +@BEGIN: from + [0] call sum param-assignment [ ] + to:@2 +@2: from @BEGIN + [1] call sum param-assignment [ ] + to:@END +@END: from @2 +sum: from @2 @BEGIN + [2] (byte) sum::b#2 ← phi( @2/(byte) 13 @BEGIN/(byte) 2 ) [ sum::a#2 sum::b#2 ] + [2] (byte) sum::a#2 ← phi( @2/(byte) 9 @BEGIN/(byte) 1 ) [ sum::a#2 sum::b#2 ] + [3] (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 [ s1#0 ] + to:sum::@return +sum::@return: from sum + [4] return (byte) s1#0 [ ] + to:@RETURN + +SYMBOLS - LIVE RANGES +(label) @2 +(label) @BEGIN +(label) @END +(byte) s1 +(byte) s1#0 +(byte) s2 +(byte()) sum((byte) sum::a , (byte) sum::b) +(label) sum::@return +(byte) sum::a +(byte) sum::a#2 +(byte) sum::b +(byte) sum::b#2 +(byte) sum::return + + INITIAL ASM BBEGIN: sum_from_BBEGIN: @@ -263,7 +315,7 @@ sum_from_B2: jmp BEND BEND: sum: - // (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 // zpby1=zpby2_plus_zpby3 + // [3] (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 [ s1#0 ] // zpby1=zpby2_plus_zpby3 lda 2 clc adc 3 @@ -275,7 +327,7 @@ sum__Breturn: Removing instruction jmp B2 Removing instruction jmp BEND Removing instruction jmp sum__Breturn -Succesful ASM optimization Pass4NextJumpElimination +Succesful ASM optimization Pass5NextJumpElimination ASSEMBLER BBEGIN: sum_from_BBEGIN: @@ -297,7 +349,7 @@ sum_from_B2: jsr sum BEND: sum: - // (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 // zpby1=zpby2_plus_zpby3 + // [3] (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 [ s1#0 ] // zpby1=zpby2_plus_zpby3 lda 2 clc adc 3 @@ -342,7 +394,7 @@ sum_from_B2: jsr sum BEND: sum: - // (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 // zpby1=zpby2_plus_zpby3 + // [3] (byte) s1#0 ← (byte) sum::a#2 + (byte) sum::b#2 [ s1#0 ] // zpby1=zpby2_plus_zpby3 lda 2 clc adc 3