diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java index b0244bd76..125842986 100644 --- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java +++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java @@ -1,7 +1,6 @@ package dk.camelot64.kickc.model; import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementInfos; import dk.camelot64.kickc.model.statements.StatementPhiBlock; import dk.camelot64.kickc.model.symbols.Label; import dk.camelot64.kickc.model.symbols.Procedure; diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphBaseVisitor.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphBaseVisitor.java index b01d4090c..bf58c9ba0 100644 --- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphBaseVisitor.java +++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphBaseVisitor.java @@ -53,6 +53,8 @@ public class ControlFlowGraphBaseVisitor { return visitAsm((StatementAsm) statement); } else if(statement instanceof StatementKickAsm) { return visitKickAsm((StatementKickAsm) statement); + } else if(statement instanceof StatementStackPull) { + return visitStackPull((StatementStackPull) statement); } else { throw new RuntimeException("Unhandled statement type " + statement); } @@ -117,4 +119,8 @@ public class ControlFlowGraphBaseVisitor { public T visitKickAsm(StatementKickAsm asm) { return null; } + + public T visitStackPull(StatementStackPull stackPull) { + return null; + } } diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java index 6d9cbc1f2..e4d9efa3e 100644 --- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java +++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java @@ -221,4 +221,8 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor uses = statementKickAsm.getUses(); @@ -166,6 +166,9 @@ public class ProgramValueIterator { for(String label : referenced.keySet()) { execute(new ProgramValue.ProgramValueAsmReferenced(statementAsm, label), handler, statement, statementsIt, block); } + } else if(statement instanceof StatementStackPull) { + StatementStackPull statementStackPull = (StatementStackPull) statement; + execute(new ProgramValue.StackPullBytes(statementStackPull), handler, statement, statementsIt, block); } } @@ -245,13 +248,13 @@ public class ProgramValueIterator { subValues.add(new ProgramValue.ProgramValueLValueIntermediateVariable((LvalueIntermediate) value)); } else if(value instanceof ParamValue) { subValues.add(new ProgramValue.ProgramValueParamValue((ParamValue) value)); - } else if(value instanceof StackIdxValue) { - subValues.add(new ProgramValue.ProgramValueStackIdxValue((StackIdxValue) value)); } else if(value instanceof MemsetValue) { subValues.add(new ProgramValue.ProgramValueMemsetValue((MemsetValue) value)); } else if(value instanceof MemcpyValue) { subValues.add(new ProgramValue.ProgramValueMempySize((MemcpyValue) value)); subValues.add(new ProgramValue.ProgramValueMempySource((MemcpyValue) value)); + } else if(value instanceof StackIdxValue) { + subValues.add(new ProgramValue.ProgramValueStackIdxValue((StackIdxValue) value)); } else if(value == null || value instanceof SymbolVariableRef || value instanceof Variable || @@ -259,8 +262,9 @@ public class ProgramValueIterator { value instanceof ConstantLiteral || value instanceof StructZero || value instanceof Label || - value instanceof LabelRef - ) { + value instanceof LabelRef || + value instanceof StackPullValue + ) { // No sub values } else { throw new RuntimeException("Unhandled value type " + value.getClass()); diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementAsm.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementAsm.java index aa0d12cbf..7a1c92891 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementAsm.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementAsm.java @@ -26,7 +26,7 @@ public class StatementAsm extends StatementBase { private AsmClobber declaredClobber; public StatementAsm(String asmBody, Map referenced, AsmClobber declaredClobber, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.asmBody = asmBody; this.referenced = referenced; this.declaredClobber = declaredClobber; diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementAssignment.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementAssignment.java index f1df8d1f8..99de0693f 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementAssignment.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementAssignment.java @@ -7,6 +7,7 @@ import dk.camelot64.kickc.model.values.LValue; import dk.camelot64.kickc.model.values.RValue; import java.util.List; +import java.util.Objects; /** * Single Static Assignment Form Statement. @@ -28,27 +29,15 @@ public class StatementAssignment extends StatementBase implements StatementLValu private boolean initialAssignment; public StatementAssignment(LValue lValue, RValue rValue2, boolean initialAssignment, StatementSource source, List comments) { - this(lValue, null, null, rValue2, initialAssignment, null, source, comments); + this(lValue, null, null, rValue2, initialAssignment, source, comments); } public StatementAssignment(LValue lValue, Operator operator, RValue rValue2, boolean initialAssignment, StatementSource source, List comments) { - this(lValue, null, operator, rValue2, initialAssignment, null, source, comments); + this(lValue, null, operator, rValue2, initialAssignment, source, comments); } public StatementAssignment(LValue lValue, RValue rValue1, Operator operator, RValue rValue2, boolean initialAssignment, StatementSource source, List comments) { - this(lValue, rValue1, operator, rValue2, initialAssignment, null, source, comments); - } - - public StatementAssignment( - LValue lValue, - RValue rValue1, - Operator operator, - RValue rValue2, - boolean initialAssignment, - Integer index, - StatementSource source, - List comments) { - super(index, source, comments); + super(source, comments); this.lValue = lValue; this.rValue1 = rValue1; this.operator = operator; @@ -56,7 +45,6 @@ public class StatementAssignment extends StatementBase implements StatementLValu this.initialAssignment = initialAssignment; } - public LValue getlValue() { return lValue; } @@ -114,22 +102,16 @@ public class StatementAssignment extends StatementBase implements StatementLValu if(this == o) return true; if(o == null || getClass() != o.getClass()) return false; if(!super.equals(o)) return false; - StatementAssignment that = (StatementAssignment) o; - - if(!lValue.equals(that.lValue)) return false; - if(rValue1 != null ? !rValue1.equals(that.rValue1) : that.rValue1 != null) return false; - if(operator != null ? !operator.equals(that.operator) : that.operator != null) return false; - return rValue2 != null ? rValue2.equals(that.rValue2) : that.rValue2 == null; + return initialAssignment == that.initialAssignment && + Objects.equals(lValue, that.lValue) && + Objects.equals(rValue1, that.rValue1) && + Objects.equals(operator, that.operator) && + Objects.equals(rValue2, that.rValue2); } @Override public int 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); - return result; + return Objects.hash(super.hashCode(), lValue, rValue1, operator, rValue2, initialAssignment); } } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java index 32935634c..7a7168049 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementBase.java @@ -16,8 +16,8 @@ public abstract class StatementBase implements Statement { /** Comments preceding the statement in the source code. */ private List comments; - public StatementBase(Integer index, StatementSource source, List comments) { - this.index = index; + public StatementBase(StatementSource source, List comments) { + this.index = null; this.source = source; this.comments = comments; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java index 289d476d2..6747016eb 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java @@ -28,7 +28,7 @@ public class StatementCall extends StatementBase implements StatementLValue, Sta private boolean initialAssignment; public StatementCall(LValue lValue, String procedureName, List parameters, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.lValue = lValue; this.procedureName = procedureName; this.parameters = parameters; diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallExecute.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallExecute.java index ff3a3caaa..4bf770188 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallExecute.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallExecute.java @@ -20,7 +20,7 @@ public class StatementCallExecute extends StatementBase implements StatementCall private ProcedureRef procedure; public StatementCallExecute(ProcedureRef procedure, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.procedure = procedure; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallFinalize.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallFinalize.java index 3672b8f65..6979bd46a 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallFinalize.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallFinalize.java @@ -25,7 +25,7 @@ public class StatementCallFinalize extends StatementBase implements StatementLVa private boolean initialAssignment; public StatementCallFinalize(LValue lValue, ProcedureRef procedure, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.lValue = lValue; this.procedure = procedure; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallPointer.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallPointer.java index f4adea33b..ca7761da8 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallPointer.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallPointer.java @@ -3,7 +3,6 @@ package dk.camelot64.kickc.model.statements; import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.values.LValue; -import dk.camelot64.kickc.model.values.ProcedureRef; import dk.camelot64.kickc.model.values.RValue; import java.util.List; @@ -24,7 +23,7 @@ public class StatementCallPointer extends StatementBase implements StatementLVal private boolean initialAssignment; public StatementCallPointer(LValue lValue, RValue procedure, List parameters, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.lValue = lValue; this.procedure = procedure; this.parameters = parameters; diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallPrepare.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallPrepare.java index d286fdf26..b4275ba6d 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallPrepare.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallPrepare.java @@ -23,7 +23,7 @@ public class StatementCallPrepare extends StatementBase { private List parameters; public StatementCallPrepare(ProcedureRef procedure, List parameters, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.procedure = procedure; this.parameters = parameters; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java index 95c3225c9..b208884fe 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementConditionalJump.java @@ -27,7 +27,7 @@ public class StatementConditionalJump extends StatementBase { private boolean wasUnrolled; public StatementConditionalJump(RValue condition, LabelRef destination,StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.rValue1 = null; this.operator = null; this.rValue2 = condition; @@ -41,7 +41,7 @@ public class StatementConditionalJump extends StatementBase { LabelRef destination, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.rValue1 = rValue1; this.operator = operator; this.rValue2 = rValue2; diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementJump.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementJump.java index 73d6692a8..fc71d1634 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementJump.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementJump.java @@ -17,7 +17,7 @@ public class StatementJump extends StatementBase { private LabelRef destination; public StatementJump(LabelRef destination, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.destination = destination; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementKickAsm.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementKickAsm.java index 5b8d13a3d..15d7df0b0 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementKickAsm.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementKickAsm.java @@ -5,7 +5,6 @@ import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.values.RValue; import dk.camelot64.kickc.model.values.SymbolRef; -import dk.camelot64.kickc.model.values.SymbolVariableRef; import java.util.ArrayList; import java.util.List; @@ -32,13 +31,13 @@ public class StatementKickAsm extends StatementBase { private AsmClobber declaredClobber; public StatementKickAsm(String kickAsmCode, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.kickAsmCode = kickAsmCode; this.uses = new ArrayList<>(); } public StatementKickAsm(String kickAsmCode, RValue location, RValue bytes, RValue cycles, List uses, AsmClobber declaredClobber, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.kickAsmCode = kickAsmCode; this.location = location; this.bytes = bytes; diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementLabel.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementLabel.java index 4aeea0532..c32c45b07 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementLabel.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementLabel.java @@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.values.LabelRef; import dk.camelot64.kickc.model.Program; -import java.util.ArrayList; import java.util.List; /** @@ -15,7 +14,7 @@ public class StatementLabel extends StatementBase { private LabelRef label; public StatementLabel(LabelRef label, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.label = label; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java index a447152b2..a01bfefeb 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementPhiBlock.java @@ -24,7 +24,7 @@ public class StatementPhiBlock extends StatementBase { private List phiVariables; public StatementPhiBlock(List comments) { - super(null, new StatementSource(RuleContext.EMPTY), comments); + super(new StatementSource(RuleContext.EMPTY), comments); this.phiVariables = new ArrayList<>(); } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureBegin.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureBegin.java index 7000c0faf..65012d36a 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureBegin.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureBegin.java @@ -4,7 +4,6 @@ import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.values.ProcedureRef; import dk.camelot64.kickc.model.Program; -import java.util.ArrayList; import java.util.List; /** Procedure declaration in SSA */ @@ -15,7 +14,7 @@ public class StatementProcedureBegin extends StatementBase { private Strategy strategy; public StatementProcedureBegin(ProcedureRef procedure,StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.procedure = procedure; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureEnd.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureEnd.java index 06615ade1..0e7b77346 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureEnd.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementProcedureEnd.java @@ -14,7 +14,7 @@ public class StatementProcedureEnd extends StatementBase { private ProcedureRef procedure; public StatementProcedureEnd(ProcedureRef procedure, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.procedure = procedure; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementReturn.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementReturn.java index 43e127f3a..4afdae20d 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementReturn.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementReturn.java @@ -17,7 +17,7 @@ public class StatementReturn extends StatementBase { private RValue value; public StatementReturn(RValue value, StatementSource source, List comments) { - super(null, source, comments); + super(source, comments); this.value = value; } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementStackPull.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementStackPull.java new file mode 100644 index 000000000..a59e45a28 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementStackPull.java @@ -0,0 +1,31 @@ +package dk.camelot64.kickc.model.statements; + +import dk.camelot64.kickc.model.Comment; +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.values.ConstantValue; + +import java.util.List; + +/** Pulls some bytes of the stack. */ +public class StatementStackPull extends StatementBase { + + private ConstantValue pullBytes; + + public StatementStackPull(ConstantValue pullBytes, StatementSource source, List comments) { + super(source, comments); + this.pullBytes = pullBytes; + } + + public ConstantValue getPullBytes() { + return pullBytes; + } + + public void setPullBytes(ConstantValue pullBytes) { + this.pullBytes = pullBytes; + } + + @Override + public String toString(Program program, boolean aliveInfo) { + return "stackpull("+pullBytes.toString(program)+")"; + } +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java b/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java index 276548bac..df44fdd5b 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1UnwindStructValues.java @@ -10,7 +10,8 @@ import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; import dk.camelot64.kickc.model.types.SymbolTypeStruct; import dk.camelot64.kickc.model.values.*; -import dk.camelot64.kickc.passes.unwinding.*; +import dk.camelot64.kickc.passes.unwinding.ValueSource; +import dk.camelot64.kickc.passes.unwinding.ValueSourceFactory; import java.util.ArrayList; import java.util.List; @@ -90,16 +91,10 @@ public class Pass1UnwindStructValues extends Pass1Base { private boolean unwindCall(StatementCall call, ListIterator stmtIt, ControlFlowBlock currentBlock) { // Unwind struct value return value boolean lvalUnwound = false; - - final ValueSource lValueSource = ValueSourceFactory.getValueSource(call.getlValue(), getProgram(), getScope(), call, stmtIt, currentBlock); - if(lValueSource != null && lValueSource.isUnwindable()) { - ArrayList unwoundMembers = new ArrayList<>(); - for(String memberName : lValueSource.getMemberNames(getScope())) { - ValueSource memberUnwinding = lValueSource.getMemberUnwinding(memberName, getProgram(), getScope(), call, stmtIt, currentBlock); - unwoundMembers.add(memberUnwinding.getSimpleValue(getScope())); - } - ValueList unwoundLValue = new ValueList(unwoundMembers); - call.setlValue(unwoundLValue); + final ValueSource valueSource = ValueSourceFactory.getValueSource(call.getlValue(), getProgram(), getScope(), call, stmtIt, currentBlock); + RValue unwoundLValue = unwindValue(valueSource, call, stmtIt, currentBlock); + if(unwoundLValue != null && !call.getlValue().equals(unwoundLValue)) { + call.setlValue((LValue) unwoundLValue); getLog().append("Converted procedure call LValue to member unwinding " + call.toString(getProgram(), false)); lvalUnwound = true; } @@ -132,6 +127,31 @@ public class Pass1UnwindStructValues extends Pass1Base { return (anyParameterUnwound || lvalUnwound); } + /** + * Unwind an LVa.lue to a ValueList if it is unwindable. + * @param value The value to unwind + * @param statement The current statement + * @param stmtIt Statement iterator + * @param currentBlock current block + * @return The unwound ValueList. null if the value is not unwindable. + */ + private RValue unwindValue(ValueSource lValueSource, Statement statement, ListIterator stmtIt, ControlFlowBlock currentBlock) { + if(lValueSource==null) { + return null; + } else if(lValueSource.isSimple()) { + return lValueSource.getSimpleValue(getScope()); + } else if(lValueSource.isUnwindable()) { + ArrayList unwoundMembers = new ArrayList<>(); + for(String memberName : lValueSource.getMemberNames(getScope())) { + ValueSource memberUnwinding = lValueSource.getMemberUnwinding(memberName, getProgram(), getScope(), statement, stmtIt, currentBlock); + unwoundMembers.add(unwindValue(memberUnwinding, statement, stmtIt, currentBlock)); + } + return new ValueList(unwoundMembers); + } else { + return null; + } + } + /** * Unwind any return value that is a struct value into the member values * @@ -139,22 +159,15 @@ public class Pass1UnwindStructValues extends Pass1Base { */ private boolean unwindReturn(StatementReturn statementReturn, ListIterator stmtIt, ControlFlowBlock currentBlock) { - boolean modified = false; - // Unwind struct value return value - final ValueSource returnVarUnwinding = ValueSourceFactory.getValueSource(statementReturn.getValue(), getProgram(), getScope(), statementReturn, stmtIt, currentBlock); - if(returnVarUnwinding != null && returnVarUnwinding.isUnwindable()) { - ArrayList unwoundMembers = new ArrayList<>(); - for(String memberName : returnVarUnwinding.getMemberNames(getScope())) { - final ValueSource memberUnwinding = returnVarUnwinding.getMemberUnwinding(memberName, getProgram(), getScope(), statementReturn, stmtIt, currentBlock); - unwoundMembers.add(memberUnwinding.getSimpleValue(getScope())); - } - ValueList unwoundReturnValue = new ValueList(unwoundMembers); - statementReturn.setValue(unwoundReturnValue); + boolean unwound = false; + final ValueSource valueSource = ValueSourceFactory.getValueSource(statementReturn.getValue(), getProgram(), getScope(), statementReturn, stmtIt, currentBlock); + RValue unwoundValue = unwindValue(valueSource, statementReturn, stmtIt, currentBlock); + if(unwoundValue != null && !statementReturn.getValue().equals(unwoundValue)) { + statementReturn.setValue(unwoundValue); getLog().append("Converted procedure struct return value to member unwinding " + statementReturn.toString(getProgram(), false)); - modified = true; - + unwound = true; } - return modified; + return unwound; } /** diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java index 5999f62b6..f11e080b6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConditionalJumpSimplification.java @@ -10,7 +10,7 @@ import dk.camelot64.kickc.model.operators.Operator; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAssignment; import dk.camelot64.kickc.model.statements.StatementConditionalJump; -import dk.camelot64.kickc.model.statements.StatementInfos; +import dk.camelot64.kickc.model.StatementInfos; import dk.camelot64.kickc.model.symbols.Scope; import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.values.RValue; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 458bce2eb..2ffff4cf3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -889,94 +889,16 @@ public class Pass4CodeGeneration { asm.getCurrentChunk().setFragment("jsr"); asm.addInstruction("jsr", AsmAddressingMode.ABS, call.getProcedure().getFullName(), false); } - } else if(statement instanceof StatementCallFinalize) { - StatementCallFinalize call = (StatementCallFinalize) statement; - Procedure procedure = getScope().getProcedure(call.getProcedure()); - if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) { - long stackFrameByteSize = CallingConventionStack.getStackFrameByteSize(procedure); - long returnByteSize = procedure.getReturnType() == null ? 0 : procedure.getReturnType().getSizeBytes(); - long stackCleanBytes = (call.getlValue() == null) ? stackFrameByteSize : (stackFrameByteSize - returnByteSize); - if(stackCleanBytes > 0) { - // Clean up the stack - String pullSignature = "_stackpullbyte_" + stackCleanBytes; - AsmFragmentInstanceSpec pullFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, pullSignature, new LinkedHashMap<>(), block.getScope()); - generateAsm(asm, pullFragmentInstanceSpec); - } - // Pull result from the stack - if(call.getlValue() != null) { - if(stackCleanBytes > 0) - asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo)); - boolean isValueListStruct = (call.getlValue() instanceof ValueList) && (procedure.getReturnType() instanceof SymbolTypeStruct); - if(!isValueListStruct) { - // Simple return value - fetch from stack - SymbolType returnType = procedure.getReturnType(); - AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(call.getlValue(), new StackPullValue(returnType), program, block.getScope()); - ensureEncoding(asm, asmFragmentInstanceSpecFactory); - generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec()); - } else { - // Struct value list return value - fetch each member from stack - final List lValues = ((ValueList) call.getlValue()).getList(); - final StructDefinition structDefinition = ((SymbolTypeStruct) procedure.getReturnType()).getStructDefinition(getScope()); - final List memberVars = new ArrayList<>(structDefinition.getAllVars(false)); - for(int i = 0; i < memberVars.size(); i++) { - LValue lValue = (LValue) lValues.get(i); - Variable memberDef = memberVars.get(i); - final SymbolType memberType = memberDef.getType(); - if(i > 0) - asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo)); - AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(lValue, new StackPullValue(memberType), program, block.getScope()); - ensureEncoding(asm, asmFragmentInstanceSpecFactory); - generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec()); - asm.getCurrentChunk().setSubStatementIdx(i); - asm.getCurrentChunk().setSubStatementId(memberDef.toString(program)); - } - } - } - } + } else if(statement instanceof StatementStackPull) { + String pullSignature = "_stackpullbyte_" + AsmFormat.getAsmConstant(program, ((StatementStackPull) statement).getPullBytes(), 99, block.getScope()); + AsmFragmentInstanceSpec pullFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, pullSignature, new LinkedHashMap<>(), block.getScope()); + generateAsm(asm, pullFragmentInstanceSpec); } else if(statement instanceof StatementReturn) { Procedure procedure = null; ScopeRef scope = block.getScope(); if(!scope.equals(ScopeRef.ROOT)) { procedure = getScope().getProcedure(scope.getFullName()); } - - if(procedure != null && Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) { - StatementReturn returnStatement = (StatementReturn) statement; - if(returnStatement.getValue() != null) { - // Store return value on stack - asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo)); - SymbolType returnType = procedure.getReturnType(); - boolean isValueListStruct = (returnStatement.getValue() instanceof ValueList) && (returnType instanceof SymbolTypeStruct); - if(!isValueListStruct) { - // A simple return type - put it on the stack - ConstantRef returnOffsetConstant = CallingConventionStack.getReturnOffsetConstant(procedure); - AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(new StackIdxValue(returnOffsetConstant, returnType), returnStatement.getValue(), program, block.getScope()); - ensureEncoding(asm, asmFragmentInstanceSpecFactory); - generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec()); - } else { - // A struct return value in a value list - Store each value on the stack - final List returnValues = ((ValueList) returnStatement.getValue()).getList(); - final StructDefinition structDefinition = ((SymbolTypeStruct) returnType).getStructDefinition(getScope()); - final List memberVars = new ArrayList<>(structDefinition.getAllVars(false)); - for(int i = 0; i < memberVars.size(); i++) { - RValue returnValue = returnValues.get(i); - Variable memberDef = memberVars.get(i); - final SymbolType memberType = memberDef.getType(); - ConstantRef returnOffsetConstant = CallingConventionStack.getReturnOffsetConstant(procedure); - ConstantRef structMemberOffsetConstant = SizeOfConstants.getStructMemberOffsetConstant(getScope(), structDefinition, memberDef.getLocalName()); - ConstantBinary memberReturnOffsetConstant = new ConstantBinary(returnOffsetConstant, Operators.PLUS, structMemberOffsetConstant); - if(i > 0) - asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo)); - AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(new StackIdxValue(memberReturnOffsetConstant, memberType), returnValue, program, block.getScope()); - ensureEncoding(asm, asmFragmentInstanceSpecFactory); - generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec()); - asm.getCurrentChunk().setSubStatementIdx(i); - asm.getCurrentChunk().setSubStatementId(memberDef.toString(program)); - } - } - } - } - if(procedure == null || procedure.getInterruptType() == null) { asm.addInstruction("rts", AsmAddressingMode.NON, null, false); } else { diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNCallingConventionStack.java b/src/main/java/dk/camelot64/kickc/passes/PassNCallingConventionStack.java index 401f465dc..74fd505f5 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNCallingConventionStack.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNCallingConventionStack.java @@ -1,18 +1,23 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.CallingConventionStack; +import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.iterator.ProgramValueIterator; +import dk.camelot64.kickc.model.operators.Operators; import dk.camelot64.kickc.model.statements.*; -import dk.camelot64.kickc.model.symbols.*; +import dk.camelot64.kickc.model.symbols.Procedure; +import dk.camelot64.kickc.model.symbols.Scope; +import dk.camelot64.kickc.model.symbols.StructDefinition; +import dk.camelot64.kickc.model.symbols.Variable; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; +import dk.camelot64.kickc.model.types.SymbolTypeStruct; import dk.camelot64.kickc.model.values.*; +import dk.camelot64.kickc.passes.utils.SizeOfConstants; -import java.util.HashMap; -import java.util.ListIterator; -import java.util.Map; +import java.util.*; /** Handle calling convention {@link Procedure.CallingConvention#STACK_CALL} by converting the making control flow graph and symbols calling convention specific. */ public class PassNCallingConventionStack extends Pass2SsaOptimization { @@ -68,8 +73,8 @@ public class PassNCallingConventionStack extends Pass2SsaOptimization { } } + // Convert param(xxx) to stackidx(PARAM_X) = xxx if(offsetConstants.size() > 0) { - // Convert ParamValue to StackIdxValue ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> { if(programValue.get() instanceof ParamValue) { // Convert ParamValues to calling-convention specific param-value @@ -84,7 +89,122 @@ public class PassNCallingConventionStack extends Pass2SsaOptimization { } }); } + + // Convert procedure return xxx to stackidx(RETURN) = xxx; + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + ListIterator stmtIt = block.getStatements().listIterator(); + while(stmtIt.hasNext()) { + Statement statement = stmtIt.next(); + if(statement instanceof StatementReturn) { + final Scope blockScope = getScope().getScope(block.getScope()); + if(blockScope instanceof Procedure) { + Procedure procedure = (Procedure) blockScope; + final SymbolType returnType = procedure.getReturnType(); + if(!SymbolType.VOID.equals(returnType) && Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) { + ConstantRef returnOffsetConstant = CallingConventionStack.getReturnOffsetConstant(procedure); + final RValue value = ((StatementReturn) statement).getValue(); + stmtIt.previous(); + generateStackReturnValues(value, returnType, returnOffsetConstant, statement.getSource(), statement.getComments(), stmtIt); + stmtIt.next(); + ((StatementReturn) statement).setValue(null); + } + } + } + } + } + + // Convert xxx = callfinalize to xxx = stackpull(type); + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + ListIterator stmtIt = block.getStatements().listIterator(); + while(stmtIt.hasNext()) { + Statement statement = stmtIt.next(); + if(statement instanceof StatementCallFinalize) { + final StatementCallFinalize call = (StatementCallFinalize) statement; + Procedure procedure = getScope().getProcedure(call.getProcedure()); + final SymbolType returnType = procedure.getReturnType(); + if(Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) { + long stackFrameByteSize = CallingConventionStack.getStackFrameByteSize(procedure); + long returnByteSize = procedure.getReturnType() == null ? 0 : procedure.getReturnType().getSizeBytes(); + long stackCleanBytes = (call.getlValue() == null) ? stackFrameByteSize : (stackFrameByteSize - returnByteSize); + stmtIt.previous(); + final StatementSource source = call.getSource(); + final List comments = call.getComments(); + if(stackCleanBytes > 0) { + // Clean up the stack + stmtIt.add(new StatementStackPull( new ConstantInteger(stackCleanBytes), source, comments)); + //String pullSignature = "_stackpullbyte_" + stackCleanBytes; + } + final RValue value = call.getlValue(); + if(value!=null) + generateStackPullValues(value, returnType, statement.getSource(), statement.getComments(), stmtIt); + stmtIt.next(); + stmtIt.remove(); + } + } + } + } + + return false; } + /** + * Put a return value onto the stack by generating stackidx(RETURN) = xxx assignments + * + * @param value The value to return + * @param returnType The type of the value + * @param stackReturnOffset The offset onto the stack to place the value at + * @param source The source line + * @param comments The comments + * @param stmtIt The statment iterator used to add statements to. + */ + private void generateStackReturnValues(RValue value, SymbolType returnType, ConstantValue stackReturnOffset, StatementSource source, List comments, ListIterator stmtIt) { + if(!(value instanceof ValueList) || !(returnType instanceof SymbolTypeStruct)) { + // A simple value to put on the stack + final StatementAssignment stackReturn = new StatementAssignment(new StackIdxValue(stackReturnOffset, returnType), value, false, source, comments); + stmtIt.add(stackReturn); + getLog().append("Calling convention " + Procedure.CallingConvention.STACK_CALL + " adding stack return " + stackReturn); + } else { + // A struct to put on the stack + final List memberValues = ((ValueList) value).getList(); + final StructDefinition structDefinition = ((SymbolTypeStruct) returnType).getStructDefinition(getScope()); + final List memberVars = new ArrayList<>(structDefinition.getAllVars(false)); + for(int i = 0; i < memberVars.size(); i++) { + final Variable memberVar = memberVars.get(i); + final RValue memberValue = memberValues.get(i); + ConstantRef structMemberOffsetConstant = SizeOfConstants.getStructMemberOffsetConstant(getScope(), structDefinition, memberVar.getLocalName()); + ConstantBinary memberReturnOffsetConstant = new ConstantBinary(stackReturnOffset, Operators.PLUS, structMemberOffsetConstant); + generateStackReturnValues(memberValue, memberVar.getType(), memberReturnOffsetConstant, source, comments, stmtIt); + } + } + } + + /** + * Generate stack pull xxx = stackpull(type) assignments + * + * @param value The value to return + * @param symbolType The type of the value + * @param source The source line + * @param comments The comments + * @param stmtIt The statment iterator used to add statements to. + */ + private void generateStackPullValues(RValue value, SymbolType symbolType, StatementSource source, List comments, ListIterator stmtIt) { + if(!(value instanceof ValueList) || !(symbolType instanceof SymbolTypeStruct)) { + // A simple value to put on the stack + final StatementAssignment stackPull = new StatementAssignment((LValue) value, new StackPullValue(symbolType), false, source, comments); + stmtIt.add(stackPull); + getLog().append("Calling convention " + Procedure.CallingConvention.STACK_CALL + " adding stack pull " + stackPull); + } else { + // A struct to put on the stack + final List memberValues = ((ValueList) value).getList(); + final StructDefinition structDefinition = ((SymbolTypeStruct) symbolType).getStructDefinition(getScope()); + final List memberVars = new ArrayList<>(structDefinition.getAllVars(false)); + for(int i = 0; i < memberVars.size(); i++) { + final Variable memberVar = memberVars.get(i); + final RValue memberValue = memberValues.get(i); + generateStackPullValues(memberValue, memberVar.getType(), source, comments, stmtIt); + } + } + } + } diff --git a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcStatementInfos.java b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcStatementInfos.java index 2ee0eb1a6..2a819ce27 100644 --- a/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcStatementInfos.java +++ b/src/main/java/dk/camelot64/kickc/passes/calcs/PassNCalcStatementInfos.java @@ -4,7 +4,7 @@ package dk.camelot64.kickc.passes.calcs; import dk.camelot64.kickc.model.ControlFlowBlock; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.statements.StatementInfos; +import dk.camelot64.kickc.model.StatementInfos; import java.util.LinkedHashMap; diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceFactory.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceFactory.java index 99ff222ae..deaed6fd9 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceFactory.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceFactory.java @@ -61,8 +61,8 @@ public class ValueSourceFactory { return structValueSource.getMemberUnwinding(((StructMemberRef) value).getMemberName(), program, programScope, currentStmt, stmtIt, currentBlock); } if(valueType instanceof SymbolTypeStruct && value instanceof ParamValue) { - final StructDefinition structDefinition = ((SymbolTypeStruct) valueType).getStructDefinition(programScope); - return new ValueSourceParamList((ParamValue) value, structDefinition); + final ValueSource subValueSource = getValueSource(((ParamValue) value).getParameter(), program, programScope, currentStmt, stmtIt, currentBlock); + return new ValueSourceParamValue(subValueSource); } return null; } diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceParamList.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceParamList.java deleted file mode 100644 index b012ffc2f..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceParamList.java +++ /dev/null @@ -1,65 +0,0 @@ -package dk.camelot64.kickc.passes.unwinding; - -import dk.camelot64.kickc.model.ControlFlowBlock; -import dk.camelot64.kickc.model.InternalError; -import dk.camelot64.kickc.model.Program; -import dk.camelot64.kickc.model.statements.Statement; -import dk.camelot64.kickc.model.symbols.ArraySpec; -import dk.camelot64.kickc.model.symbols.ProgramScope; -import dk.camelot64.kickc.model.symbols.StructDefinition; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.values.LValue; -import dk.camelot64.kickc.model.values.ParamValue; -import dk.camelot64.kickc.model.values.RValue; - -import java.util.ListIterator; - -/** A parameter value list. */ -public class ValueSourceParamList extends ValueSourceBase { - - private final StructDefinition structDefinition; - private final ParamValue paramValue; - - public ValueSourceParamList(ParamValue paramValue, StructDefinition structDefinition) { - this.paramValue = paramValue; - this.structDefinition = structDefinition; - } - - @Override - public SymbolType getSymbolType() { - return structDefinition.getType(); - } - - @Override - public ArraySpec getArraySpec() { - return null; - } - - @Override - protected boolean isStructClassic() { - return false; - } - - @Override - public RValue getSimpleValue(ProgramScope programScope) { - throw new InternalError("Not a simple value"); - } - - @Override - public LValue getBulkLValue(ProgramScope scope) { - throw new InternalError("Not a bulk value"); - } - - @Override - public RValue getBulkRValue(ProgramScope scope) { - throw new InternalError("Not a bulk value"); - } - - @Override - public ValueSource getMemberUnwinding(String memberName, Program program, ProgramScope programScope, Statement currentStmt, ListIterator stmtIt, ControlFlowBlock currentBlock) { - final ValueSource paramValueSource = ValueSourceFactory.getValueSource(paramValue.getParameter(), program, programScope, currentStmt, stmtIt, currentBlock); - final ValueSource memberUnwinding = paramValueSource.getMemberUnwinding(memberName, program, programScope, currentStmt, stmtIt, currentBlock); - return new ValueSourceParamValue(memberUnwinding); - } - -} diff --git a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceParamValue.java b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceParamValue.java index 638ee6363..9dff01e65 100644 --- a/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceParamValue.java +++ b/src/main/java/dk/camelot64/kickc/passes/unwinding/ValueSourceParamValue.java @@ -14,7 +14,7 @@ import dk.camelot64.kickc.model.values.VariableRef; import java.util.ListIterator; -/** An unwound parameter value. */ +/** A parameter value list. */ public class ValueSourceParamValue extends ValueSourceBase { private final ValueSource valueSource; @@ -30,7 +30,7 @@ public class ValueSourceParamValue extends ValueSourceBase { @Override public ArraySpec getArraySpec() { - return valueSource.getArraySpec(); + return null; } @Override @@ -55,7 +55,8 @@ public class ValueSourceParamValue extends ValueSourceBase { @Override public ValueSource getMemberUnwinding(String memberName, Program program, ProgramScope programScope, Statement currentStmt, ListIterator stmtIt, ControlFlowBlock currentBlock) { - throw new InternalError("Not unwindable"); + final ValueSource memberUnwinding = valueSource.getMemberUnwinding(memberName, program, programScope, currentStmt, stmtIt, currentBlock); + return new ValueSourceParamValue(memberUnwinding); } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 6d9e5d7f7..8a3c429ae 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -279,6 +279,11 @@ public class TestPrograms { compileAndCompare("declared-memory-var-0"); } + @Test + public void testProcedureCallingConventionStack11() throws IOException, URISyntaxException { + compileAndCompare("procedure-callingconvention-stack-11"); + } + @Test public void testProcedureCallingConventionStack10() throws IOException, URISyntaxException { compileAndCompare("procedure-callingconvention-stack-10"); diff --git a/src/test/kc/procedure-callingconvention-stack-11.kc b/src/test/kc/procedure-callingconvention-stack-11.kc new file mode 100644 index 000000000..ffefcd363 --- /dev/null +++ b/src/test/kc/procedure-callingconvention-stack-11.kc @@ -0,0 +1,44 @@ +// Test a procedure with calling convention stack +// Returning and passing struct of struct values + +#pragma calling(__stackcall) +#pragma var_model(ma_zp) + +const char* SCREEN = 0x0400; +char idx = 0; + +struct Point { + char x; + char y; +}; + +struct Vector { + struct Point p1; + struct Point p2; +}; + + +void main(void) { + for(char i=0;i<5;i++) { + struct Vector v = get(i); + print(v); + } +} + +struct Vector get(char i) { + struct Vector v = { {i, i/2}, {i+1, i*2} }; + return v; +} + +void print(struct Vector v) { + SCREEN[idx++] = v.p1.x; + SCREEN[idx++] = v.p1.y; + SCREEN[idx++] = v.p2.x; + SCREEN[idx++] = v.p2.y; + SCREEN[idx++] = ' '; +} + + + + + diff --git a/src/test/ref/procedure-callingconvention-stack-0.cfg b/src/test/ref/procedure-callingconvention-stack-0.cfg index 1ec9e63e9..5f27ebb47 100644 --- a/src/test/ref/procedure-callingconvention-stack-0.cfg +++ b/src/test/ref/procedure-callingconvention-stack-0.cfg @@ -12,19 +12,21 @@ main: scope:[main] from @1 [4] callprepare plus (byte) '0' (byte) 7 [5] callexecute plus - [6] (byte~) main::$0 ← callfinalize plus - [7] *((const byte*) SCREEN) ← (byte~) main::$0 + stackpull((number) 1) + [7] (byte~) main::$0 ← stackpull(byte) + [8] *((const byte*) SCREEN) ← (byte~) main::$0 to:main::@return main::@return: scope:[main] from main - [8] return + [9] return to:@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) - [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 + [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) + [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) + [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [12] return (byte) plus::return#0 + [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 + [14] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-0.log b/src/test/ref/procedure-callingconvention-stack-0.log index d85baac91..ab6ad9428 100644 --- a/src/test/ref/procedure-callingconvention-stack-0.log +++ b/src/test/ref/procedure-callingconvention-stack-0.log @@ -3,6 +3,8 @@ Culled Empty Block (label) plus::@1 Calling convention STACK_CALL adding prepare/execute/finalize for (byte~) main::$0 ← call plus (byte) '0' (number) 7 Calling convention STACK_CALL replacing param((byte) plus::a) with stackidx(byte,(const byte) plus::OFFSET_STACK_A) Calling convention STACK_CALL replacing param((byte) plus::b) with stackidx(byte,(const byte) plus::OFFSET_STACK_B) +Calling convention STACK_CALL adding stack return stackidx(byte,plus::OFFSET_STACK_RETURN) ← plus::return +Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(byte) CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -12,7 +14,8 @@ CONTROL FLOW GRAPH SSA main: scope:[main] from @2 callprepare plus (byte) '0' (number) 7 callexecute plus - (byte~) main::$0 ← callfinalize plus + stackpull((number) 1) + (byte~) main::$0 ← stackpull(byte) *((const byte*) SCREEN + (number) 0) ← (byte~) main::$0 to:main::@return main::@return: scope:[main] from main @@ -28,7 +31,8 @@ plus: scope:[plus] from to:plus::@return plus::@return: scope:[plus] from plus (byte) plus::return#1 ← phi( plus/(byte) plus::return#0 ) - return (byte) plus::return#1 + stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#1 + return to:@return @2: scope:[] from @begin call main @@ -73,10 +77,8 @@ Finalized unsigned number type (byte) 0 Successful SSA optimization PassNFinalizeNumberTypeConversions Alias (byte) plus::return#0 = (byte~) plus::$0 (byte) plus::return#1 Successful SSA optimization Pass2AliasElimination -Simplifying expression containing zero SCREEN in [3] *((const byte*) SCREEN + (byte) 0) ← (byte~) main::$0 +Simplifying expression containing zero SCREEN in [4] *((const byte*) SCREEN + (byte) 0) ← (byte~) main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN -Successful SSA optimization PassNEliminateUnusedVars Adding NOP phi() at start of @begin Adding NOP phi() at start of @2 Adding NOP phi() at start of @3 @@ -108,34 +110,36 @@ FINAL CONTROL FLOW GRAPH main: scope:[main] from @1 [4] callprepare plus (byte) '0' (byte) 7 [5] callexecute plus - [6] (byte~) main::$0 ← callfinalize plus - [7] *((const byte*) SCREEN) ← (byte~) main::$0 + stackpull((number) 1) + [7] (byte~) main::$0 ← stackpull(byte) + [8] *((const byte*) SCREEN) ← (byte~) main::$0 to:main::@return main::@return: scope:[main] from main - [8] return + [9] return to:@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) - [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 + [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) + [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) + [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [12] return (byte) plus::return#0 + [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 + [14] return to:@return VARIABLE REGISTER WEIGHTS (void()) main() -(byte~) main::$0 2.0 +(byte~) main::$0 4.0 __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::a (byte) plus::a#0 2.0 (byte) plus::b (byte) plus::b#0 4.0 (byte) plus::return -(byte) plus::return#0 2.0 +(byte) plus::return#0 4.0 Initial phi equivalence classes Added variable main::$0 to live range equivalence class [ main::$0 ] @@ -188,18 +192,18 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [6] (byte~) main::$0 ← callfinalize plus -- vbuz1=_stackpullbyte_ + // [7] (byte~) main::$0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla sta.z __0 - // [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1 + // [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1 lda.z __0 sta SCREEN jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts } // plus @@ -207,18 +211,19 @@ main: { plus: { .const OFFSET_STACK_A = 1 .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN = 1 .label a = 3 .label b = 4 .label return = 5 - // [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1 + // [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b - // [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3 + // [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3 lda.z a clc adc.z b @@ -226,41 +231,43 @@ plus: { jmp __breturn // plus::@return __breturn: - // [12] return (byte) plus::return#0 - // [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1 + // [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [14] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [6] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement stackpull((number) 1) always clobbers reg byte a +Statement [7] (byte~) main::$0 ← stackpull(byte) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a +Statement [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte a as potential for zp[1]:3 [ plus::a#0 ] Removing always clobbered register reg byte x as potential for zp[1]:3 [ plus::a#0 ] -Statement [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a -Statement [12] return (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x +Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [6] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a -Statement [12] return (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x +Statement stackpull((number) 1) always clobbers reg byte a +Statement [7] (byte~) main::$0 ← stackpull(byte) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a +Statement [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x Potential registers zp[1]:2 [ main::$0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:3 [ plus::a#0 ] : zp[1]:3 , reg byte y , Potential registers zp[1]:4 [ plus::b#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:5 [ plus::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [plus] 4: zp[1]:4 [ plus::b#0 ] 2: zp[1]:3 [ plus::a#0 ] 2: zp[1]:5 [ plus::return#0 ] -Uplift Scope [main] 2: zp[1]:2 [ main::$0 ] +Uplift Scope [plus] 4: zp[1]:4 [ plus::b#0 ] 4: zp[1]:5 [ plus::return#0 ] 2: zp[1]:3 [ plus::a#0 ] +Uplift Scope [main] 4: zp[1]:2 [ main::$0 ] Uplift Scope [] -Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] zp[1]:3 [ plus::a#0 ] reg byte a [ plus::return#0 ] +Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:3 [ plus::a#0 ] Uplifting [main] best 85 combination reg byte a [ main::$0 ] Uplifting [] best 85 combination Attempting to uplift remaining variables inzp[1]:3 [ plus::a#0 ] @@ -301,16 +308,16 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [6] (byte~) main::$0 ← callfinalize plus -- vbuaa=_stackpullbyte_ + // [7] (byte~) main::$0 ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla - // [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa + // [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa sta SCREEN jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts } // plus @@ -320,23 +327,23 @@ plus: { .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 .label a = 2 - // [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + // [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x - // [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + // [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa clc adc.z a jmp __breturn // plus::@return __breturn: - // [12] return (byte) plus::return#0 - // [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + // [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [14] return rts } // File Data @@ -368,7 +375,7 @@ FINAL SYMBOL TABLE (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 (void()) main() -(byte~) main::$0 reg byte a 2.0 +(byte~) main::$0 reg byte a 4.0 (label) main::@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (label) plus::@return @@ -380,7 +387,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::b (byte) plus::b#0 reg byte a 4.0 (byte) plus::return -(byte) plus::return#0 reg byte a 2.0 +(byte) plus::return#0 reg byte a 4.0 reg byte a [ main::$0 ] zp[1]:2 [ plus::a#0 ] @@ -417,16 +424,16 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [6] (byte~) main::$0 ← callfinalize plus -- vbuaa=_stackpullbyte_ + // [7] (byte~) main::$0 ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla // SCREEN[0] = plus('0', 7) - // [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa + // [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa sta SCREEN // main::@return // } - // [8] return + // [9] return rts } // plus @@ -436,23 +443,23 @@ plus: { .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 .label a = 2 - // [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + // [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // return a+b; - // [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + // [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa clc adc.z a // plus::@return // } - // [12] return (byte) plus::return#0 - // [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + // [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [14] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-0.sym b/src/test/ref/procedure-callingconvention-stack-0.sym index 176d2a699..304e9cb44 100644 --- a/src/test/ref/procedure-callingconvention-stack-0.sym +++ b/src/test/ref/procedure-callingconvention-stack-0.sym @@ -4,7 +4,7 @@ (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 (void()) main() -(byte~) main::$0 reg byte a 2.0 +(byte~) main::$0 reg byte a 4.0 (label) main::@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (label) plus::@return @@ -16,7 +16,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::b (byte) plus::b#0 reg byte a 4.0 (byte) plus::return -(byte) plus::return#0 reg byte a 2.0 +(byte) plus::return#0 reg byte a 4.0 reg byte a [ main::$0 ] zp[1]:2 [ plus::a#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-1.cfg b/src/test/ref/procedure-callingconvention-stack-1.cfg index 1ec9e63e9..5f27ebb47 100644 --- a/src/test/ref/procedure-callingconvention-stack-1.cfg +++ b/src/test/ref/procedure-callingconvention-stack-1.cfg @@ -12,19 +12,21 @@ main: scope:[main] from @1 [4] callprepare plus (byte) '0' (byte) 7 [5] callexecute plus - [6] (byte~) main::$0 ← callfinalize plus - [7] *((const byte*) SCREEN) ← (byte~) main::$0 + stackpull((number) 1) + [7] (byte~) main::$0 ← stackpull(byte) + [8] *((const byte*) SCREEN) ← (byte~) main::$0 to:main::@return main::@return: scope:[main] from main - [8] return + [9] return to:@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) - [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 + [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) + [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) + [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [12] return (byte) plus::return#0 + [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 + [14] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-1.log b/src/test/ref/procedure-callingconvention-stack-1.log index d85baac91..ab6ad9428 100644 --- a/src/test/ref/procedure-callingconvention-stack-1.log +++ b/src/test/ref/procedure-callingconvention-stack-1.log @@ -3,6 +3,8 @@ Culled Empty Block (label) plus::@1 Calling convention STACK_CALL adding prepare/execute/finalize for (byte~) main::$0 ← call plus (byte) '0' (number) 7 Calling convention STACK_CALL replacing param((byte) plus::a) with stackidx(byte,(const byte) plus::OFFSET_STACK_A) Calling convention STACK_CALL replacing param((byte) plus::b) with stackidx(byte,(const byte) plus::OFFSET_STACK_B) +Calling convention STACK_CALL adding stack return stackidx(byte,plus::OFFSET_STACK_RETURN) ← plus::return +Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(byte) CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -12,7 +14,8 @@ CONTROL FLOW GRAPH SSA main: scope:[main] from @2 callprepare plus (byte) '0' (number) 7 callexecute plus - (byte~) main::$0 ← callfinalize plus + stackpull((number) 1) + (byte~) main::$0 ← stackpull(byte) *((const byte*) SCREEN + (number) 0) ← (byte~) main::$0 to:main::@return main::@return: scope:[main] from main @@ -28,7 +31,8 @@ plus: scope:[plus] from to:plus::@return plus::@return: scope:[plus] from plus (byte) plus::return#1 ← phi( plus/(byte) plus::return#0 ) - return (byte) plus::return#1 + stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#1 + return to:@return @2: scope:[] from @begin call main @@ -73,10 +77,8 @@ Finalized unsigned number type (byte) 0 Successful SSA optimization PassNFinalizeNumberTypeConversions Alias (byte) plus::return#0 = (byte~) plus::$0 (byte) plus::return#1 Successful SSA optimization Pass2AliasElimination -Simplifying expression containing zero SCREEN in [3] *((const byte*) SCREEN + (byte) 0) ← (byte~) main::$0 +Simplifying expression containing zero SCREEN in [4] *((const byte*) SCREEN + (byte) 0) ← (byte~) main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN -Successful SSA optimization PassNEliminateUnusedVars Adding NOP phi() at start of @begin Adding NOP phi() at start of @2 Adding NOP phi() at start of @3 @@ -108,34 +110,36 @@ FINAL CONTROL FLOW GRAPH main: scope:[main] from @1 [4] callprepare plus (byte) '0' (byte) 7 [5] callexecute plus - [6] (byte~) main::$0 ← callfinalize plus - [7] *((const byte*) SCREEN) ← (byte~) main::$0 + stackpull((number) 1) + [7] (byte~) main::$0 ← stackpull(byte) + [8] *((const byte*) SCREEN) ← (byte~) main::$0 to:main::@return main::@return: scope:[main] from main - [8] return + [9] return to:@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) - [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 + [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) + [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) + [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [12] return (byte) plus::return#0 + [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 + [14] return to:@return VARIABLE REGISTER WEIGHTS (void()) main() -(byte~) main::$0 2.0 +(byte~) main::$0 4.0 __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::a (byte) plus::a#0 2.0 (byte) plus::b (byte) plus::b#0 4.0 (byte) plus::return -(byte) plus::return#0 2.0 +(byte) plus::return#0 4.0 Initial phi equivalence classes Added variable main::$0 to live range equivalence class [ main::$0 ] @@ -188,18 +192,18 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [6] (byte~) main::$0 ← callfinalize plus -- vbuz1=_stackpullbyte_ + // [7] (byte~) main::$0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla sta.z __0 - // [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1 + // [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuz1 lda.z __0 sta SCREEN jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts } // plus @@ -207,18 +211,19 @@ main: { plus: { .const OFFSET_STACK_A = 1 .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN = 1 .label a = 3 .label b = 4 .label return = 5 - // [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1 + // [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b - // [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3 + // [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3 lda.z a clc adc.z b @@ -226,41 +231,43 @@ plus: { jmp __breturn // plus::@return __breturn: - // [12] return (byte) plus::return#0 - // [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1 + // [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [14] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [6] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement stackpull((number) 1) always clobbers reg byte a +Statement [7] (byte~) main::$0 ← stackpull(byte) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a +Statement [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte a as potential for zp[1]:3 [ plus::a#0 ] Removing always clobbered register reg byte x as potential for zp[1]:3 [ plus::a#0 ] -Statement [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a -Statement [12] return (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x +Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [6] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a -Statement [12] return (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x +Statement stackpull((number) 1) always clobbers reg byte a +Statement [7] (byte~) main::$0 ← stackpull(byte) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a +Statement [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte x Potential registers zp[1]:2 [ main::$0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:3 [ plus::a#0 ] : zp[1]:3 , reg byte y , Potential registers zp[1]:4 [ plus::b#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:5 [ plus::return#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [plus] 4: zp[1]:4 [ plus::b#0 ] 2: zp[1]:3 [ plus::a#0 ] 2: zp[1]:5 [ plus::return#0 ] -Uplift Scope [main] 2: zp[1]:2 [ main::$0 ] +Uplift Scope [plus] 4: zp[1]:4 [ plus::b#0 ] 4: zp[1]:5 [ plus::return#0 ] 2: zp[1]:3 [ plus::a#0 ] +Uplift Scope [main] 4: zp[1]:2 [ main::$0 ] Uplift Scope [] -Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] zp[1]:3 [ plus::a#0 ] reg byte a [ plus::return#0 ] +Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:3 [ plus::a#0 ] Uplifting [main] best 85 combination reg byte a [ main::$0 ] Uplifting [] best 85 combination Attempting to uplift remaining variables inzp[1]:3 [ plus::a#0 ] @@ -301,16 +308,16 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [6] (byte~) main::$0 ← callfinalize plus -- vbuaa=_stackpullbyte_ + // [7] (byte~) main::$0 ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla - // [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa + // [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa sta SCREEN jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts } // plus @@ -320,23 +327,23 @@ plus: { .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 .label a = 2 - // [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + // [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x - // [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + // [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa clc adc.z a jmp __breturn // plus::@return __breturn: - // [12] return (byte) plus::return#0 - // [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + // [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [14] return rts } // File Data @@ -368,7 +375,7 @@ FINAL SYMBOL TABLE (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 (void()) main() -(byte~) main::$0 reg byte a 2.0 +(byte~) main::$0 reg byte a 4.0 (label) main::@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (label) plus::@return @@ -380,7 +387,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::b (byte) plus::b#0 reg byte a 4.0 (byte) plus::return -(byte) plus::return#0 reg byte a 2.0 +(byte) plus::return#0 reg byte a 4.0 reg byte a [ main::$0 ] zp[1]:2 [ plus::a#0 ] @@ -417,16 +424,16 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (byte~) main::$0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [6] (byte~) main::$0 ← callfinalize plus -- vbuaa=_stackpullbyte_ + // [7] (byte~) main::$0 ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla // SCREEN[0] = plus('0', 7) - // [7] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa + // [8] *((const byte*) SCREEN) ← (byte~) main::$0 -- _deref_pbuc1=vbuaa sta SCREEN // main::@return // } - // [8] return + // [9] return rts } // plus @@ -436,23 +443,23 @@ plus: { .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 .label a = 2 - // [9] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [10] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [10] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + // [11] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // return a+b; - // [11] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + // [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa clc adc.z a // plus::@return // } - // [12] return (byte) plus::return#0 - // [12] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + // [13] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [14] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-1.sym b/src/test/ref/procedure-callingconvention-stack-1.sym index 176d2a699..304e9cb44 100644 --- a/src/test/ref/procedure-callingconvention-stack-1.sym +++ b/src/test/ref/procedure-callingconvention-stack-1.sym @@ -4,7 +4,7 @@ (const byte*) SCREEN = (byte*) 1024 (const word) STACK_BASE = (word) $103 (void()) main() -(byte~) main::$0 reg byte a 2.0 +(byte~) main::$0 reg byte a 4.0 (label) main::@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (label) plus::@return @@ -16,7 +16,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::b (byte) plus::b#0 reg byte a 4.0 (byte) plus::return -(byte) plus::return#0 reg byte a 2.0 +(byte) plus::return#0 reg byte a 4.0 reg byte a [ main::$0 ] zp[1]:2 [ plus::a#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-10.asm b/src/test/ref/procedure-callingconvention-stack-10.asm index 9e9bfea9d..d056fd49d 100644 --- a/src/test/ref/procedure-callingconvention-stack-10.asm +++ b/src/test/ref/procedure-callingconvention-stack-10.asm @@ -6,7 +6,6 @@ .label SCREEN = $400 .const OFFSET_STRUCT_POINT_Y = 1 .const STACK_BASE = $103 - .const OFFSET_STRUCT_POINT_X = 0 .label idx = 2 __bbegin: // idx = 0 @@ -43,8 +42,7 @@ print: { // get(byte register(X) i) get: { .const OFFSET_STACK_I = 0 - .const OFFSET_STACK_RETURN = 0 - .label p = 8 + .label p = 6 tsx lda STACK_BASE+OFFSET_STACK_I,x tax @@ -55,21 +53,19 @@ get: { stx.z p sta p+OFFSET_STRUCT_POINT_Y // return p; - txa - ldy p+OFFSET_STRUCT_POINT_Y + tay // } + txa tsx - sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X,x + sta STACK_BASE+0,x tya tsx - sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y,x + sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x rts } main: { .label i = 3 - .label p = 6 - .label __1_x = 4 - .label __1_y = 5 + .label p = 4 // i=0 lda #0 sta.z i @@ -87,16 +83,13 @@ main: { pha jsr get pla - sta.z __1_x + tax pla - sta.z __1_y // p = get(i) - lda.z __1_x - sta.z p - lda.z __1_y + stx.z p sta p+OFFSET_STRUCT_POINT_Y // print(p) - lda.z p + txa pha lda p+OFFSET_STRUCT_POINT_Y pha diff --git a/src/test/ref/procedure-callingconvention-stack-10.cfg b/src/test/ref/procedure-callingconvention-stack-10.cfg index 628e983df..292ca676a 100644 --- a/src/test/ref/procedure-callingconvention-stack-10.cfg +++ b/src/test/ref/procedure-callingconvention-stack-10.cfg @@ -4,55 +4,57 @@ @1: scope:[] from @begin [1] callprepare main [2] callexecute main - [3] callfinalize main to:@end @end: scope:[] from @1 - [4] phi() + [3] phi() __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) print: scope:[print] from - [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) - [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) - [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 - [8] (byte) idx ← ++ (byte) idx - [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 - [10] (byte) idx ← ++ (byte) idx + [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) + [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) + [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 + [7] (byte) idx ← ++ (byte) idx + [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 + [9] (byte) idx ← ++ (byte) idx to:print::@return print::@return: scope:[print] from print - [11] return + [10] return to:@return __stackcall (struct Point()) get((byte) get::i) get: scope:[get] from - [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) - [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 - [14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 - [15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 - [16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) - [17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) + [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) + [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 + [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 + [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 + [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) + [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) to:get::@return get::@return: scope:[get] from get - [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } + [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 + [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 + [19] return to:@return __stackcall (void()) main() main: scope:[main] from - [19] (byte) main::i ← (byte) 0 + [20] (byte) main::i ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@2 - [20] if((byte) main::i<(byte) 5) goto main::@2 + [21] if((byte) main::i<(byte) 5) goto main::@2 to:main::@return main::@return: scope:[main] from main::@1 - [21] return + [22] return to:@return main::@2: scope:[main] from main::@1 - [22] callprepare get (byte) main::i - [23] callexecute get - [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get - [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x - [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y - [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) - [28] callexecute print - [29] callfinalize print - [30] (byte) main::i ← ++ (byte) main::i + [23] callprepare get (byte) main::i + [24] callexecute get + [25] (byte~) main::$1_x ← stackpull(byte) + [26] (byte~) main::$1_y ← stackpull(byte) + [27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x + [28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y + [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) + [30] callexecute print + stackpull((number) 2) + [32] (byte) main::i ← ++ (byte) main::i to:main::@1 diff --git a/src/test/ref/procedure-callingconvention-stack-10.log b/src/test/ref/procedure-callingconvention-stack-10.log index 96446658c..75d44d887 100644 --- a/src/test/ref/procedure-callingconvention-stack-10.log +++ b/src/test/ref/procedure-callingconvention-stack-10.log @@ -39,6 +39,10 @@ Calling convention STACK_CALL adding prepare/execute/finalize for call main Calling convention STACK_CALL replacing param((byte) get::i) with stackidx(byte,(const byte) get::OFFSET_STACK_I) Calling convention STACK_CALL replacing param((byte) print::p_x) with stackidx(byte,(const byte) print::OFFSET_STACK_P_X) Calling convention STACK_CALL replacing param((byte) print::p_y) with stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) +Calling convention STACK_CALL adding stack return stackidx(byte,get::OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X) ← get::return_x +Calling convention STACK_CALL adding stack return stackidx(byte,get::OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y) ← get::return_y +Calling convention STACK_CALL adding stack pull main::$1_x ← stackpull(byte) +Calling convention STACK_CALL adding stack pull main::$1_y ← stackpull(byte) CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -56,13 +60,14 @@ main::@1: scope:[main] from main main::@2 main::@2: scope:[main] from main::@1 callprepare get (byte) main::i callexecute get - { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get + (byte~) main::$1_x ← stackpull(byte) + (byte~) main::$1_y ← stackpull(byte) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y (struct Point) main::p ← struct-unwound {*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)} callprepare print *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) callexecute print - callfinalize print + stackpull((number) 2) (byte) main::i ← ++ (byte) main::i to:main::@1 main::@return: scope:[main] from main::@1 @@ -83,7 +88,9 @@ get: scope:[get] from get::@return: scope:[get] from get (byte) get::return_y#1 ← phi( get/(byte) get::return_y#0 ) (byte) get::return_x#1 ← phi( get/(byte) get::return_x#0 ) - return { (byte) get::return_x#1, (byte) get::return_y#1 } + stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_x#1 + stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#1 + return to:@return __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) @@ -101,7 +108,6 @@ print::@return: scope:[print] from print @3: scope:[] from @begin callprepare main callexecute main - callfinalize main to:@end @end: scope:[] from @3 @@ -167,23 +173,26 @@ Alias (byte) get::return_y#0 = (byte) get::return_y#1 Successful SSA optimization Pass2AliasElimination Simple Condition (bool~) main::$0 [3] if((byte) main::i<(byte) 5) goto main::@2 Successful SSA optimization Pass2ConditionalJumpSimplification -Removing C-classic struct-unwound assignment [9] (struct Point) main::p ← struct-unwound {*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)} -Removing C-classic struct-unwound assignment [19] (struct Point) get::p ← struct-unwound {*((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)} -Simplifying expression containing zero (byte*)&main::p in [7] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x -Simplifying expression containing zero (byte*)&main::p in [10] callprepare print *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) -Simplifying expression containing zero (byte*)&get::p in [17] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i#0 -Simplifying expression containing zero (byte*)&get::p in [20] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) +Removing C-classic struct-unwound assignment [10] (struct Point) main::p ← struct-unwound {*((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y)} +Removing C-classic struct-unwound assignment [20] (struct Point) get::p ← struct-unwound {*((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X), *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y)} +Simplifying constant evaluating to zero (const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X in [24] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::return_x#0 +Successful SSA optimization PassNSimplifyConstantZero +Simplifying expression containing zero (byte*)&main::p in [8] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte~) main::$1_x +Simplifying expression containing zero (byte*)&main::p in [11] callprepare print *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_X) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) +Simplifying expression containing zero (byte*)&get::p in [18] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) ← (byte) get::i#0 +Simplifying expression containing zero (byte*)&get::p in [21] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_X) +Simplifying expression containing zero OFFSET_STRUCT_POINT_Y in [25] stackidx(byte,(const byte) get::OFFSET_STACK_RETURN+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (struct Point) get::return#0 and assignment [19] (struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#0, (byte) get::return_y#0} +Eliminating unused variable (struct Point) get::return#0 and assignment [20] (struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#0, (byte) get::return_y#0} Eliminating unused constant (const byte) get::OFFSET_STACK_RETURN Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X Successful SSA optimization PassNEliminateUnusedVars -Rewriting division to use shift [14] (byte~) get::$0 ← (byte) get::i#0 / (byte) 2 +Rewriting division to use shift [15] (byte~) get::$0 ← (byte) get::i#0 / (byte) 2 Successful SSA optimization Pass2MultiplyToShiftRewriting Adding NOP phi() at start of @end CALL GRAPH Calls in [] to main:2 -Calls in [main] to get:23 print:28 +Calls in [main] to get:24 print:30 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes @@ -197,57 +206,59 @@ FINAL CONTROL FLOW GRAPH @1: scope:[] from @begin [1] callprepare main [2] callexecute main - [3] callfinalize main to:@end @end: scope:[] from @1 - [4] phi() + [3] phi() __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) print: scope:[print] from - [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) - [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) - [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 - [8] (byte) idx ← ++ (byte) idx - [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 - [10] (byte) idx ← ++ (byte) idx + [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) + [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) + [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 + [7] (byte) idx ← ++ (byte) idx + [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 + [9] (byte) idx ← ++ (byte) idx to:print::@return print::@return: scope:[print] from print - [11] return + [10] return to:@return __stackcall (struct Point()) get((byte) get::i) get: scope:[get] from - [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) - [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 - [14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 - [15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 - [16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) - [17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) + [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) + [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 + [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 + [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 + [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) + [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) to:get::@return get::@return: scope:[get] from get - [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } + [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 + [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 + [19] return to:@return __stackcall (void()) main() main: scope:[main] from - [19] (byte) main::i ← (byte) 0 + [20] (byte) main::i ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@2 - [20] if((byte) main::i<(byte) 5) goto main::@2 + [21] if((byte) main::i<(byte) 5) goto main::@2 to:main::@return main::@return: scope:[main] from main::@1 - [21] return + [22] return to:@return main::@2: scope:[main] from main::@1 - [22] callprepare get (byte) main::i - [23] callexecute get - [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get - [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x - [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y - [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) - [28] callexecute print - [29] callfinalize print - [30] (byte) main::i ← ++ (byte) main::i + [23] callprepare get (byte) main::i + [24] callexecute get + [25] (byte~) main::$1_x ← stackpull(byte) + [26] (byte~) main::$1_y ← stackpull(byte) + [27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x + [28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y + [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) + [30] callexecute print + stackpull((number) 2) + [32] (byte) main::i ← ++ (byte) main::i to:main::@1 null depth in calling loop Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 in scope print @@ -263,14 +274,14 @@ __stackcall (struct Point()) get((byte) get::i) (struct Point) get::p loadstore (struct Point) get::return (byte) get::return_x -(byte) get::return_x#0 1.0 +(byte) get::return_x#0 2.0 (byte) get::return_y (byte) get::return_y#0 2.0 -(byte) idx loadstore 0.7 +(byte) idx loadstore 0.6666666666666666 __stackcall (void()) main() -(byte~) main::$1_x 0.8461538461538461 -(byte~) main::$1_y 0.8461538461538461 -(byte) main::i loadstore 3.1818181818181817 +(byte~) main::$1_x 11.0 +(byte~) main::$1_y 11.0 +(byte) main::i loadstore 2.9166666666666665 (struct Point) main::p loadstore __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (byte) print::p_x @@ -342,8 +353,7 @@ __b1: // [1] callprepare main // [2] callexecute main -- jsr jsr main - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end @@ -355,30 +365,30 @@ print: { .const OFFSET_STACK_P_Y = 0 .label p_x = 3 .label p_y = 4 - // [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuz1=_stackidxbyte_vbuc1 + // [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_P_X,x sta.z p_x - // [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuz1=_stackidxbyte_vbuc1 + // [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_P_Y,x sta.z p_y - // [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2 + // [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuz2 lda.z p_x ldy.z idx sta SCREEN,y - // [8] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 + // [7] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 inc.z idx - // [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuz2 + // [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuz2 lda.z p_y ldy.z idx sta SCREEN,y - // [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 + // [9] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 inc.z idx jmp __breturn // print::@return __breturn: - // [11] return + // [10] return rts } // get @@ -390,38 +400,38 @@ get: { .label i = 5 .label return_x = 7 .label return_y = 8 - // [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuz1=_stackidxbyte_vbuc1 + // [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x sta.z i - // [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuz1=vbuz2_ror_1 + // [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuz1=vbuz2_ror_1 lda.z i lsr sta.z __0 - // [14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuz1 + // [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuz1 lda.z i sta.z p - // [15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuz1 + // [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuz1 lda.z __0 sta p+OFFSET_STRUCT_POINT_Y - // [16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuz1=_deref_pbuc1 + // [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuz1=_deref_pbuc1 lda.z p sta.z return_x - // [17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1 + // [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuz1=_deref_pbuc1 lda p+OFFSET_STRUCT_POINT_Y sta.z return_y jmp __breturn // get::@return __breturn: - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::x#0] -- _stackidxbyte_vbuc1=vbuz1 + // [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_x tsx - sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X,x - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::y#1] -- _stackidxbyte_vbuc1=vbuz1 + sta STACK_BASE+0,x + // [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return_y tsx - sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y,x + sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x + // [19] return rts } // main @@ -430,142 +440,134 @@ main: { .label p = $c .label __1_x = $a .label __1_y = $b - // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + // [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: - // [20] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 jmp __breturn // main::@return __breturn: - // [21] return + // [22] return rts // main::@2 __b2: - // [22] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1 + // [23] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1 lda.z i pha - // [22] callprepare get (byte) main::i -- _stackpushbyte_1 + // [23] callprepare get (byte) main::i -- _stackpushbyte_1 pha - // [23] callexecute get -- jsr + // [24] callexecute get -- jsr jsr get - // [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::x#0] -- vbuz1=_stackpullbyte_ + // [25] (byte~) main::$1_x ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla sta.z __1_x - // [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::y#1] -- vbuz1=_stackpullbyte_ + // [26] (byte~) main::$1_y ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla sta.z __1_y - // [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1 + // [27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1 lda.z __1_x sta.z p - // [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1 + // [28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1 lda.z __1_y sta p+OFFSET_STRUCT_POINT_Y - // [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1 + // [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1 lda.z p pha - // [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1 + // [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1 lda p+OFFSET_STRUCT_POINT_Y pha - // [28] callexecute print -- jsr + // [30] callexecute print -- jsr jsr print - // [29] callfinalize print -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla - // [30] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::$1_x main::$1_y main::p ] ( [ idx get::p main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Removing always clobbered register reg byte a as potential for zp[1]:10 [ main::$1_x ] -Removing always clobbered register reg byte a as potential for zp[1]:11 [ main::$1_y ] -Statement [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x -Removing always clobbered register reg byte x as potential for zp[1]:10 [ main::$1_x ] -Removing always clobbered register reg byte x as potential for zp[1]:11 [ main::$1_y ] -Statement [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x +Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::p ] ( [ idx get::p main::p ] ) always clobbers reg byte a +Statement [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x +Statement [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte a as potential for zp[1]:3 [ print::p_x#0 ] Removing always clobbered register reg byte x as potential for zp[1]:3 [ print::p_x#0 ] -Statement [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y -Removing always clobbered register reg byte y as potential for zp[1]:10 [ main::$1_x ] -Removing always clobbered register reg byte y as potential for zp[1]:11 [ main::$1_y ] +Statement [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y Removing always clobbered register reg byte a as potential for zp[1]:4 [ print::p_y#0 ] Removing always clobbered register reg byte y as potential for zp[1]:4 [ print::p_y#0 ] -Statement [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx ] ) always clobbers reg byte a reg byte y -Statement [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x -Statement [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a +Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:30 [ get::p main::i main::p idx ] ) always clobbers reg byte a reg byte y +Statement [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:24 [ idx main::i main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x +Statement [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:24 [ idx main::i main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:5 [ get::i#0 ] -Statement [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [ get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::p ] ) always clobbers reg byte x -Statement [19] (byte) main::i ← (byte) 0 [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [20] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [22] callprepare get (byte) main::i [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [29] callfinalize print [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::$1_x main::$1_y main::p ] ( [ idx get::p main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x -Statement [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x -Statement [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y -Statement [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:28 [ get::p main::i main::$1_x main::$1_y main::p idx ] ) always clobbers reg byte a reg byte y -Statement [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x -Statement [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a -Statement [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [ get::p ] ( main:2::get:23 [ idx main::i main::$1_x main::$1_y main::p get::p ] ) always clobbers reg byte x -Statement [19] (byte) main::i ← (byte) 0 [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [20] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [22] callprepare get (byte) main::i [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a -Statement [29] callfinalize print [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a +Statement [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 [ get::p get::return_y#0 ] ( main:2::get:24 [ idx main::i main::p get::p get::return_y#0 ] ) always clobbers reg byte x +Removing always clobbered register reg byte x as potential for zp[1]:8 [ get::return_y#0 ] +Statement [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 [ get::p ] ( main:2::get:24 [ idx main::i main::p get::p ] ) always clobbers reg byte x +Statement [20] (byte) main::i ← (byte) 0 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement [21] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement [23] callprepare get (byte) main::i [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement [25] (byte~) main::$1_x ← stackpull(byte) [ idx get::p main::i main::$1_x main::p ] ( main:2 [ idx get::p main::i main::$1_x main::p ] ) always clobbers reg byte a +Statement [26] (byte~) main::$1_y ← stackpull(byte) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:10 [ main::$1_x ] +Statement [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement stackpull((number) 2) always clobbers reg byte a +Statement [0] (byte) idx ← (byte) 0 [ idx get::p main::p ] ( [ idx get::p main::p ] ) always clobbers reg byte a +Statement [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) [ idx print::p_x#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_x#0 ] ) always clobbers reg byte a reg byte x +Statement [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) [ idx print::p_x#0 print::p_y#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_x#0 print::p_y#0 ] ) always clobbers reg byte a reg byte x +Statement [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 [ idx print::p_y#0 ] ( main:2::print:30 [ get::p main::i main::p idx print::p_y#0 ] ) always clobbers reg byte a reg byte y +Statement [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 [ idx ] ( main:2::print:30 [ get::p main::i main::p idx ] ) always clobbers reg byte a reg byte y +Statement [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) [ get::i#0 get::p ] ( main:2::get:24 [ idx main::i main::p get::i#0 get::p ] ) always clobbers reg byte a reg byte x +Statement [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 [ get::i#0 get::$0 get::p ] ( main:2::get:24 [ idx main::i main::p get::i#0 get::$0 get::p ] ) always clobbers reg byte a +Statement [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 [ get::p get::return_y#0 ] ( main:2::get:24 [ idx main::i main::p get::p get::return_y#0 ] ) always clobbers reg byte x +Statement [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 [ get::p ] ( main:2::get:24 [ idx main::i main::p get::p ] ) always clobbers reg byte x +Statement [20] (byte) main::i ← (byte) 0 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement [21] if((byte) main::i<(byte) 5) goto main::@2 [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement [23] callprepare get (byte) main::i [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement [25] (byte~) main::$1_x ← stackpull(byte) [ idx get::p main::i main::$1_x main::p ] ( main:2 [ idx get::p main::i main::$1_x main::p ] ) always clobbers reg byte a +Statement [26] (byte~) main::$1_y ← stackpull(byte) [ idx get::p main::i main::$1_x main::$1_y main::p ] ( main:2 [ idx get::p main::i main::$1_x main::$1_y main::p ] ) always clobbers reg byte a +Statement [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [ idx get::p main::i main::p ] ( main:2 [ idx get::p main::i main::p ] ) always clobbers reg byte a +Statement stackpull((number) 2) always clobbers reg byte a Potential registers zp[1]:2 [ idx ] : zp[1]:2 , Potential registers zp[1]:3 [ print::p_x#0 ] : zp[1]:3 , reg byte y , Potential registers zp[1]:4 [ print::p_y#0 ] : zp[1]:4 , reg byte x , Potential registers zp[1]:5 [ get::i#0 ] : zp[1]:5 , reg byte x , reg byte y , Potential registers zp[1]:6 [ get::$0 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:7 [ get::return_x#0 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , -Potential registers zp[1]:8 [ get::return_y#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ get::return_y#0 ] : zp[1]:8 , reg byte a , reg byte y , Potential registers zp[1]:9 [ main::i ] : zp[1]:9 , -Potential registers zp[1]:10 [ main::$1_x ] : zp[1]:10 , -Potential registers zp[1]:11 [ main::$1_y ] : zp[1]:11 , +Potential registers zp[1]:10 [ main::$1_x ] : zp[1]:10 , reg byte x , reg byte y , +Potential registers zp[1]:11 [ main::$1_y ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , Potential registers zp[2]:12 [ main::p ] : zp[2]:12 , Potential registers zp[2]:14 [ get::p ] : zp[2]:14 , REGISTER UPLIFT SCOPES -Uplift Scope [get] 3: zp[1]:5 [ get::i#0 ] 2: zp[1]:6 [ get::$0 ] 2: zp[1]:8 [ get::return_y#0 ] 1: zp[1]:7 [ get::return_x#0 ] 0: zp[2]:14 [ get::p ] -Uplift Scope [main] 3.18: zp[1]:9 [ main::i ] 0.85: zp[1]:10 [ main::$1_x ] 0.85: zp[1]:11 [ main::$1_y ] 0: zp[2]:12 [ main::p ] +Uplift Scope [main] 11: zp[1]:10 [ main::$1_x ] 11: zp[1]:11 [ main::$1_y ] 2.92: zp[1]:9 [ main::i ] 0: zp[2]:12 [ main::p ] +Uplift Scope [get] 3: zp[1]:5 [ get::i#0 ] 2: zp[1]:6 [ get::$0 ] 2: zp[1]:7 [ get::return_x#0 ] 2: zp[1]:8 [ get::return_y#0 ] 0: zp[2]:14 [ get::p ] Uplift Scope [print] 2: zp[1]:3 [ print::p_x#0 ] 1.33: zp[1]:4 [ print::p_y#0 ] -Uplift Scope [] 0.7: zp[1]:2 [ idx ] +Uplift Scope [] 0.67: zp[1]:2 [ idx ] Uplift Scope [Point] -Uplifting [get] best 1016 combination reg byte x [ get::i#0 ] reg byte a [ get::$0 ] reg byte y [ get::return_y#0 ] reg byte a [ get::return_x#0 ] zp[2]:14 [ get::p ] -Limited combination testing to 100 combinations of 192 possible. -Uplifting [main] best 1016 combination zp[1]:9 [ main::i ] zp[1]:10 [ main::$1_x ] zp[1]:11 [ main::$1_y ] zp[2]:12 [ main::p ] -Uplifting [print] best 1012 combination reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ] -Uplifting [] best 1012 combination zp[1]:2 [ idx ] -Uplifting [Point] best 1012 combination +Uplifting [main] best 937 combination reg byte x [ main::$1_x ] reg byte a [ main::$1_y ] zp[1]:9 [ main::i ] zp[2]:12 [ main::p ] +Uplifting [get] best 922 combination reg byte x [ get::i#0 ] reg byte a [ get::$0 ] reg byte x [ get::return_x#0 ] zp[1]:8 [ get::return_y#0 ] zp[2]:14 [ get::p ] +Limited combination testing to 100 combinations of 144 possible. +Uplifting [print] best 918 combination reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ] +Uplifting [] best 918 combination zp[1]:2 [ idx ] +Uplifting [Point] best 918 combination Attempting to uplift remaining variables inzp[1]:9 [ main::i ] -Uplifting [main] best 1012 combination zp[1]:9 [ main::i ] -Attempting to uplift remaining variables inzp[1]:10 [ main::$1_x ] -Uplifting [main] best 1012 combination zp[1]:10 [ main::$1_x ] -Attempting to uplift remaining variables inzp[1]:11 [ main::$1_y ] -Uplifting [main] best 1012 combination zp[1]:11 [ main::$1_y ] +Uplifting [main] best 918 combination zp[1]:9 [ main::i ] +Attempting to uplift remaining variables inzp[1]:8 [ get::return_y#0 ] +Uplifting [get] best 914 combination reg byte y [ get::return_y#0 ] Attempting to uplift remaining variables inzp[1]:2 [ idx ] -Uplifting [] best 1012 combination zp[1]:2 [ idx ] +Uplifting [] best 914 combination zp[1]:2 [ idx ] Allocated (was zp[1]:9) zp[1]:3 [ main::i ] -Allocated (was zp[1]:10) zp[1]:4 [ main::$1_x ] -Allocated (was zp[1]:11) zp[1]:5 [ main::$1_y ] -Allocated (was zp[2]:12) zp[2]:6 [ main::p ] -Allocated (was zp[2]:14) zp[2]:8 [ get::p ] +Allocated (was zp[2]:12) zp[2]:4 [ main::p ] +Allocated (was zp[2]:14) zp[2]:6 [ get::p ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -579,7 +581,6 @@ ASSEMBLER BEFORE OPTIMIZATION .label SCREEN = $400 .const OFFSET_STRUCT_POINT_Y = 1 .const STACK_BASE = $103 - .const OFFSET_STRUCT_POINT_X = 0 .label idx = 2 // @begin __bbegin: @@ -592,8 +593,7 @@ __b1: // [1] callprepare main // [2] callexecute main -- jsr jsr main - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end @@ -603,120 +603,115 @@ __bend: print: { .const OFFSET_STACK_P_X = 1 .const OFFSET_STACK_P_Y = 0 - // [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuyy=_stackidxbyte_vbuc1 + // [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuyy=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_P_X,x tay - // [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuxx=_stackidxbyte_vbuc1 + // [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuxx=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_P_Y,x tax - // [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuyy + // [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuyy tya ldy.z idx sta SCREEN,y - // [8] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 + // [7] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 inc.z idx - // [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuxx + // [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuxx ldy.z idx txa sta SCREEN,y - // [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 + // [9] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 inc.z idx jmp __breturn // print::@return __breturn: - // [11] return + // [10] return rts } // get // get(byte register(X) i) get: { .const OFFSET_STACK_I = 0 - .const OFFSET_STACK_RETURN = 0 - .label p = 8 - // [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 + .label p = 6 + // [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x tax - // [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1 + // [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1 txa lsr - // [14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx + // [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx stx.z p - // [15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa + // [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa sta p+OFFSET_STRUCT_POINT_Y - // [16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuaa=_deref_pbuc1 - lda.z p - // [17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1 + // [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuxx=_deref_pbuc1 + ldx.z p + // [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1 ldy p+OFFSET_STRUCT_POINT_Y jmp __breturn // get::@return __breturn: - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::x#0] -- _stackidxbyte_vbuc1=vbuaa + // [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuxx + txa tsx - sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X,x - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::y#1] -- _stackidxbyte_vbuc1=vbuyy + sta STACK_BASE+0,x + // [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuyy tya tsx - sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y,x + sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x + // [19] return rts } // main main: { .label i = 3 - .label p = 6 - .label __1_x = 4 - .label __1_y = 5 - // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + .label p = 4 + // [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: - // [20] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 jmp __breturn // main::@return __breturn: - // [21] return + // [22] return rts // main::@2 __b2: - // [22] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1 + // [23] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1 lda.z i pha - // [22] callprepare get (byte) main::i -- _stackpushbyte_1 + // [23] callprepare get (byte) main::i -- _stackpushbyte_1 pha - // [23] callexecute get -- jsr + // [24] callexecute get -- jsr jsr get - // [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::x#0] -- vbuz1=_stackpullbyte_ + // [25] (byte~) main::$1_x ← stackpull(byte) -- vbuxx=_stackpullbyte_ pla - sta.z __1_x - // [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::y#1] -- vbuz1=_stackpullbyte_ + tax + // [26] (byte~) main::$1_y ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla - sta.z __1_y - // [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1 - lda.z __1_x - sta.z p - // [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1 - lda.z __1_y + // [27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx + stx.z p + // [28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa sta p+OFFSET_STRUCT_POINT_Y - // [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1 + // [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1 lda.z p pha - // [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1 + // [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1 lda p+OFFSET_STRUCT_POINT_Y pha - // [28] callexecute print -- jsr + // [30] callexecute print -- jsr jsr print - // [29] callfinalize print -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla - // [30] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } @@ -730,7 +725,10 @@ Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination +Removing instruction ldx.z p +Replacing instruction ldy p+OFFSET_STRUCT_POINT_Y with TAY Replacing instruction lda.z p with TXA +Succesful ASM optimization Pass5UnnecesaryLoadElimination Removing instruction __bend_from___b1: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __b1: @@ -746,7 +744,6 @@ FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end -(const byte) OFFSET_STRUCT_POINT_X = (byte) 0 (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (byte) Point::x loadstore (byte) Point::y loadstore @@ -756,24 +753,23 @@ __stackcall (struct Point()) get((byte) get::i) (byte~) get::$0 reg byte a 2.0 (label) get::@return (const byte) get::OFFSET_STACK_I = (byte) 0 -(const byte) get::OFFSET_STACK_RETURN = (byte) 0 (byte) get::i (byte) get::i#0 reg byte x 3.0 -(struct Point) get::p loadstore zp[2]:8 +(struct Point) get::p loadstore zp[2]:6 (struct Point) get::return (byte) get::return_x -(byte) get::return_x#0 reg byte a 1.0 +(byte) get::return_x#0 reg byte x 2.0 (byte) get::return_y (byte) get::return_y#0 reg byte y 2.0 -(byte) idx loadstore zp[1]:2 0.7 +(byte) idx loadstore zp[1]:2 0.6666666666666666 __stackcall (void()) main() -(byte~) main::$1_x zp[1]:4 0.8461538461538461 -(byte~) main::$1_y zp[1]:5 0.8461538461538461 +(byte~) main::$1_x reg byte x 11.0 +(byte~) main::$1_y reg byte a 11.0 (label) main::@1 (label) main::@2 (label) main::@return -(byte) main::i loadstore zp[1]:3 3.1818181818181817 -(struct Point) main::p loadstore zp[2]:6 +(byte) main::i loadstore zp[1]:3 2.9166666666666665 +(struct Point) main::p loadstore zp[2]:4 __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (label) print::@return (const byte) print::OFFSET_STACK_P_X = (byte) 1 @@ -788,17 +784,17 @@ reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ] reg byte x [ get::i#0 ] reg byte a [ get::$0 ] -reg byte a [ get::return_x#0 ] +reg byte x [ get::return_x#0 ] reg byte y [ get::return_y#0 ] zp[1]:3 [ main::i ] -zp[1]:4 [ main::$1_x ] -zp[1]:5 [ main::$1_y ] -zp[2]:6 [ main::p ] -zp[2]:8 [ get::p ] +reg byte x [ main::$1_x ] +reg byte a [ main::$1_y ] +zp[2]:4 [ main::p ] +zp[2]:6 [ get::p ] FINAL ASSEMBLER -Score: 972 +Score: 860 // File Comments // Test a procedure with calling convention stack @@ -811,7 +807,6 @@ Score: 972 .label SCREEN = $400 .const OFFSET_STRUCT_POINT_Y = 1 .const STACK_BASE = $103 - .const OFFSET_STRUCT_POINT_X = 0 .label idx = 2 // @begin __bbegin: @@ -824,8 +819,7 @@ __bbegin: // [2] callexecute main -- jsr jsr main rts - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] // @end // print // print(byte register(Y) p_x, byte register(X) p_y) @@ -833,129 +827,123 @@ print: { .const OFFSET_STACK_P_X = 1 .const OFFSET_STACK_P_Y = 0 // } - // [5] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuyy=_stackidxbyte_vbuc1 + // [4] (byte) print::p_x#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_X) -- vbuyy=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_P_X,x tay - // [6] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuxx=_stackidxbyte_vbuc1 + // [5] (byte) print::p_y#0 ← stackidx(byte,(const byte) print::OFFSET_STACK_P_Y) -- vbuxx=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_P_Y,x tax // SCREEN[idx++] = p.x - // [7] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuyy + // [6] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_x#0 -- pbuc1_derefidx_vbuz1=vbuyy tya ldy.z idx sta SCREEN,y // SCREEN[idx++] = p.x; - // [8] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 + // [7] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 inc.z idx // SCREEN[idx++] = p.y - // [9] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuxx + // [8] *((const byte*) SCREEN + (byte) idx) ← (byte) print::p_y#0 -- pbuc1_derefidx_vbuz1=vbuxx ldy.z idx txa sta SCREEN,y // SCREEN[idx++] = p.y; - // [10] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 + // [9] (byte) idx ← ++ (byte) idx -- vbuz1=_inc_vbuz1 inc.z idx // print::@return // } - // [11] return + // [10] return rts } // get // get(byte register(X) i) get: { .const OFFSET_STACK_I = 0 - .const OFFSET_STACK_RETURN = 0 - .label p = 8 - // [12] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 + .label p = 6 + // [11] (byte) get::i#0 ← stackidx(byte,(const byte) get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_I,x tax // i/2 - // [13] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1 + // [12] (byte~) get::$0 ← (byte) get::i#0 >> (byte) 1 -- vbuaa=vbuxx_ror_1 txa lsr // p = { i, i/2 } - // [14] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx + // [13] *((byte*)&(struct Point) get::p) ← (byte) get::i#0 -- _deref_pbuc1=vbuxx stx.z p - // [15] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa + // [14] *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) get::$0 -- _deref_pbuc1=vbuaa sta p+OFFSET_STRUCT_POINT_Y // return p; - // [16] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuaa=_deref_pbuc1 - txa - // [17] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1 - ldy p+OFFSET_STRUCT_POINT_Y + // [15] (byte) get::return_x#0 ← *((byte*)&(struct Point) get::p) -- vbuxx=_deref_pbuc1 + // [16] (byte) get::return_y#0 ← *((byte*)&(struct Point) get::p+(const byte) OFFSET_STRUCT_POINT_Y) -- vbuyy=_deref_pbuc1 + tay // get::@return // } - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::x#0] -- _stackidxbyte_vbuc1=vbuaa + // [17] stackidx(byte,(byte) 0) ← (byte) get::return_x#0 -- _stackidxbyte_vbuc1=vbuxx + txa tsx - sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_X,x - // [18] return { (byte) get::return_x#0, (byte) get::return_y#0 } [(byte) Point::y#1] -- _stackidxbyte_vbuc1=vbuyy + sta STACK_BASE+0,x + // [18] stackidx(byte,(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) get::return_y#0 -- _stackidxbyte_vbuc1=vbuyy tya tsx - sta STACK_BASE+OFFSET_STACK_RETURN+OFFSET_STRUCT_POINT_Y,x + sta STACK_BASE+OFFSET_STRUCT_POINT_Y,x + // [19] return rts } // main main: { .label i = 3 - .label p = 6 - .label __1_x = 4 - .label __1_y = 5 + .label p = 4 // i=0 - // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + // [20] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i // main::@1 __b1: // for(char i=0;i<5;i++) - // [20] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + // [21] if((byte) main::i<(byte) 5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #5 bcc __b2 // main::@return // } - // [21] return + // [22] return rts // main::@2 __b2: // get(i) - // [22] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1 + // [23] callprepare get (byte) main::i [(byte) get::i#0] -- _stackpushbyte_=vbuz1 lda.z i pha - // [22] callprepare get (byte) main::i -- _stackpushbyte_1 + // [23] callprepare get (byte) main::i -- _stackpushbyte_1 pha - // [23] callexecute get -- jsr + // [24] callexecute get -- jsr jsr get - // [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::x#0] -- vbuz1=_stackpullbyte_ + // [25] (byte~) main::$1_x ← stackpull(byte) -- vbuxx=_stackpullbyte_ pla - sta.z __1_x - // [24] { (byte~) main::$1_x, (byte~) main::$1_y } ← callfinalize get [(byte) Point::y#1] -- vbuz1=_stackpullbyte_ + tax + // [26] (byte~) main::$1_y ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla - sta.z __1_y // p = get(i) - // [25] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuz1 - lda.z __1_x - sta.z p - // [26] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuz1 - lda.z __1_y + // [27] *((byte*)&(struct Point) main::p) ← (byte~) main::$1_x -- _deref_pbuc1=vbuxx + stx.z p + // [28] *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte~) main::$1_y -- _deref_pbuc1=vbuaa sta p+OFFSET_STRUCT_POINT_Y // print(p) - // [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1 - lda.z p + // [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_x#0] -- _stackpushbyte_=_deref_pbuc1 + txa pha - // [27] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1 + // [29] callprepare print *((byte*)&(struct Point) main::p) *((byte*)&(struct Point) main::p+(const byte) OFFSET_STRUCT_POINT_Y) [(byte) print::p_y#1] -- _stackpushbyte_=_deref_pbuc1 lda p+OFFSET_STRUCT_POINT_Y pha - // [28] callexecute print -- jsr + // [30] callexecute print -- jsr jsr print - // [29] callfinalize print -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla // for(char i=0;i<5;i++) - // [30] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } diff --git a/src/test/ref/procedure-callingconvention-stack-10.sym b/src/test/ref/procedure-callingconvention-stack-10.sym index 92a7518a9..7f5036206 100644 --- a/src/test/ref/procedure-callingconvention-stack-10.sym +++ b/src/test/ref/procedure-callingconvention-stack-10.sym @@ -1,7 +1,6 @@ (label) @1 (label) @begin (label) @end -(const byte) OFFSET_STRUCT_POINT_X = (byte) 0 (const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 (byte) Point::x loadstore (byte) Point::y loadstore @@ -11,24 +10,23 @@ __stackcall (struct Point()) get((byte) get::i) (byte~) get::$0 reg byte a 2.0 (label) get::@return (const byte) get::OFFSET_STACK_I = (byte) 0 -(const byte) get::OFFSET_STACK_RETURN = (byte) 0 (byte) get::i (byte) get::i#0 reg byte x 3.0 -(struct Point) get::p loadstore zp[2]:8 +(struct Point) get::p loadstore zp[2]:6 (struct Point) get::return (byte) get::return_x -(byte) get::return_x#0 reg byte a 1.0 +(byte) get::return_x#0 reg byte x 2.0 (byte) get::return_y (byte) get::return_y#0 reg byte y 2.0 -(byte) idx loadstore zp[1]:2 0.7 +(byte) idx loadstore zp[1]:2 0.6666666666666666 __stackcall (void()) main() -(byte~) main::$1_x zp[1]:4 0.8461538461538461 -(byte~) main::$1_y zp[1]:5 0.8461538461538461 +(byte~) main::$1_x reg byte x 11.0 +(byte~) main::$1_y reg byte a 11.0 (label) main::@1 (label) main::@2 (label) main::@return -(byte) main::i loadstore zp[1]:3 3.1818181818181817 -(struct Point) main::p loadstore zp[2]:6 +(byte) main::i loadstore zp[1]:3 2.9166666666666665 +(struct Point) main::p loadstore zp[2]:4 __stackcall (void()) print((byte) print::p_x , (byte) print::p_y) (label) print::@return (const byte) print::OFFSET_STACK_P_X = (byte) 1 @@ -43,10 +41,10 @@ reg byte y [ print::p_x#0 ] reg byte x [ print::p_y#0 ] reg byte x [ get::i#0 ] reg byte a [ get::$0 ] -reg byte a [ get::return_x#0 ] +reg byte x [ get::return_x#0 ] reg byte y [ get::return_y#0 ] zp[1]:3 [ main::i ] -zp[1]:4 [ main::$1_x ] -zp[1]:5 [ main::$1_y ] -zp[2]:6 [ main::p ] -zp[2]:8 [ get::p ] +reg byte x [ main::$1_x ] +reg byte a [ main::$1_y ] +zp[2]:4 [ main::p ] +zp[2]:6 [ get::p ] diff --git a/src/test/ref/procedure-callingconvention-stack-2.cfg b/src/test/ref/procedure-callingconvention-stack-2.cfg index 9d8df073a..bf5a14389 100644 --- a/src/test/ref/procedure-callingconvention-stack-2.cfg +++ b/src/test/ref/procedure-callingconvention-stack-2.cfg @@ -12,19 +12,21 @@ main: scope:[main] from @1 [4] callprepare plus (word) $1234 (word) $2345 [5] callexecute plus - [6] (word~) main::$0 ← callfinalize plus - [7] *((const word*) SCREEN) ← (word~) main::$0 + stackpull((number) 2) + [7] (word~) main::$0 ← stackpull(word) + [8] *((const word*) SCREEN) ← (word~) main::$0 to:main::@return main::@return: scope:[main] from main - [8] return + [9] return to:@return __stackcall (word()) plus((word) plus::a , (word) plus::b) plus: scope:[plus] from - [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) - [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) - [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 + [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) + [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) + [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [12] return (word) plus::return#0 + [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 + [14] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-2.log b/src/test/ref/procedure-callingconvention-stack-2.log index cd8e9e00f..6f8841d93 100644 --- a/src/test/ref/procedure-callingconvention-stack-2.log +++ b/src/test/ref/procedure-callingconvention-stack-2.log @@ -4,6 +4,8 @@ Culled Empty Block (label) plus::@1 Calling convention STACK_CALL adding prepare/execute/finalize for (word~) main::$0 ← call plus (number) $1234 (number) $2345 Calling convention STACK_CALL replacing param((word) plus::a) with stackidx(word,(const byte) plus::OFFSET_STACK_A) Calling convention STACK_CALL replacing param((word) plus::b) with stackidx(word,(const byte) plus::OFFSET_STACK_B) +Calling convention STACK_CALL adding stack return stackidx(word,plus::OFFSET_STACK_RETURN) ← plus::return +Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(word) CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -13,7 +15,8 @@ CONTROL FLOW GRAPH SSA main: scope:[main] from @2 callprepare plus (number) $1234 (number) $2345 callexecute plus - (word~) main::$0 ← callfinalize plus + stackpull((number) 2) + (word~) main::$0 ← stackpull(word) (number~) main::$1 ← (number) 0 * (const byte) SIZEOF_WORD *((const word*) SCREEN + (number~) main::$1) ← (word~) main::$0 to:main::@return @@ -30,7 +33,8 @@ plus: scope:[plus] from to:plus::@return plus::@return: scope:[plus] from plus (word) plus::return#1 ← phi( plus/(word) plus::return#0 ) - return (word) plus::return#1 + stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#1 + return to:@return @2: scope:[] from @begin call main @@ -82,16 +86,15 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions Inferred type updated to byte in (unumber~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD Alias (word) plus::return#0 = (word~) plus::$0 (word) plus::return#1 Successful SSA optimization Pass2AliasElimination -Constant right-side identified [3] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD +Constant right-side identified [4] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::$1 = 0*SIZEOF_WORD Successful SSA optimization Pass2ConstantIdentification Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_WORD in Successful SSA optimization PassNSimplifyConstantZero -Simplifying expression containing zero SCREEN in [4] *((const word*) SCREEN + (const byte) main::$1) ← (word~) main::$0 +Simplifying expression containing zero SCREEN in [5] *((const word*) SCREEN + (const byte) main::$1) ← (word~) main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused constant (const byte) main::$1 -Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN Eliminating unused constant (const byte) SIZEOF_WORD Successful SSA optimization PassNEliminateUnusedVars Adding NOP phi() at start of @begin @@ -125,34 +128,36 @@ FINAL CONTROL FLOW GRAPH main: scope:[main] from @1 [4] callprepare plus (word) $1234 (word) $2345 [5] callexecute plus - [6] (word~) main::$0 ← callfinalize plus - [7] *((const word*) SCREEN) ← (word~) main::$0 + stackpull((number) 2) + [7] (word~) main::$0 ← stackpull(word) + [8] *((const word*) SCREEN) ← (word~) main::$0 to:main::@return main::@return: scope:[main] from main - [8] return + [9] return to:@return __stackcall (word()) plus((word) plus::a , (word) plus::b) plus: scope:[plus] from - [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) - [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) - [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 + [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) + [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) + [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [12] return (word) plus::return#0 + [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 + [14] return to:@return VARIABLE REGISTER WEIGHTS (void()) main() -(word~) main::$0 2.0 +(word~) main::$0 4.0 __stackcall (word()) plus((word) plus::a , (word) plus::b) (word) plus::a (word) plus::a#0 2.0 (word) plus::b (word) plus::b#0 4.0 (word) plus::return -(word) plus::return#0 2.0 +(word) plus::return#0 4.0 Initial phi equivalence classes Added variable main::$0 to live range equivalence class [ main::$0 ] @@ -209,15 +214,15 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla - // [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_ + // [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_ pla sta.z __0 pla sta.z __0+1 - // [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 + // [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 lda.z __0 sta SCREEN lda.z __0+1 @@ -225,7 +230,7 @@ main: { jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts } // plus @@ -233,22 +238,23 @@ main: { plus: { .const OFFSET_STACK_A = 2 .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN = 2 .label a = 4 .label b = 6 .label return = 8 - // [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 + // [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 + // [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b lda STACK_BASE+OFFSET_STACK_B+1,x sta.z b+1 - // [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz2_plus_vwuz3 + // [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz2_plus_vwuz3 lda.z a clc adc.z b @@ -259,36 +265,37 @@ plus: { jmp __breturn // plus::@return __breturn: - // [12] return (word) plus::return#0 - // [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 + // [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [14] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [4] callprepare plus (word) $1234 (word) $2345 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [6] (word~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [7] *((const word*) SCREEN) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a -Statement [12] return (word) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte a reg byte x +Statement stackpull((number) 2) always clobbers reg byte a +Statement [7] (word~) main::$0 ← stackpull(word) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a +Statement [8] *((const word*) SCREEN) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte a reg byte x Potential registers zp[2]:2 [ main::$0 ] : zp[2]:2 , Potential registers zp[2]:4 [ plus::a#0 ] : zp[2]:4 , Potential registers zp[2]:6 [ plus::b#0 ] : zp[2]:6 , Potential registers zp[2]:8 [ plus::return#0 ] : zp[2]:8 , REGISTER UPLIFT SCOPES -Uplift Scope [plus] 4: zp[2]:6 [ plus::b#0 ] 2: zp[2]:4 [ plus::a#0 ] 2: zp[2]:8 [ plus::return#0 ] -Uplift Scope [main] 2: zp[2]:2 [ main::$0 ] +Uplift Scope [plus] 4: zp[2]:6 [ plus::b#0 ] 4: zp[2]:8 [ plus::return#0 ] 2: zp[2]:4 [ plus::a#0 ] +Uplift Scope [main] 4: zp[2]:2 [ main::$0 ] Uplift Scope [] -Uplifting [plus] best 164 combination zp[2]:6 [ plus::b#0 ] zp[2]:4 [ plus::a#0 ] zp[2]:8 [ plus::return#0 ] +Uplifting [plus] best 164 combination zp[2]:6 [ plus::b#0 ] zp[2]:8 [ plus::return#0 ] zp[2]:4 [ plus::a#0 ] Uplifting [main] best 164 combination zp[2]:2 [ main::$0 ] Uplifting [] best 164 combination Coalescing zero page register [ zp[2]:4 [ plus::a#0 ] ] with [ zp[2]:8 [ plus::return#0 ] ] - score: 1 @@ -335,15 +342,15 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla - // [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_ + // [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_ pla sta.z __0 pla sta.z __0+1 - // [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 + // [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 lda.z __0 sta SCREEN lda.z __0+1 @@ -351,7 +358,7 @@ main: { jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts } // plus @@ -363,19 +370,19 @@ plus: { .label a = 2 .label b = 4 .label return = 2 - // [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 + // [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 + // [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b lda STACK_BASE+OFFSET_STACK_B+1,x sta.z b+1 - // [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2 + // [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2 lda.z return clc adc.z b @@ -386,13 +393,13 @@ plus: { jmp __breturn // plus::@return __breturn: - // [12] return (word) plus::return#0 - // [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 + // [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [14] return rts } // File Data @@ -424,7 +431,7 @@ FINAL SYMBOL TABLE (const word*) SCREEN = (word*) 1024 (const word) STACK_BASE = (word) $103 (void()) main() -(word~) main::$0 zp[2]:2 2.0 +(word~) main::$0 zp[2]:2 4.0 (label) main::@return __stackcall (word()) plus((word) plus::a , (word) plus::b) (label) plus::@return @@ -436,7 +443,7 @@ __stackcall (word()) plus((word) plus::a , (word) plus::b) (word) plus::b (word) plus::b#0 b zp[2]:4 4.0 (word) plus::return -(word) plus::return#0 return zp[2]:2 2.0 +(word) plus::return#0 return zp[2]:2 4.0 zp[2]:2 [ plus::a#0 plus::return#0 main::$0 ] zp[2]:4 [ plus::b#0 ] @@ -476,23 +483,23 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla - // [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_ + // [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_ pla sta.z __0 pla sta.z __0+1 // SCREEN[0] = plus(0x1234, 0x2345) - // [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 + // [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 lda.z __0 sta SCREEN lda.z __0+1 sta SCREEN+1 // main::@return // } - // [8] return + // [9] return rts } // plus @@ -504,20 +511,20 @@ plus: { .label a = 2 .label b = 4 .label return = 2 - // [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 + // [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 + // [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b lda STACK_BASE+OFFSET_STACK_B+1,x sta.z b+1 // return a+b; - // [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2 + // [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2 lda.z return clc adc.z b @@ -527,13 +534,13 @@ plus: { sta.z return+1 // plus::@return // } - // [12] return (word) plus::return#0 - // [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 + // [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [14] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-2.sym b/src/test/ref/procedure-callingconvention-stack-2.sym index 8e1b5048c..b3aa72105 100644 --- a/src/test/ref/procedure-callingconvention-stack-2.sym +++ b/src/test/ref/procedure-callingconvention-stack-2.sym @@ -4,7 +4,7 @@ (const word*) SCREEN = (word*) 1024 (const word) STACK_BASE = (word) $103 (void()) main() -(word~) main::$0 zp[2]:2 2.0 +(word~) main::$0 zp[2]:2 4.0 (label) main::@return __stackcall (word()) plus((word) plus::a , (word) plus::b) (label) plus::@return @@ -16,7 +16,7 @@ __stackcall (word()) plus((word) plus::a , (word) plus::b) (word) plus::b (word) plus::b#0 b zp[2]:4 4.0 (word) plus::return -(word) plus::return#0 return zp[2]:2 2.0 +(word) plus::return#0 return zp[2]:2 4.0 zp[2]:2 [ plus::a#0 plus::return#0 main::$0 ] zp[2]:4 [ plus::b#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-3.cfg b/src/test/ref/procedure-callingconvention-stack-3.cfg index 917d122ab..1b6799cf8 100644 --- a/src/test/ref/procedure-callingconvention-stack-3.cfg +++ b/src/test/ref/procedure-callingconvention-stack-3.cfg @@ -12,19 +12,21 @@ main: scope:[main] from @1 [4] callprepare plus (byte) '0' (byte) 7 [5] callexecute plus - [6] (word~) main::$0 ← callfinalize plus - [7] *((const word*) SCREEN) ← (word~) main::$0 + stackpull((number) 2) + [7] (word~) main::$0 ← stackpull(word) + [8] *((const word*) SCREEN) ← (word~) main::$0 to:main::@return main::@return: scope:[main] from main - [8] return + [9] return to:@return __stackcall (word()) plus((word) plus::a , (word) plus::b) plus: scope:[plus] from - [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) - [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) - [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 + [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) + [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) + [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [12] return (word) plus::return#0 + [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 + [14] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-3.log b/src/test/ref/procedure-callingconvention-stack-3.log index e77e0a572..454f51414 100644 --- a/src/test/ref/procedure-callingconvention-stack-3.log +++ b/src/test/ref/procedure-callingconvention-stack-3.log @@ -4,6 +4,8 @@ Culled Empty Block (label) plus::@1 Calling convention STACK_CALL adding prepare/execute/finalize for (word~) main::$0 ← call plus (byte) '0' (number) 7 Calling convention STACK_CALL replacing param((word) plus::a) with stackidx(word,(const byte) plus::OFFSET_STACK_A) Calling convention STACK_CALL replacing param((word) plus::b) with stackidx(word,(const byte) plus::OFFSET_STACK_B) +Calling convention STACK_CALL adding stack return stackidx(word,plus::OFFSET_STACK_RETURN) ← plus::return +Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(word) CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -13,7 +15,8 @@ CONTROL FLOW GRAPH SSA main: scope:[main] from @2 callprepare plus (byte) '0' (number) 7 callexecute plus - (word~) main::$0 ← callfinalize plus + stackpull((number) 2) + (word~) main::$0 ← stackpull(word) (number~) main::$1 ← (number) 0 * (const byte) SIZEOF_WORD *((const word*) SCREEN + (number~) main::$1) ← (word~) main::$0 to:main::@return @@ -30,7 +33,8 @@ plus: scope:[plus] from to:plus::@return plus::@return: scope:[plus] from plus (word) plus::return#1 ← phi( plus/(word) plus::return#0 ) - return (word) plus::return#1 + stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#1 + return to:@return @2: scope:[] from @begin call main @@ -79,16 +83,15 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions Inferred type updated to byte in (unumber~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD Alias (word) plus::return#0 = (word~) plus::$0 (word) plus::return#1 Successful SSA optimization Pass2AliasElimination -Constant right-side identified [3] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD +Constant right-side identified [4] (byte~) main::$1 ← (byte) 0 * (const byte) SIZEOF_WORD Successful SSA optimization Pass2ConstantRValueConsolidation Constant (const byte) main::$1 = 0*SIZEOF_WORD Successful SSA optimization Pass2ConstantIdentification Simplifying constant evaluating to zero (byte) 0*(const byte) SIZEOF_WORD in Successful SSA optimization PassNSimplifyConstantZero -Simplifying expression containing zero SCREEN in [4] *((const word*) SCREEN + (const byte) main::$1) ← (word~) main::$0 +Simplifying expression containing zero SCREEN in [5] *((const word*) SCREEN + (const byte) main::$1) ← (word~) main::$0 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused constant (const byte) main::$1 -Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN Eliminating unused constant (const byte) SIZEOF_WORD Successful SSA optimization PassNEliminateUnusedVars Adding NOP phi() at start of @begin @@ -122,34 +125,36 @@ FINAL CONTROL FLOW GRAPH main: scope:[main] from @1 [4] callprepare plus (byte) '0' (byte) 7 [5] callexecute plus - [6] (word~) main::$0 ← callfinalize plus - [7] *((const word*) SCREEN) ← (word~) main::$0 + stackpull((number) 2) + [7] (word~) main::$0 ← stackpull(word) + [8] *((const word*) SCREEN) ← (word~) main::$0 to:main::@return main::@return: scope:[main] from main - [8] return + [9] return to:@return __stackcall (word()) plus((word) plus::a , (word) plus::b) plus: scope:[plus] from - [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) - [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) - [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 + [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) + [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) + [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [12] return (word) plus::return#0 + [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 + [14] return to:@return VARIABLE REGISTER WEIGHTS (void()) main() -(word~) main::$0 2.0 +(word~) main::$0 4.0 __stackcall (word()) plus((word) plus::a , (word) plus::b) (word) plus::a (word) plus::a#0 2.0 (word) plus::b (word) plus::b#0 4.0 (word) plus::return -(word) plus::return#0 2.0 +(word) plus::return#0 4.0 Initial phi equivalence classes Added variable main::$0 to live range equivalence class [ main::$0 ] @@ -209,15 +214,15 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla - // [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_ + // [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_ pla sta.z __0 pla sta.z __0+1 - // [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 + // [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 lda.z __0 sta SCREEN lda.z __0+1 @@ -225,7 +230,7 @@ main: { jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts } // plus @@ -233,22 +238,23 @@ main: { plus: { .const OFFSET_STACK_A = 2 .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN = 2 .label a = 4 .label b = 6 .label return = 8 - // [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 + // [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 + // [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b lda STACK_BASE+OFFSET_STACK_B+1,x sta.z b+1 - // [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz2_plus_vwuz3 + // [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz2_plus_vwuz3 lda.z a clc adc.z b @@ -259,36 +265,37 @@ plus: { jmp __breturn // plus::@return __breturn: - // [12] return (word) plus::return#0 - // [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 + // [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [14] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [4] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [6] (word~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [7] *((const word*) SCREEN) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a -Statement [12] return (word) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte a reg byte x +Statement stackpull((number) 2) always clobbers reg byte a +Statement [7] (word~) main::$0 ← stackpull(word) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a +Statement [8] *((const word*) SCREEN) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:5 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:5 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:5 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 [ ] ( main:2::plus:5 [ ] ) always clobbers reg byte a reg byte x Potential registers zp[2]:2 [ main::$0 ] : zp[2]:2 , Potential registers zp[2]:4 [ plus::a#0 ] : zp[2]:4 , Potential registers zp[2]:6 [ plus::b#0 ] : zp[2]:6 , Potential registers zp[2]:8 [ plus::return#0 ] : zp[2]:8 , REGISTER UPLIFT SCOPES -Uplift Scope [plus] 4: zp[2]:6 [ plus::b#0 ] 2: zp[2]:4 [ plus::a#0 ] 2: zp[2]:8 [ plus::return#0 ] -Uplift Scope [main] 2: zp[2]:2 [ main::$0 ] +Uplift Scope [plus] 4: zp[2]:6 [ plus::b#0 ] 4: zp[2]:8 [ plus::return#0 ] 2: zp[2]:4 [ plus::a#0 ] +Uplift Scope [main] 4: zp[2]:2 [ main::$0 ] Uplift Scope [] -Uplifting [plus] best 164 combination zp[2]:6 [ plus::b#0 ] zp[2]:4 [ plus::a#0 ] zp[2]:8 [ plus::return#0 ] +Uplifting [plus] best 164 combination zp[2]:6 [ plus::b#0 ] zp[2]:8 [ plus::return#0 ] zp[2]:4 [ plus::a#0 ] Uplifting [main] best 164 combination zp[2]:2 [ main::$0 ] Uplifting [] best 164 combination Coalescing zero page register [ zp[2]:4 [ plus::a#0 ] ] with [ zp[2]:8 [ plus::return#0 ] ] - score: 1 @@ -338,15 +345,15 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla - // [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_ + // [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_ pla sta.z __0 pla sta.z __0+1 - // [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 + // [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 lda.z __0 sta SCREEN lda.z __0+1 @@ -354,7 +361,7 @@ main: { jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts } // plus @@ -366,19 +373,19 @@ plus: { .label a = 2 .label b = 4 .label return = 2 - // [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 + // [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 + // [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b lda STACK_BASE+OFFSET_STACK_B+1,x sta.z b+1 - // [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2 + // [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2 lda.z return clc adc.z b @@ -389,13 +396,13 @@ plus: { jmp __breturn // plus::@return __breturn: - // [12] return (word) plus::return#0 - // [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 + // [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [14] return rts } // File Data @@ -427,7 +434,7 @@ FINAL SYMBOL TABLE (const word*) SCREEN = (word*) 1024 (const word) STACK_BASE = (word) $103 (void()) main() -(word~) main::$0 zp[2]:2 2.0 +(word~) main::$0 zp[2]:2 4.0 (label) main::@return __stackcall (word()) plus((word) plus::a , (word) plus::b) (label) plus::@return @@ -439,7 +446,7 @@ __stackcall (word()) plus((word) plus::a , (word) plus::b) (word) plus::b (word) plus::b#0 b zp[2]:4 4.0 (word) plus::return -(word) plus::return#0 return zp[2]:2 2.0 +(word) plus::return#0 return zp[2]:2 4.0 zp[2]:2 [ plus::a#0 plus::return#0 main::$0 ] zp[2]:4 [ plus::b#0 ] @@ -482,23 +489,23 @@ main: { pha // [5] callexecute plus -- jsr jsr plus - // [6] (word~) main::$0 ← callfinalize plus -- _stackpullbyte_2 + // stackpull((number) 2) -- _stackpullbyte_2 pla pla - // [6] (word~) main::$0 ← callfinalize plus -- vwuz1=_stackpullword_ + // [7] (word~) main::$0 ← stackpull(word) -- vwuz1=_stackpullword_ pla sta.z __0 pla sta.z __0+1 // SCREEN[0] = plus('0', 7) - // [7] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 + // [8] *((const word*) SCREEN) ← (word~) main::$0 -- _deref_pwuc1=vwuz1 lda.z __0 sta SCREEN lda.z __0+1 sta SCREEN+1 // main::@return // } - // [8] return + // [9] return rts } // plus @@ -510,20 +517,20 @@ plus: { .label a = 2 .label b = 4 .label return = 2 - // [9] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 + // [10] (word) plus::a#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [10] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 + // [11] (word) plus::b#0 ← stackidx(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackidxword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b lda STACK_BASE+OFFSET_STACK_B+1,x sta.z b+1 // return a+b; - // [11] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2 + // [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 -- vwuz1=vwuz1_plus_vwuz2 lda.z return clc adc.z b @@ -533,13 +540,13 @@ plus: { sta.z return+1 // plus::@return // } - // [12] return (word) plus::return#0 - // [12] return (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 + // [13] stackidx(word,(const byte) plus::OFFSET_STACK_RETURN) ← (word) plus::return#0 -- _stackidxword_vbuc1=vwuz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [14] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-3.sym b/src/test/ref/procedure-callingconvention-stack-3.sym index 8e1b5048c..b3aa72105 100644 --- a/src/test/ref/procedure-callingconvention-stack-3.sym +++ b/src/test/ref/procedure-callingconvention-stack-3.sym @@ -4,7 +4,7 @@ (const word*) SCREEN = (word*) 1024 (const word) STACK_BASE = (word) $103 (void()) main() -(word~) main::$0 zp[2]:2 2.0 +(word~) main::$0 zp[2]:2 4.0 (label) main::@return __stackcall (word()) plus((word) plus::a , (word) plus::b) (label) plus::@return @@ -16,7 +16,7 @@ __stackcall (word()) plus((word) plus::a , (word) plus::b) (word) plus::b (word) plus::b#0 b zp[2]:4 4.0 (word) plus::return -(word) plus::return#0 return zp[2]:2 2.0 +(word) plus::return#0 return zp[2]:2 4.0 zp[2]:2 [ plus::a#0 plus::return#0 main::$0 ] zp[2]:4 [ plus::b#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-4.asm b/src/test/ref/procedure-callingconvention-stack-4.asm index 7dba0db1d..5fc35e565 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.asm +++ b/src/test/ref/procedure-callingconvention-stack-4.asm @@ -18,8 +18,8 @@ main: { txa pha jsr plus - // w = plus('0', v) pla + // w = plus('0', v) pla // w+a sty.z $ff diff --git a/src/test/ref/procedure-callingconvention-stack-4.cfg b/src/test/ref/procedure-callingconvention-stack-4.cfg index e7f013f85..b63ac07c4 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.cfg +++ b/src/test/ref/procedure-callingconvention-stack-4.cfg @@ -17,22 +17,24 @@ main::@1: scope:[main] from main main::@1 [6] (byte) main::v#0 ← (byte) main::a#2 + (byte) 1 [7] callprepare plus (byte) '0' (byte) main::v#0 [8] callexecute plus - [9] (byte) main::w#0 ← callfinalize plus - [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 - [11] *((const byte*) SCREEN) ← (byte~) main::$2 - [12] (byte) main::a#1 ← ++ (byte) main::a#2 - [13] if((byte) main::a#1!=(byte) 2) goto main::@1 + stackpull((number) 1) + [10] (byte) main::w#0 ← stackpull(byte) + [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 + [12] *((const byte*) SCREEN) ← (byte~) main::$2 + [13] (byte) main::a#1 ← ++ (byte) main::a#2 + [14] if((byte) main::a#1!=(byte) 2) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - [14] return + [15] return to:@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) - [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 + [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) + [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) + [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [18] return (byte) plus::return#0 + [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 + [20] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-4.log b/src/test/ref/procedure-callingconvention-stack-4.log index b10eb0805..b236288ab 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.log +++ b/src/test/ref/procedure-callingconvention-stack-4.log @@ -4,6 +4,8 @@ Culled Empty Block (label) plus::@1 Calling convention STACK_CALL adding prepare/execute/finalize for (byte~) main::$1 ← call plus (byte) '0' (byte) main::v Calling convention STACK_CALL replacing param((byte) plus::a) with stackidx(byte,(const byte) plus::OFFSET_STACK_A) Calling convention STACK_CALL replacing param((byte) plus::b) with stackidx(byte,(const byte) plus::OFFSET_STACK_B) +Calling convention STACK_CALL adding stack return stackidx(byte,plus::OFFSET_STACK_RETURN) ← plus::return +Calling convention STACK_CALL adding stack pull main::$1 ← stackpull(byte) CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -22,7 +24,8 @@ main::@1: scope:[main] from main main::@1 (byte) main::v#0 ← (number~) main::$0 callprepare plus (byte) '0' (byte) main::v#0 callexecute plus - (byte~) main::$1 ← callfinalize plus + stackpull((number) 1) + (byte~) main::$1 ← stackpull(byte) (byte) main::w#0 ← (byte~) main::$1 (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 *((const byte*) SCREEN + (byte) i#4) ← (byte~) main::$2 @@ -47,7 +50,8 @@ plus: scope:[plus] from to:plus::@return plus::@return: scope:[plus] from plus (byte) plus::return#1 ← phi( plus/(byte) plus::return#0 ) - return (byte) plus::return#1 + stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#1 + return to:@return @2: scope:[] from @begin (byte) i#9 ← phi( @begin/(byte) i#0 ) @@ -126,17 +130,16 @@ Identical Phi Values (byte) i#8 (byte) i#0 Identical Phi Values (byte) i#1 (byte) i#8 Identical Phi Values (byte) i#3 (byte) i#1 Successful SSA optimization Pass2IdenticalPhiElimination -Simple Condition (bool~) main::$3 [12] if((byte) main::a#1!=rangelast(0,1)) goto main::@1 +Simple Condition (bool~) main::$3 [13] if((byte) main::a#1!=rangelast(0,1)) goto main::@1 Successful SSA optimization Pass2ConditionalJumpSimplification Constant (const byte) i#0 = 0 Constant (const byte) main::a#0 = 0 Successful SSA optimization Pass2ConstantIdentification -Resolved ranged next value [10] main::a#1 ← ++ main::a#2 to ++ -Resolved ranged comparison value [12] if(main::a#1!=rangelast(0,1)) goto main::@1 to (number) 2 -Simplifying expression containing zero SCREEN in [9] *((const byte*) SCREEN + (const byte) i#0) ← (byte~) main::$2 +Resolved ranged next value [11] main::a#1 ← ++ main::a#2 to ++ +Resolved ranged comparison value [13] if(main::a#1!=rangelast(0,1)) goto main::@1 to (number) 2 +Simplifying expression containing zero SCREEN in [10] *((const byte*) SCREEN + (const byte) i#0) ← (byte~) main::$2 Successful SSA optimization PassNSimplifyExpressionWithZero -Eliminating unused variable (byte) i#2 and assignment [13] (byte) i#2 ← ++ (byte) i#6 -Eliminating unused constant (const byte) plus::OFFSET_STACK_RETURN +Eliminating unused variable (byte) i#2 and assignment [14] (byte) i#2 ← ++ (byte) i#6 Eliminating unused constant (const byte) i#0 Successful SSA optimization PassNEliminateUnusedVars Eliminating unused variable - keeping the phi block (byte) i#6 @@ -161,7 +164,7 @@ Calls in [] to main:2 Calls in [main] to plus:9 Created 1 initial phi equivalence classes -Coalesced [16] main::a#3 ← main::a#1 +Coalesced [17] main::a#3 ← main::a#1 Coalesced down to 1 phi equivalence classes Culled Empty Block (label) @3 Culled Empty Block (label) main::@3 @@ -191,24 +194,26 @@ main::@1: scope:[main] from main main::@1 [6] (byte) main::v#0 ← (byte) main::a#2 + (byte) 1 [7] callprepare plus (byte) '0' (byte) main::v#0 [8] callexecute plus - [9] (byte) main::w#0 ← callfinalize plus - [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 - [11] *((const byte*) SCREEN) ← (byte~) main::$2 - [12] (byte) main::a#1 ← ++ (byte) main::a#2 - [13] if((byte) main::a#1!=(byte) 2) goto main::@1 + stackpull((number) 1) + [10] (byte) main::w#0 ← stackpull(byte) + [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 + [12] *((const byte*) SCREEN) ← (byte~) main::$2 + [13] (byte) main::a#1 ← ++ (byte) main::a#2 + [14] if((byte) main::a#1!=(byte) 2) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - [14] return + [15] return to:@return __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) - [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) - [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 + [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) + [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) + [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus - [18] return (byte) plus::return#0 + [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 + [20] return to:@return @@ -218,18 +223,18 @@ VARIABLE REGISTER WEIGHTS (byte~) main::$2 22.0 (byte) main::a (byte) main::a#1 16.5 -(byte) main::a#2 6.285714285714286 +(byte) main::a#2 5.5 (byte) main::v (byte) main::v#0 11.0 (byte) main::w -(byte) main::w#0 11.0 +(byte) main::w#0 22.0 __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::a (byte) plus::a#0 2.0 (byte) plus::b (byte) plus::b#0 4.0 (byte) plus::return -(byte) plus::return#0 2.0 +(byte) plus::return#0 4.0 Initial phi equivalence classes [ main::a#2 main::a#1 ] @@ -313,29 +318,29 @@ main: { pha // [8] callexecute plus -- jsr jsr plus - // [9] (byte) main::w#0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [9] (byte) main::w#0 ← callfinalize plus -- vbuz1=_stackpullbyte_ + // [10] (byte) main::w#0 ← stackpull(byte) -- vbuz1=_stackpullbyte_ pla sta.z w - // [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuz1=vbuz2_plus_vbuz3 + // [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuz1=vbuz2_plus_vbuz3 lda.z w clc adc.z a sta.z __2 - // [11] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuz1 lda.z __2 sta SCREEN - // [12] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuz1=_inc_vbuz1 + // [13] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuz1=_inc_vbuz1 inc.z a - // [13] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + // [14] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 lda #2 cmp.z a bne __b1_from___b1 jmp __breturn // main::@return __breturn: - // [14] return + // [15] return rts } // plus @@ -343,18 +348,19 @@ main: { plus: { .const OFFSET_STACK_A = 1 .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN = 1 .label a = 6 .label b = 7 .label return = 8 - // [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1 + // [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b - // [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3 + // [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuz1=vbuz2_plus_vbuz3 lda.z a clc adc.z b @@ -362,11 +368,11 @@ plus: { jmp __breturn // plus::@return __breturn: - // [18] return (byte) plus::return#0 - // [18] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1 + // [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuz1 lda.z return tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [20] return rts } // File Data @@ -374,22 +380,24 @@ plus: { REGISTER UPLIFT POTENTIAL REGISTERS Statement [7] callprepare plus (byte) '0' (byte) main::v#0 [ main::a#2 ] ( main:2 [ main::a#2 ] ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::a#2 main::a#1 ] -Statement [9] (byte) main::w#0 ← callfinalize plus [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a -Statement [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a -Statement [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement stackpull((number) 1) always clobbers reg byte a +Statement [10] (byte) main::w#0 ← stackpull(byte) [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a +Statement [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a +Statement [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::a#2 main::a#1 ] -Statement [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte a as potential for zp[1]:6 [ plus::a#0 ] Removing always clobbered register reg byte x as potential for zp[1]:6 [ plus::a#0 ] -Statement [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a -Statement [18] return (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x +Statement [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a +Statement [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x Statement [7] callprepare plus (byte) '0' (byte) main::v#0 [ main::a#2 ] ( main:2 [ main::a#2 ] ) always clobbers reg byte a -Statement [9] (byte) main::w#0 ← callfinalize plus [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a -Statement [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a -Statement [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x -Statement [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a -Statement [18] return (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x +Statement stackpull((number) 1) always clobbers reg byte a +Statement [10] (byte) main::w#0 ← stackpull(byte) [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a +Statement [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a +Statement [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a +Statement [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x Potential registers zp[1]:2 [ main::a#2 main::a#1 ] : zp[1]:2 , reg byte y , Potential registers zp[1]:3 [ main::v#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:4 [ main::w#0 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , @@ -399,13 +407,13 @@ Potential registers zp[1]:7 [ plus::b#0 ] : zp[1]:7 , reg byte a , reg byte x , Potential registers zp[1]:8 [ plus::return#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES -Uplift Scope [main] 22.79: zp[1]:2 [ main::a#2 main::a#1 ] 22: zp[1]:5 [ main::$2 ] 11: zp[1]:3 [ main::v#0 ] 11: zp[1]:4 [ main::w#0 ] -Uplift Scope [plus] 4: zp[1]:7 [ plus::b#0 ] 2: zp[1]:6 [ plus::a#0 ] 2: zp[1]:8 [ plus::return#0 ] +Uplift Scope [main] 22: zp[1]:2 [ main::a#2 main::a#1 ] 22: zp[1]:4 [ main::w#0 ] 22: zp[1]:5 [ main::$2 ] 11: zp[1]:3 [ main::v#0 ] +Uplift Scope [plus] 4: zp[1]:7 [ plus::b#0 ] 4: zp[1]:8 [ plus::return#0 ] 2: zp[1]:6 [ plus::a#0 ] Uplift Scope [] -Uplifting [main] best 661 combination reg byte y [ main::a#2 main::a#1 ] reg byte a [ main::$2 ] reg byte x [ main::v#0 ] reg byte a [ main::w#0 ] +Uplifting [main] best 661 combination reg byte y [ main::a#2 main::a#1 ] reg byte a [ main::w#0 ] reg byte a [ main::$2 ] reg byte x [ main::v#0 ] Limited combination testing to 100 combinations of 128 possible. -Uplifting [plus] best 649 combination reg byte a [ plus::b#0 ] zp[1]:6 [ plus::a#0 ] reg byte a [ plus::return#0 ] +Uplifting [plus] best 649 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:6 [ plus::a#0 ] Uplifting [] best 649 combination Attempting to uplift remaining variables inzp[1]:6 [ plus::a#0 ] Uplifting [plus] best 649 combination zp[1]:6 [ plus::a#0 ] @@ -463,25 +471,25 @@ main: { pha // [8] callexecute plus -- jsr jsr plus - // [9] (byte) main::w#0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [9] (byte) main::w#0 ← callfinalize plus -- vbuaa=_stackpullbyte_ + // [10] (byte) main::w#0 ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla - // [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy + // [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy sty.z $ff clc adc.z $ff - // [11] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa + // [12] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa sta SCREEN - // [12] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy + // [13] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy iny - // [13] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 + // [14] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 cpy #2 bne __b1_from___b1 jmp __breturn // main::@return __breturn: - // [14] return + // [15] return rts } // plus @@ -491,23 +499,23 @@ plus: { .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 .label a = 2 - // [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + // [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x - // [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + // [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa clc adc.z a jmp __breturn // plus::@return __breturn: - // [18] return (byte) plus::return#0 - // [18] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + // [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [20] return rts } // File Data @@ -552,11 +560,11 @@ FINAL SYMBOL TABLE (label) main::@return (byte) main::a (byte) main::a#1 reg byte y 16.5 -(byte) main::a#2 reg byte y 6.285714285714286 +(byte) main::a#2 reg byte y 5.5 (byte) main::v (byte) main::v#0 reg byte x 11.0 (byte) main::w -(byte) main::w#0 reg byte a 11.0 +(byte) main::w#0 reg byte a 22.0 __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (label) plus::@return (const byte) plus::OFFSET_STACK_A = (byte) 1 @@ -567,7 +575,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::b (byte) plus::b#0 reg byte a 4.0 (byte) plus::return -(byte) plus::return#0 reg byte a 2.0 +(byte) plus::return#0 reg byte a 4.0 reg byte y [ main::a#2 main::a#1 ] reg byte x [ main::v#0 ] @@ -621,28 +629,28 @@ main: { pha // [8] callexecute plus -- jsr jsr plus - // w = plus('0', v) - // [9] (byte) main::w#0 ← callfinalize plus -- _stackpullbyte_1 + // stackpull((number) 1) -- _stackpullbyte_1 pla - // [9] (byte) main::w#0 ← callfinalize plus -- vbuaa=_stackpullbyte_ + // w = plus('0', v) + // [10] (byte) main::w#0 ← stackpull(byte) -- vbuaa=_stackpullbyte_ pla // w+a - // [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy + // [11] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 -- vbuaa=vbuaa_plus_vbuyy sty.z $ff clc adc.z $ff // SCREEN[i] = w+a - // [11] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa + // [12] *((const byte*) SCREEN) ← (byte~) main::$2 -- _deref_pbuc1=vbuaa sta SCREEN // for(char a:0..1) - // [12] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy + // [13] (byte) main::a#1 ← ++ (byte) main::a#2 -- vbuyy=_inc_vbuyy iny - // [13] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 + // [14] if((byte) main::a#1!=(byte) 2) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 cpy #2 bne __b1 // main::@return // } - // [14] return + // [15] return rts } // plus @@ -652,23 +660,23 @@ plus: { .const OFFSET_STACK_B = 0 .const OFFSET_STACK_RETURN = 1 .label a = 2 - // [15] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + // [16] (byte) plus::a#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [16] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + // [17] (byte) plus::b#0 ← stackidx(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // return a+b; - // [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + // [18] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa clc adc.z a // plus::@return // } - // [18] return (byte) plus::return#0 - // [18] return (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + // [19] stackidx(byte,(const byte) plus::OFFSET_STACK_RETURN) ← (byte) plus::return#0 -- _stackidxbyte_vbuc1=vbuaa tsx sta STACK_BASE+OFFSET_STACK_RETURN,x + // [20] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-4.sym b/src/test/ref/procedure-callingconvention-stack-4.sym index af3516db8..ad8773595 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.sym +++ b/src/test/ref/procedure-callingconvention-stack-4.sym @@ -10,11 +10,11 @@ (label) main::@return (byte) main::a (byte) main::a#1 reg byte y 16.5 -(byte) main::a#2 reg byte y 6.285714285714286 +(byte) main::a#2 reg byte y 5.5 (byte) main::v (byte) main::v#0 reg byte x 11.0 (byte) main::w -(byte) main::w#0 reg byte a 11.0 +(byte) main::w#0 reg byte a 22.0 __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (label) plus::@return (const byte) plus::OFFSET_STACK_A = (byte) 1 @@ -25,7 +25,7 @@ __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) (byte) plus::b (byte) plus::b#0 reg byte a 4.0 (byte) plus::return -(byte) plus::return#0 reg byte a 2.0 +(byte) plus::return#0 reg byte a 4.0 reg byte y [ main::a#2 main::a#1 ] reg byte x [ main::v#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-5.cfg b/src/test/ref/procedure-callingconvention-stack-5.cfg index 1e743c3a6..82676c346 100644 --- a/src/test/ref/procedure-callingconvention-stack-5.cfg +++ b/src/test/ref/procedure-callingconvention-stack-5.cfg @@ -12,11 +12,11 @@ main: scope:[main] from @1 [4] callprepare next [5] callexecute next - [6] (signed word~) main::$0 ← callfinalize next + [6] (signed word~) main::$0 ← stackpull(signed word) [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 [8] callprepare next [9] callexecute next - [10] (signed word~) main::$1 ← callfinalize next + [10] (signed word~) main::$1 ← stackpull(signed word) [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 to:main::@return main::@return: scope:[main] from main @@ -29,5 +29,6 @@ next: scope:[next] from [14] (signed word) next::return#0 ← (signed word) current#5 to:next::@return next::@return: scope:[next] from next - [15] return (signed word) next::return#0 + [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 + [16] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-5.log b/src/test/ref/procedure-callingconvention-stack-5.log index b836c6a73..1f3e590a2 100644 --- a/src/test/ref/procedure-callingconvention-stack-5.log +++ b/src/test/ref/procedure-callingconvention-stack-5.log @@ -3,6 +3,9 @@ Fixing pointer array-indexing *((const signed word*) SCREEN + (number) 1) Culled Empty Block (label) next::@1 Calling convention STACK_CALL adding prepare/execute/finalize for (signed word~) main::$0 ← call next Calling convention STACK_CALL adding prepare/execute/finalize for (signed word~) main::$1 ← call next +Calling convention STACK_CALL adding stack return stackidx(signed word,next::OFFSET_STACK_RETURN) ← next::return +Calling convention STACK_CALL adding stack pull main::$0 ← stackpull(signed word) +Calling convention STACK_CALL adding stack pull main::$1 ← stackpull(signed word) CONTROL FLOW GRAPH SSA @begin: scope:[] from @@ -13,12 +16,12 @@ main: scope:[main] from @2 (signed word) current#7 ← phi( @2/(signed word) current#8 ) callprepare next callexecute next - (signed word~) main::$0 ← callfinalize next + (signed word~) main::$0 ← stackpull(signed word) (number~) main::$2 ← (number) 0 * (const byte) SIZEOF_SIGNED_WORD *((const signed word*) SCREEN + (number~) main::$2) ← (signed word~) main::$0 callprepare next callexecute next - (signed word~) main::$1 ← callfinalize next + (signed word~) main::$1 ← stackpull(signed word) (number~) main::$3 ← (number) 1 * (const byte) SIZEOF_SIGNED_WORD *((const signed word*) SCREEN + (number~) main::$3) ← (signed word~) main::$1 to:main::@return @@ -39,7 +42,8 @@ next: scope:[next] from to:next::@return next::@return: scope:[next] from next (signed word) next::return#1 ← phi( next/(signed word) next::return#0 ) - return (signed word) next::return#1 + stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#1 + return to:@return @2: scope:[] from @1 (signed word) current#8 ← phi( @1/(signed word) current#1 ) @@ -118,7 +122,6 @@ Simplifying expression containing zero SCREEN in [5] *((const signed word*) SCRE Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused variable (signed word) current#2 and assignment [11] (signed word) current#2 ← ++ (signed word) current#5 Eliminating unused constant (const byte) main::$2 -Eliminating unused constant (const byte) next::OFFSET_STACK_RETURN Eliminating unused constant (const signed word) current#1 Successful SSA optimization PassNEliminateUnusedVars Constant inlined main::$3 = (byte) 1*(const byte) SIZEOF_SIGNED_WORD @@ -158,11 +161,11 @@ FINAL CONTROL FLOW GRAPH main: scope:[main] from @1 [4] callprepare next [5] callexecute next - [6] (signed word~) main::$0 ← callfinalize next + [6] (signed word~) main::$0 ← stackpull(signed word) [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 [8] callprepare next [9] callexecute next - [10] (signed word~) main::$1 ← callfinalize next + [10] (signed word~) main::$1 ← stackpull(signed word) [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 to:main::@return main::@return: scope:[main] from main @@ -175,7 +178,8 @@ next: scope:[next] from [14] (signed word) next::return#0 ← (signed word) current#5 to:next::@return next::@return: scope:[next] from next - [15] return (signed word) next::return#0 + [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 + [16] return to:@return @@ -183,11 +187,11 @@ VARIABLE REGISTER WEIGHTS (signed word) current (signed word) current#5 2.0 (void()) main() -(signed word~) main::$0 2.0 -(signed word~) main::$1 2.0 +(signed word~) main::$0 4.0 +(signed word~) main::$1 4.0 __stackcall (signed word()) next() (signed word) next::return -(signed word) next::return#0 2.0 +(signed word) next::return#0 4.0 Initial phi equivalence classes [ current#5 ] @@ -241,7 +245,7 @@ main: { pha // [5] callexecute next -- jsr jsr next - // [6] (signed word~) main::$0 ← callfinalize next -- vwsz1=_stackpullsword_ + // [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __0 pla @@ -256,7 +260,7 @@ main: { pha // [9] callexecute next -- jsr jsr next - // [10] (signed word~) main::$1 ← callfinalize next -- vwsz1=_stackpullsword_ + // [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __1 pla @@ -274,6 +278,7 @@ main: { } // next next: { + .const OFFSET_STACK_RETURN = 0 .label return = 8 // [14] (signed word) next::return#0 ← (signed word) current#5 -- vwsz1=vwsz2 lda.z current @@ -283,32 +288,32 @@ next: { jmp __breturn // next::@return __breturn: - // [15] return (signed word) next::return#0 - // [15] return (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 + // [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [16] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [6] (signed word~) main::$0 ← callfinalize next [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a +Statement [6] (signed word~) main::$0 ← stackpull(signed word) [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a Statement [7] *((const signed word*) SCREEN) ← (signed word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [10] (signed word~) main::$1 ← callfinalize next [ main::$1 ] ( main:2 [ main::$1 ] ) always clobbers reg byte a +Statement [10] (signed word~) main::$1 ← stackpull(signed word) [ main::$1 ] ( main:2 [ main::$1 ] ) always clobbers reg byte a Statement [11] *((const signed word*) SCREEN+(byte) 1*(const byte) SIZEOF_SIGNED_WORD) ← (signed word~) main::$1 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [14] (signed word) next::return#0 ← (signed word) current#5 [ next::return#0 ] ( main:2::next:5 [ next::return#0 ] main:2::next:9 [ next::return#0 ] ) always clobbers reg byte a -Statement [15] return (signed word) next::return#0 [ ] ( main:2::next:5 [ ] main:2::next:9 [ ] ) always clobbers reg byte a reg byte x +Statement [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 [ ] ( main:2::next:5 [ ] main:2::next:9 [ ] ) always clobbers reg byte a reg byte x Potential registers zp[2]:2 [ current#5 ] : zp[2]:2 , Potential registers zp[2]:4 [ main::$0 ] : zp[2]:4 , Potential registers zp[2]:6 [ main::$1 ] : zp[2]:6 , Potential registers zp[2]:8 [ next::return#0 ] : zp[2]:8 , REGISTER UPLIFT SCOPES -Uplift Scope [main] 2: zp[2]:4 [ main::$0 ] 2: zp[2]:6 [ main::$1 ] -Uplift Scope [next] 2: zp[2]:8 [ next::return#0 ] +Uplift Scope [main] 4: zp[2]:4 [ main::$0 ] 4: zp[2]:6 [ main::$1 ] +Uplift Scope [next] 4: zp[2]:8 [ next::return#0 ] Uplift Scope [] 2: zp[2]:2 [ current#5 ] Uplifting [main] best 140 combination zp[2]:4 [ main::$0 ] zp[2]:6 [ main::$1 ] @@ -355,7 +360,7 @@ main: { pha // [5] callexecute next -- jsr jsr next - // [6] (signed word~) main::$0 ← callfinalize next -- vwsz1=_stackpullsword_ + // [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __0 pla @@ -370,7 +375,7 @@ main: { pha // [9] callexecute next -- jsr jsr next - // [10] (signed word~) main::$1 ← callfinalize next -- vwsz1=_stackpullsword_ + // [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __1 pla @@ -394,13 +399,13 @@ next: { jmp __breturn // next::@return __breturn: - // [15] return (signed word) next::return#0 - // [15] return (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 + // [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [16] return rts } // File Data @@ -435,14 +440,14 @@ FINAL SYMBOL TABLE (signed word) current (signed word) current#5 current zp[2]:2 2.0 (void()) main() -(signed word~) main::$0 zp[2]:2 2.0 -(signed word~) main::$1 zp[2]:4 2.0 +(signed word~) main::$0 zp[2]:2 4.0 +(signed word~) main::$1 zp[2]:4 4.0 (label) main::@return __stackcall (signed word()) next() (label) next::@return (const byte) next::OFFSET_STACK_RETURN = (byte) 0 (signed word) next::return -(signed word) next::return#0 return zp[2]:2 2.0 +(signed word) next::return#0 return zp[2]:2 4.0 zp[2]:2 [ main::$0 current#5 next::return#0 ] zp[2]:4 [ main::$1 ] @@ -479,7 +484,7 @@ main: { pha // [5] callexecute next -- jsr jsr next - // [6] (signed word~) main::$0 ← callfinalize next -- vwsz1=_stackpullsword_ + // [6] (signed word~) main::$0 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __0 pla @@ -496,7 +501,7 @@ main: { pha // [9] callexecute next -- jsr jsr next - // [10] (signed word~) main::$1 ← callfinalize next -- vwsz1=_stackpullsword_ + // [10] (signed word~) main::$1 ← stackpull(signed word) -- vwsz1=_stackpullsword_ pla sta.z __1 pla @@ -520,13 +525,13 @@ next: { // [14] (signed word) next::return#0 ← (signed word) current#5 // next::@return // } - // [15] return (signed word) next::return#0 - // [15] return (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 + // [15] stackidx(signed word,(const byte) next::OFFSET_STACK_RETURN) ← (signed word) next::return#0 -- _stackidxsword_vbuc1=vwsz1 tsx lda.z return sta STACK_BASE+OFFSET_STACK_RETURN,x lda.z return+1 sta STACK_BASE+OFFSET_STACK_RETURN+1,x + // [16] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-5.sym b/src/test/ref/procedure-callingconvention-stack-5.sym index 470022f42..64067d892 100644 --- a/src/test/ref/procedure-callingconvention-stack-5.sym +++ b/src/test/ref/procedure-callingconvention-stack-5.sym @@ -7,14 +7,14 @@ (signed word) current (signed word) current#5 current zp[2]:2 2.0 (void()) main() -(signed word~) main::$0 zp[2]:2 2.0 -(signed word~) main::$1 zp[2]:4 2.0 +(signed word~) main::$0 zp[2]:2 4.0 +(signed word~) main::$1 zp[2]:4 4.0 (label) main::@return __stackcall (signed word()) next() (label) next::@return (const byte) next::OFFSET_STACK_RETURN = (byte) 0 (signed word) next::return -(signed word) next::return#0 return zp[2]:2 2.0 +(signed word) next::return#0 return zp[2]:2 4.0 zp[2]:2 [ main::$0 current#5 next::return#0 ] zp[2]:4 [ main::$1 ] diff --git a/src/test/ref/procedure-callingconvention-stack-7.cfg b/src/test/ref/procedure-callingconvention-stack-7.cfg index 70af47256..cb5adafe9 100644 --- a/src/test/ref/procedure-callingconvention-stack-7.cfg +++ b/src/test/ref/procedure-callingconvention-stack-7.cfg @@ -4,35 +4,33 @@ @1: scope:[] from @begin [1] callprepare main [2] callexecute main - [3] callfinalize main to:@end @end: scope:[] from @1 - [4] phi() + [3] phi() __stackcall (void()) printline() printline: scope:[printline] from - [5] (byte) printline::i ← (byte) 0 + [4] (byte) printline::i ← (byte) 0 to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - [6] if((byte) printline::i<(byte) $28) goto printline::@2 + [5] if((byte) printline::i<(byte) $28) goto printline::@2 to:printline::@return printline::@return: scope:[printline] from printline::@1 - [7] return + [6] return to:@return printline::@2: scope:[printline] from printline::@1 - [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - [9] (byte) printline::i ← ++ (byte) printline::i + [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' + [8] (byte) printline::i ← ++ (byte) printline::i to:printline::@1 __stackcall (void()) main() main: scope:[main] from - [10] (byte) main::val ← (byte) 0 - [11] (byte) main::val ← *((const byte*) SCREEN) - [12] callprepare printline - [13] callexecute printline - [14] callfinalize printline - [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val + [9] (byte) main::val ← (byte) 0 + [10] (byte) main::val ← *((const byte*) SCREEN) + [11] callprepare printline + [12] callexecute printline + [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val to:main::@return main::@return: scope:[main] from main - [16] return + [14] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-7.log b/src/test/ref/procedure-callingconvention-stack-7.log index fde530dcc..acf5803e7 100644 --- a/src/test/ref/procedure-callingconvention-stack-7.log +++ b/src/test/ref/procedure-callingconvention-stack-7.log @@ -16,7 +16,6 @@ main: scope:[main] from (byte) main::val ← *((const byte*) SCREEN) callprepare printline callexecute printline - callfinalize printline *((const byte*) SCREEN + (number) $50) ← (byte) main::val to:main::@return main::@return: scope:[main] from main @@ -41,7 +40,6 @@ printline::@return: scope:[printline] from printline::@1 @2: scope:[] from @begin callprepare main callexecute main - callfinalize main to:@end @end: scope:[] from @2 @@ -70,7 +68,7 @@ Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) $50 Finalized unsigned number type (byte) $28 Successful SSA optimization PassNFinalizeNumberTypeConversions -Simple Condition (bool~) printline::$0 [9] if((byte) printline::i<(byte) $28) goto printline::@2 +Simple Condition (bool~) printline::$0 [8] if((byte) printline::i<(byte) $28) goto printline::@2 Successful SSA optimization Pass2ConditionalJumpSimplification Consolidated array index constant in *(SCREEN+$50) Successful SSA optimization Pass2ConstantAdditionElimination @@ -78,7 +76,7 @@ Adding NOP phi() at start of @begin Adding NOP phi() at start of @end CALL GRAPH Calls in [] to main:2 -Calls in [main] to printline:13 +Calls in [main] to printline:12 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes @@ -93,43 +91,41 @@ FINAL CONTROL FLOW GRAPH @1: scope:[] from @begin [1] callprepare main [2] callexecute main - [3] callfinalize main to:@end @end: scope:[] from @1 - [4] phi() + [3] phi() __stackcall (void()) printline() printline: scope:[printline] from - [5] (byte) printline::i ← (byte) 0 + [4] (byte) printline::i ← (byte) 0 to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - [6] if((byte) printline::i<(byte) $28) goto printline::@2 + [5] if((byte) printline::i<(byte) $28) goto printline::@2 to:printline::@return printline::@return: scope:[printline] from printline::@1 - [7] return + [6] return to:@return printline::@2: scope:[printline] from printline::@1 - [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - [9] (byte) printline::i ← ++ (byte) printline::i + [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' + [8] (byte) printline::i ← ++ (byte) printline::i to:printline::@1 __stackcall (void()) main() main: scope:[main] from - [10] (byte) main::val ← (byte) 0 - [11] (byte) main::val ← *((const byte*) SCREEN) - [12] callprepare printline - [13] callexecute printline - [14] callfinalize printline - [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val + [9] (byte) main::val ← (byte) 0 + [10] (byte) main::val ← *((const byte*) SCREEN) + [11] callprepare printline + [12] callexecute printline + [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val to:main::@return main::@return: scope:[main] from main - [16] return + [14] return to:@return VARIABLE REGISTER WEIGHTS __stackcall (void()) main() -(byte) main::val loadstore 1.5 +(byte) main::val loadstore 2.0 __stackcall (void()) printline() (byte) printline::i loadstore 11.5 @@ -161,8 +157,7 @@ __b1: // [1] callprepare main // [2] callexecute main -- jsr jsr main - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end @@ -170,68 +165,67 @@ __bend: // printline printline: { .label i = 2 - // [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // printline::@1 __b1: - // [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 + // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #$28 bcc __b2 jmp __breturn // printline::@return __breturn: - // [7] return + // [6] return rts // printline::@2 __b2: - // [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'*' ldy.z i sta SCREEN,y - // [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 + // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } // main main: { .label val = 3 - // [10] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 + // [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z val - // [11] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 + // [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 lda SCREEN sta.z val - // [12] callprepare printline - // [13] callexecute printline -- jsr + // [11] callprepare printline + // [12] callexecute printline -- jsr jsr printline - // [14] callfinalize printline - // [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 + // [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 jmp __breturn // main::@return __breturn: - // [16] return + // [14] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [5] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:13 [ main::val printline::i ] ) always clobbers reg byte a -Statement [6] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:13 [ main::val printline::i ] ) always clobbers reg byte a -Statement [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:13 [ main::val printline::i ] ) always clobbers reg byte a reg byte y -Statement [10] (byte) main::val ← (byte) 0 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [11] (byte) main::val ← *((const byte*) SCREEN) [ main::val ] ( main:2 [ main::val ] ) always clobbers reg byte a -Statement [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [4] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:12 [ main::val printline::i ] ) always clobbers reg byte a +Statement [5] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:12 [ main::val printline::i ] ) always clobbers reg byte a +Statement [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:12 [ main::val printline::i ] ) always clobbers reg byte a reg byte y +Statement [9] (byte) main::val ← (byte) 0 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [10] (byte) main::val ← *((const byte*) SCREEN) [ main::val ] ( main:2 [ main::val ] ) always clobbers reg byte a +Statement [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val [ ] ( main:2 [ ] ) always clobbers reg byte a Potential registers zp[1]:2 [ printline::i ] : zp[1]:2 , Potential registers zp[1]:3 [ main::val ] : zp[1]:3 , REGISTER UPLIFT SCOPES Uplift Scope [printline] 11.5: zp[1]:2 [ printline::i ] -Uplift Scope [main] 1.5: zp[1]:3 [ main::val ] +Uplift Scope [main] 2: zp[1]:3 [ main::val ] Uplift Scope [] Uplifting [printline] best 372 combination zp[1]:2 [ printline::i ] @@ -260,8 +254,7 @@ __b1: // [1] callprepare main // [2] callexecute main -- jsr jsr main - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end @@ -269,51 +262,50 @@ __bend: // printline printline: { .label i = 2 - // [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // printline::@1 __b1: - // [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 + // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #$28 bcc __b2 jmp __breturn // printline::@return __breturn: - // [7] return + // [6] return rts // printline::@2 __b2: - // [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'*' ldy.z i sta SCREEN,y - // [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 + // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } // main main: { .label val = 3 - // [10] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 + // [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z val - // [11] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 + // [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 lda SCREEN sta.z val - // [12] callprepare printline - // [13] callexecute printline -- jsr + // [11] callprepare printline + // [12] callexecute printline -- jsr jsr printline - // [14] callfinalize printline - // [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 + // [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 jmp __breturn // main::@return __breturn: - // [16] return + // [14] return rts } // File Data @@ -342,7 +334,7 @@ FINAL SYMBOL TABLE (const byte*) SCREEN = (byte*) 1024 __stackcall (void()) main() (label) main::@return -(byte) main::val loadstore zp[1]:3 1.5 +(byte) main::val loadstore zp[1]:3 2.0 __stackcall (void()) printline() (label) printline::@1 (label) printline::@2 @@ -372,36 +364,35 @@ __bbegin: // [2] callexecute main -- jsr jsr main rts - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] // @end // printline printline: { .label i = 2 // i=0 - // [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i // printline::@1 __b1: // for(char i=0; i<40; i++) - // [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 + // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #$28 bcc __b2 // printline::@return // } - // [7] return + // [6] return rts // printline::@2 __b2: // SCREEN[i] = '*' - // [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'*' ldy.z i sta SCREEN,y // for(char i=0; i<40; i++) - // [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 + // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } @@ -409,25 +400,24 @@ printline: { main: { .label val = 3 // val - // [10] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 + // [9] (byte) main::val ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z val // val = *SCREEN - // [11] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 + // [10] (byte) main::val ← *((const byte*) SCREEN) -- vbuz1=_deref_pbuc1 lda SCREEN sta.z val // printline() - // [12] callprepare printline - // [13] callexecute printline -- jsr + // [11] callprepare printline + // [12] callexecute printline -- jsr jsr printline - // [14] callfinalize printline // SCREEN[80] = val - // [15] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 + // [13] *((const byte*) SCREEN+(byte) $50) ← (byte) main::val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 // main::@return // } - // [16] return + // [14] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-7.sym b/src/test/ref/procedure-callingconvention-stack-7.sym index 77a3a89c6..46fa4aa36 100644 --- a/src/test/ref/procedure-callingconvention-stack-7.sym +++ b/src/test/ref/procedure-callingconvention-stack-7.sym @@ -4,7 +4,7 @@ (const byte*) SCREEN = (byte*) 1024 __stackcall (void()) main() (label) main::@return -(byte) main::val loadstore zp[1]:3 1.5 +(byte) main::val loadstore zp[1]:3 2.0 __stackcall (void()) printline() (label) printline::@1 (label) printline::@2 diff --git a/src/test/ref/procedure-callingconvention-stack-8.cfg b/src/test/ref/procedure-callingconvention-stack-8.cfg index 17bd2faea..86ae4a1fd 100644 --- a/src/test/ref/procedure-callingconvention-stack-8.cfg +++ b/src/test/ref/procedure-callingconvention-stack-8.cfg @@ -4,34 +4,32 @@ @1: scope:[] from @begin [1] callprepare main [2] callexecute main - [3] callfinalize main to:@end @end: scope:[] from @1 - [4] phi() + [3] phi() __stackcall (void()) printline() printline: scope:[printline] from - [5] (byte) printline::i ← (byte) 0 + [4] (byte) printline::i ← (byte) 0 to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - [6] if((byte) printline::i<(byte) $28) goto printline::@2 + [5] if((byte) printline::i<(byte) $28) goto printline::@2 to:printline::@return printline::@return: scope:[printline] from printline::@1 - [7] return + [6] return to:@return printline::@2: scope:[printline] from printline::@1 - [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - [9] (byte) printline::i ← ++ (byte) printline::i + [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' + [8] (byte) printline::i ← ++ (byte) printline::i to:printline::@1 __stackcall (void()) main() main: scope:[main] from - [10] (byte) val ← (byte) '-' - [11] callprepare printline - [12] callexecute printline - [13] callfinalize printline - [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val + [9] (byte) val ← (byte) '-' + [10] callprepare printline + [11] callexecute printline + [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val to:main::@return main::@return: scope:[main] from main - [15] return + [13] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-8.log b/src/test/ref/procedure-callingconvention-stack-8.log index b89e8d93b..16c70eecf 100644 --- a/src/test/ref/procedure-callingconvention-stack-8.log +++ b/src/test/ref/procedure-callingconvention-stack-8.log @@ -16,7 +16,6 @@ main: scope:[main] from (byte) val ← (byte) '-' callprepare printline callexecute printline - callfinalize printline *((const byte*) SCREEN + (number) $50) ← (byte) val to:main::@return main::@return: scope:[main] from main @@ -41,7 +40,6 @@ printline::@return: scope:[printline] from printline::@1 @2: scope:[] from @begin callprepare main callexecute main - callfinalize main to:@end @end: scope:[] from @2 @@ -70,14 +68,14 @@ Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) $50 Finalized unsigned number type (byte) $28 Successful SSA optimization PassNFinalizeNumberTypeConversions -Simple Condition (bool~) printline::$0 [9] if((byte) printline::i<(byte) $28) goto printline::@2 +Simple Condition (bool~) printline::$0 [8] if((byte) printline::i<(byte) $28) goto printline::@2 Successful SSA optimization Pass2ConditionalJumpSimplification Consolidated array index constant in *(SCREEN+$50) Successful SSA optimization Pass2ConstantAdditionElimination Adding NOP phi() at start of @end CALL GRAPH Calls in [] to main:2 -Calls in [main] to printline:12 +Calls in [main] to printline:11 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes @@ -91,36 +89,34 @@ FINAL CONTROL FLOW GRAPH @1: scope:[] from @begin [1] callprepare main [2] callexecute main - [3] callfinalize main to:@end @end: scope:[] from @1 - [4] phi() + [3] phi() __stackcall (void()) printline() printline: scope:[printline] from - [5] (byte) printline::i ← (byte) 0 + [4] (byte) printline::i ← (byte) 0 to:printline::@1 printline::@1: scope:[printline] from printline printline::@2 - [6] if((byte) printline::i<(byte) $28) goto printline::@2 + [5] if((byte) printline::i<(byte) $28) goto printline::@2 to:printline::@return printline::@return: scope:[printline] from printline::@1 - [7] return + [6] return to:@return printline::@2: scope:[printline] from printline::@1 - [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' - [9] (byte) printline::i ← ++ (byte) printline::i + [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' + [8] (byte) printline::i ← ++ (byte) printline::i to:printline::@1 __stackcall (void()) main() main: scope:[main] from - [10] (byte) val ← (byte) '-' - [11] callprepare printline - [12] callexecute printline - [13] callfinalize printline - [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val + [9] (byte) val ← (byte) '-' + [10] callprepare printline + [11] callexecute printline + [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val to:main::@return main::@return: scope:[main] from main - [15] return + [13] return to:@return @@ -128,7 +124,7 @@ VARIABLE REGISTER WEIGHTS __stackcall (void()) main() __stackcall (void()) printline() (byte) printline::i loadstore 11.5 -(byte) val loadstore 1.5 +(byte) val loadstore 2.0 Initial phi equivalence classes Added variable val to live range equivalence class [ val ] @@ -162,8 +158,7 @@ __b1: // [1] callprepare main // [2] callexecute main -- jsr jsr main - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end @@ -171,64 +166,63 @@ __bend: // printline printline: { .label i = 3 - // [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // printline::@1 __b1: - // [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 + // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #$28 bcc __b2 jmp __breturn // printline::@return __breturn: - // [7] return + // [6] return rts // printline::@2 __b2: - // [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'*' ldy.z i sta SCREEN,y - // [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 + // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } // main main: { - // [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1 + // [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1 lda #'-' sta.z val - // [11] callprepare printline - // [12] callexecute printline -- jsr + // [10] callprepare printline + // [11] callexecute printline -- jsr jsr printline - // [13] callfinalize printline - // [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 jmp __breturn // main::@return __breturn: - // [15] return + // [13] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] (byte) val ← (byte) 0 [ ] ( [ ] ) always clobbers reg byte a -Statement [5] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:12 [ val printline::i ] ) always clobbers reg byte a -Statement [6] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:12 [ val printline::i ] ) always clobbers reg byte a -Statement [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:12 [ val printline::i ] ) always clobbers reg byte a reg byte y -Statement [10] (byte) val ← (byte) '-' [ val ] ( main:2 [ val ] ) always clobbers reg byte a -Statement [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [4] (byte) printline::i ← (byte) 0 [ printline::i ] ( main:2::printline:11 [ val printline::i ] ) always clobbers reg byte a +Statement [5] if((byte) printline::i<(byte) $28) goto printline::@2 [ printline::i ] ( main:2::printline:11 [ val printline::i ] ) always clobbers reg byte a +Statement [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' [ printline::i ] ( main:2::printline:11 [ val printline::i ] ) always clobbers reg byte a reg byte y +Statement [9] (byte) val ← (byte) '-' [ val ] ( main:2 [ val ] ) always clobbers reg byte a +Statement [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val [ ] ( main:2 [ ] ) always clobbers reg byte a Potential registers zp[1]:2 [ val ] : zp[1]:2 , Potential registers zp[1]:3 [ printline::i ] : zp[1]:3 , REGISTER UPLIFT SCOPES Uplift Scope [printline] 11.5: zp[1]:3 [ printline::i ] -Uplift Scope [] 1.5: zp[1]:2 [ val ] +Uplift Scope [] 2: zp[1]:2 [ val ] Uplift Scope [main] Uplifting [printline] best 343 combination zp[1]:3 [ printline::i ] @@ -261,8 +255,7 @@ __b1: // [1] callprepare main // [2] callexecute main -- jsr jsr main - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end @@ -270,47 +263,46 @@ __bend: // printline printline: { .label i = 3 - // [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // printline::@1 __b1: - // [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 + // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #$28 bcc __b2 jmp __breturn // printline::@return __breturn: - // [7] return + // [6] return rts // printline::@2 __b2: - // [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'*' ldy.z i sta SCREEN,y - // [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 + // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } // main main: { - // [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1 + // [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1 lda #'-' sta.z val - // [11] callprepare printline - // [12] callexecute printline -- jsr + // [10] callprepare printline + // [11] callexecute printline -- jsr jsr printline - // [13] callfinalize printline - // [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 jmp __breturn // main::@return __breturn: - // [15] return + // [13] return rts } // File Data @@ -344,7 +336,7 @@ __stackcall (void()) printline() (label) printline::@2 (label) printline::@return (byte) printline::i loadstore zp[1]:3 11.5 -(byte) val loadstore zp[1]:2 1.5 +(byte) val loadstore zp[1]:2 2.0 zp[1]:2 [ val ] zp[1]:3 [ printline::i ] @@ -374,57 +366,55 @@ __bbegin: // [2] callexecute main -- jsr jsr main rts - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] // @end // printline printline: { .label i = 3 // i=0 - // [5] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printline::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i // printline::@1 __b1: // for(char i=0; i<40; i++) - // [6] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 + // [5] if((byte) printline::i<(byte) $28) goto printline::@2 -- vbuz1_lt_vbuc1_then_la1 lda.z i cmp #$28 bcc __b2 // printline::@return // } - // [7] return + // [6] return rts // printline::@2 __b2: // SCREEN[i] = '*' - // [8] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 + // [7] *((const byte*) SCREEN + (byte) printline::i) ← (byte) '*' -- pbuc1_derefidx_vbuz1=vbuc2 lda #'*' ldy.z i sta SCREEN,y // for(char i=0; i<40; i++) - // [9] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 + // [8] (byte) printline::i ← ++ (byte) printline::i -- vbuz1=_inc_vbuz1 inc.z i jmp __b1 } // main main: { // val = '-' - // [10] (byte) val ← (byte) '-' -- vbuz1=vbuc1 + // [9] (byte) val ← (byte) '-' -- vbuz1=vbuc1 lda #'-' sta.z val // printline() - // [11] callprepare printline - // [12] callexecute printline -- jsr + // [10] callprepare printline + // [11] callexecute printline -- jsr jsr printline - // [13] callfinalize printline // SCREEN[80] = val - // [14] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 + // [12] *((const byte*) SCREEN+(byte) $50) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN+$50 // main::@return // } - // [15] return + // [13] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-8.sym b/src/test/ref/procedure-callingconvention-stack-8.sym index 46f85cb55..bacdce28e 100644 --- a/src/test/ref/procedure-callingconvention-stack-8.sym +++ b/src/test/ref/procedure-callingconvention-stack-8.sym @@ -9,7 +9,7 @@ __stackcall (void()) printline() (label) printline::@2 (label) printline::@return (byte) printline::i loadstore zp[1]:3 11.5 -(byte) val loadstore zp[1]:2 1.5 +(byte) val loadstore zp[1]:2 2.0 zp[1]:2 [ val ] zp[1]:3 [ printline::i ] diff --git a/src/test/ref/procedure-callingconvention-stack-9.cfg b/src/test/ref/procedure-callingconvention-stack-9.cfg index cd2b2f75d..e66c13921 100644 --- a/src/test/ref/procedure-callingconvention-stack-9.cfg +++ b/src/test/ref/procedure-callingconvention-stack-9.cfg @@ -4,77 +4,71 @@ @1: scope:[] from @begin [1] callprepare main [2] callexecute main - [3] callfinalize main to:@end @end: scope:[] from @1 - [4] phi() + [3] phi() __stackcall (void()) printother() printother: scope:[printother] from - [5] (byte) printother::i ← (byte) 0 + [4] (byte) printother::i ← (byte) 0 to:printother::@1 printother::@1: scope:[printother] from printother printother::@1 - [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) - [7] (byte) printother::i ← ++ (byte) printother::i - [8] if((byte) printother::i!=(byte) 6) goto printother::@1 + [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) + [6] (byte) printother::i ← ++ (byte) printother::i + [7] if((byte) printother::i!=(byte) 6) goto printother::@1 to:printother::@return printother::@return: scope:[printother] from printother::@1 - [9] return + [8] return to:@return __stackcall (void()) incval() incval: scope:[incval] from - [10] (byte) val ← ++ (byte) val + [9] (byte) val ← ++ (byte) val to:incval::@return incval::@return: scope:[incval] from incval - [11] return + [10] return to:@return __stackcall (void()) printval() printval: scope:[printval] from - [12] *((const byte*) SCREEN) ← (byte) val + [11] *((const byte*) SCREEN) ← (byte) val to:printval::@return printval::@return: scope:[printval] from printval - [13] return + [12] return to:@return __stackcall (void()) ival() ival: scope:[ival] from - [14] callprepare incval - [15] callexecute incval - [16] callfinalize incval + [13] callprepare incval + [14] callexecute incval to:ival::@return ival::@return: scope:[ival] from ival - [17] return + [15] return to:@return __stackcall (void()) pval() pval: scope:[pval] from - [18] callprepare printval - [19] callexecute printval - [20] callfinalize printval + [16] callprepare printval + [17] callexecute printval to:pval::@return pval::@return: scope:[pval] from pval - [21] return + [18] return to:@return __stackcall (void()) main() main: scope:[main] from - [22] (byte) main::i ← (byte) 0 + [19] (byte) main::i ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@1 - [23] callprepare pval - [24] callexecute pval - [25] callfinalize pval - [26] callprepare printother - [27] callexecute printother - [28] callfinalize printother - [29] callprepare ival - [30] callexecute ival - [31] callfinalize ival - [32] (byte) main::i ← ++ (byte) main::i - [33] if((byte) main::i!=(byte) 6) goto main::@1 + [20] callprepare pval + [21] callexecute pval + [22] callprepare printother + [23] callexecute printother + [24] callprepare ival + [25] callexecute ival + [26] (byte) main::i ← ++ (byte) main::i + [27] if((byte) main::i!=(byte) 6) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - [34] return + [28] return to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-9.log b/src/test/ref/procedure-callingconvention-stack-9.log index 994211a86..57ff1873b 100644 --- a/src/test/ref/procedure-callingconvention-stack-9.log +++ b/src/test/ref/procedure-callingconvention-stack-9.log @@ -24,13 +24,10 @@ main: scope:[main] from main::@1: scope:[main] from main main::@1 callprepare pval callexecute pval - callfinalize pval callprepare printother callexecute printother - callfinalize printother callprepare ival callexecute ival - callfinalize ival (byte) main::i ← (byte) main::i + rangenext(0,5) (bool~) main::$3 ← (byte) main::i != rangelast(0,5) if((bool~) main::$3) goto main::@1 @@ -43,7 +40,6 @@ __stackcall (void()) pval() pval: scope:[pval] from callprepare printval callexecute printval - callfinalize printval to:pval::@return pval::@return: scope:[pval] from pval return @@ -53,7 +49,6 @@ __stackcall (void()) ival() ival: scope:[ival] from callprepare incval callexecute incval - callfinalize incval to:ival::@return ival::@return: scope:[ival] from ival return @@ -91,7 +86,6 @@ printother::@return: scope:[printother] from printother::@1 @6: scope:[] from @begin callprepare main callexecute main - callfinalize main to:@end @end: scope:[] from @6 @@ -130,14 +124,14 @@ Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) $28 Successful SSA optimization PassNFinalizeNumberTypeConversions -Simple Condition (bool~) main::$3 [13] if((byte) main::i!=rangelast(0,5)) goto main::@1 -Simple Condition (bool~) printother::$1 [31] if((byte) printother::i!=rangelast(0,5)) goto printother::@1 +Simple Condition (bool~) main::$3 [10] if((byte) main::i!=rangelast(0,5)) goto main::@1 +Simple Condition (bool~) printother::$1 [26] if((byte) printother::i!=rangelast(0,5)) goto printother::@1 Successful SSA optimization Pass2ConditionalJumpSimplification -Resolved ranged next value [11] main::i ← ++ main::i to ++ -Resolved ranged comparison value [13] if(main::i!=rangelast(0,5)) goto main::@1 to (number) 6 -Resolved ranged next value [29] printother::i ← ++ printother::i to ++ -Resolved ranged comparison value [31] if(printother::i!=rangelast(0,5)) goto printother::@1 to (number) 6 -Simplifying expression containing zero SCREEN in [23] *((const byte*) SCREEN + (byte) 0) ← (byte) val +Resolved ranged next value [8] main::i ← ++ main::i to ++ +Resolved ranged comparison value [10] if(main::i!=rangelast(0,5)) goto main::@1 to (number) 6 +Resolved ranged next value [24] printother::i ← ++ printother::i to ++ +Resolved ranged comparison value [26] if(printother::i!=rangelast(0,5)) goto printother::@1 to (number) 6 +Simplifying expression containing zero SCREEN in [18] *((const byte*) SCREEN + (byte) 0) ← (byte) val Successful SSA optimization PassNSimplifyExpressionWithZero Adding number conversion cast (unumber) 6 in if((byte) main::i!=(number) 6) goto main::@1 Adding number conversion cast (unumber) 6 in if((byte) printother::i!=(number) 6) goto printother::@1 @@ -151,9 +145,9 @@ Successful SSA optimization PassNFinalizeNumberTypeConversions Adding NOP phi() at start of @end CALL GRAPH Calls in [] to main:2 -Calls in [ival] to incval:15 -Calls in [pval] to printval:19 -Calls in [main] to pval:24 printother:27 ival:30 +Calls in [ival] to incval:14 +Calls in [pval] to printval:17 +Calls in [main] to pval:21 printother:23 ival:25 Created 0 initial phi equivalence classes Coalesced down to 0 phi equivalence classes @@ -167,79 +161,73 @@ FINAL CONTROL FLOW GRAPH @1: scope:[] from @begin [1] callprepare main [2] callexecute main - [3] callfinalize main to:@end @end: scope:[] from @1 - [4] phi() + [3] phi() __stackcall (void()) printother() printother: scope:[printother] from - [5] (byte) printother::i ← (byte) 0 + [4] (byte) printother::i ← (byte) 0 to:printother::@1 printother::@1: scope:[printother] from printother printother::@1 - [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) - [7] (byte) printother::i ← ++ (byte) printother::i - [8] if((byte) printother::i!=(byte) 6) goto printother::@1 + [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) + [6] (byte) printother::i ← ++ (byte) printother::i + [7] if((byte) printother::i!=(byte) 6) goto printother::@1 to:printother::@return printother::@return: scope:[printother] from printother::@1 - [9] return + [8] return to:@return __stackcall (void()) incval() incval: scope:[incval] from - [10] (byte) val ← ++ (byte) val + [9] (byte) val ← ++ (byte) val to:incval::@return incval::@return: scope:[incval] from incval - [11] return + [10] return to:@return __stackcall (void()) printval() printval: scope:[printval] from - [12] *((const byte*) SCREEN) ← (byte) val + [11] *((const byte*) SCREEN) ← (byte) val to:printval::@return printval::@return: scope:[printval] from printval - [13] return + [12] return to:@return __stackcall (void()) ival() ival: scope:[ival] from - [14] callprepare incval - [15] callexecute incval - [16] callfinalize incval + [13] callprepare incval + [14] callexecute incval to:ival::@return ival::@return: scope:[ival] from ival - [17] return + [15] return to:@return __stackcall (void()) pval() pval: scope:[pval] from - [18] callprepare printval - [19] callexecute printval - [20] callfinalize printval + [16] callprepare printval + [17] callexecute printval to:pval::@return pval::@return: scope:[pval] from pval - [21] return + [18] return to:@return __stackcall (void()) main() main: scope:[main] from - [22] (byte) main::i ← (byte) 0 + [19] (byte) main::i ← (byte) 0 to:main::@1 main::@1: scope:[main] from main main::@1 - [23] callprepare pval - [24] callexecute pval - [25] callfinalize pval - [26] callprepare printother - [27] callexecute printother - [28] callfinalize printother - [29] callprepare ival - [30] callexecute ival - [31] callfinalize ival - [32] (byte) main::i ← ++ (byte) main::i - [33] if((byte) main::i!=(byte) 6) goto main::@1 + [20] callprepare pval + [21] callexecute pval + [22] callprepare printother + [23] callexecute printother + [24] callprepare ival + [25] callexecute ival + [26] (byte) main::i ← ++ (byte) main::i + [27] if((byte) main::i!=(byte) 6) goto main::@1 to:main::@return main::@return: scope:[main] from main::@1 - [34] return + [28] return to:@return null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope printother @@ -252,12 +240,12 @@ VARIABLE REGISTER WEIGHTS __stackcall (void()) incval() __stackcall (void()) ival() __stackcall (void()) main() -(byte) main::i loadstore 2.9166666666666665 +(byte) main::i loadstore 3.8888888888888893 __stackcall (void()) printother() (byte) printother::i loadstore 14.25 __stackcall (void()) printval() __stackcall (void()) pval() -(byte) val loadstore 0.3076923076923077 +(byte) val loadstore 0.38095238095238093 Initial phi equivalence classes Added variable val to live range equivalence class [ val ] @@ -294,8 +282,7 @@ __b1: // [1] callprepare main // [2] callexecute main -- jsr jsr main - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end @@ -303,123 +290,118 @@ __bend: // printother printother: { .label i = 3 - // [5] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // printother::@1 __b1: - // [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 + // [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 ldx.z i inc SCREEN+$28,x - // [7] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 + // [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 inc.z i - // [8] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 + // [7] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 lda #6 cmp.z i bne __b1 jmp __breturn // printother::@return __breturn: - // [9] return + // [8] return rts } // incval incval: { - // [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 + // [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 inc.z val jmp __breturn // incval::@return __breturn: - // [11] return + // [10] return rts } // printval printval: { - // [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 + // [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN jmp __breturn // printval::@return __breturn: - // [13] return + // [12] return rts } // ival ival: { - // [14] callprepare incval - // [15] callexecute incval -- jsr + // [13] callprepare incval + // [14] callexecute incval -- jsr jsr incval - // [16] callfinalize incval jmp __breturn // ival::@return __breturn: - // [17] return + // [15] return rts } // pval pval: { - // [18] callprepare printval - // [19] callexecute printval -- jsr + // [16] callprepare printval + // [17] callexecute printval -- jsr jsr printval - // [20] callfinalize printval jmp __breturn // pval::@return __breturn: - // [21] return + // [18] return rts } // main main: { .label i = 4 - // [22] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: - // [23] callprepare pval - // [24] callexecute pval -- jsr + // [20] callprepare pval + // [21] callexecute pval -- jsr jsr pval - // [25] callfinalize pval - // [26] callprepare printother - // [27] callexecute printother -- jsr + // [22] callprepare printother + // [23] callexecute printother -- jsr jsr printother - // [28] callfinalize printother - // [29] callprepare ival - // [30] callexecute ival -- jsr + // [24] callprepare ival + // [25] callexecute ival -- jsr jsr ival - // [31] callfinalize ival - // [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [26] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 inc.z i - // [33] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + // [27] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 lda #6 cmp.z i bne __b1 jmp __breturn // main::@return __breturn: - // [34] return + // [28] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS Statement [0] (byte) val ← (byte) 0 [ val ] ( [ val ] ) always clobbers reg byte a -Statement [5] (byte) printother::i ← (byte) 0 [ printother::i ] ( main:2::printother:27 [ val main::i printother::i ] ) always clobbers reg byte a -Statement [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) [ printother::i ] ( main:2::printother:27 [ val main::i printother::i ] ) always clobbers reg byte x -Statement [8] if((byte) printother::i!=(byte) 6) goto printother::@1 [ printother::i ] ( main:2::printother:27 [ val main::i printother::i ] ) always clobbers reg byte a -Statement [12] *((const byte*) SCREEN) ← (byte) val [ val ] ( main:2::pval:24::printval:19 [ main::i val ] ) always clobbers reg byte a -Statement [22] (byte) main::i ← (byte) 0 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a -Statement [33] if((byte) main::i!=(byte) 6) goto main::@1 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a +Statement [4] (byte) printother::i ← (byte) 0 [ printother::i ] ( main:2::printother:23 [ val main::i printother::i ] ) always clobbers reg byte a +Statement [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) [ printother::i ] ( main:2::printother:23 [ val main::i printother::i ] ) always clobbers reg byte x +Statement [7] if((byte) printother::i!=(byte) 6) goto printother::@1 [ printother::i ] ( main:2::printother:23 [ val main::i printother::i ] ) always clobbers reg byte a +Statement [11] *((const byte*) SCREEN) ← (byte) val [ val ] ( main:2::pval:21::printval:17 [ main::i val ] ) always clobbers reg byte a +Statement [19] (byte) main::i ← (byte) 0 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a +Statement [27] if((byte) main::i!=(byte) 6) goto main::@1 [ val main::i ] ( main:2 [ val main::i ] ) always clobbers reg byte a Potential registers zp[1]:2 [ val ] : zp[1]:2 , Potential registers zp[1]:3 [ printother::i ] : zp[1]:3 , Potential registers zp[1]:4 [ main::i ] : zp[1]:4 , REGISTER UPLIFT SCOPES Uplift Scope [printother] 14.25: zp[1]:3 [ printother::i ] -Uplift Scope [main] 2.92: zp[1]:4 [ main::i ] -Uplift Scope [] 0.31: zp[1]:2 [ val ] +Uplift Scope [main] 3.89: zp[1]:4 [ main::i ] +Uplift Scope [] 0.38: zp[1]:2 [ val ] Uplift Scope [pval] Uplift Scope [ival] Uplift Scope [printval] @@ -461,8 +443,7 @@ __b1: // [1] callprepare main // [2] callexecute main -- jsr jsr main - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] __bend_from___b1: jmp __bend // @end @@ -470,103 +451,98 @@ __bend: // printother printother: { .label i = 3 - // [5] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // printother::@1 __b1: - // [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 + // [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 ldx.z i inc SCREEN+$28,x - // [7] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 + // [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 inc.z i - // [8] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 + // [7] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 lda #6 cmp.z i bne __b1 jmp __breturn // printother::@return __breturn: - // [9] return + // [8] return rts } // incval incval: { - // [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 + // [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 inc.z val jmp __breturn // incval::@return __breturn: - // [11] return + // [10] return rts } // printval printval: { - // [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 + // [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN jmp __breturn // printval::@return __breturn: - // [13] return + // [12] return rts } // ival ival: { - // [14] callprepare incval - // [15] callexecute incval -- jsr + // [13] callprepare incval + // [14] callexecute incval -- jsr jsr incval - // [16] callfinalize incval jmp __breturn // ival::@return __breturn: - // [17] return + // [15] return rts } // pval pval: { - // [18] callprepare printval - // [19] callexecute printval -- jsr + // [16] callprepare printval + // [17] callexecute printval -- jsr jsr printval - // [20] callfinalize printval jmp __breturn // pval::@return __breturn: - // [21] return + // [18] return rts } // main main: { .label i = 4 - // [22] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i jmp __b1 // main::@1 __b1: - // [23] callprepare pval - // [24] callexecute pval -- jsr + // [20] callprepare pval + // [21] callexecute pval -- jsr jsr pval - // [25] callfinalize pval - // [26] callprepare printother - // [27] callexecute printother -- jsr + // [22] callprepare printother + // [23] callexecute printother -- jsr jsr printother - // [28] callfinalize printother - // [29] callprepare ival - // [30] callexecute ival -- jsr + // [24] callprepare ival + // [25] callexecute ival -- jsr jsr ival - // [31] callfinalize ival - // [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [26] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 inc.z i - // [33] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + // [27] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 lda #6 cmp.z i bne __b1 jmp __breturn // main::@return __breturn: - // [34] return + // [28] return rts } // File Data @@ -609,7 +585,7 @@ __stackcall (void()) ival() __stackcall (void()) main() (label) main::@1 (label) main::@return -(byte) main::i loadstore zp[1]:4 2.9166666666666665 +(byte) main::i loadstore zp[1]:4 3.8888888888888893 __stackcall (void()) printother() (label) printother::@1 (label) printother::@return @@ -618,7 +594,7 @@ __stackcall (void()) printval() (label) printval::@return __stackcall (void()) pval() (label) pval::@return -(byte) val loadstore zp[1]:2 0.3076923076923077 +(byte) val loadstore zp[1]:2 0.38095238095238093 zp[1]:2 [ val ] zp[1]:3 [ printother::i ] @@ -649,113 +625,107 @@ __bbegin: // [2] callexecute main -- jsr jsr main rts - // [3] callfinalize main - // [4] phi from @1 to @end [phi:@1->@end] + // [3] phi from @1 to @end [phi:@1->@end] // @end // printother printother: { .label i = 3 // for(char i:0..5) - // [5] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 + // [4] (byte) printother::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i // printother::@1 __b1: // (SCREEN+40)[i]++; - // [6] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 + // [5] *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) ← ++ *((const byte*) SCREEN+(byte) $28 + (byte) printother::i) -- pbuc1_derefidx_vbuz1=_inc_pbuc1_derefidx_vbuz1 ldx.z i inc SCREEN+$28,x // for(char i:0..5) - // [7] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 + // [6] (byte) printother::i ← ++ (byte) printother::i -- vbuz1=_inc_vbuz1 inc.z i - // [8] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 + // [7] if((byte) printother::i!=(byte) 6) goto printother::@1 -- vbuz1_neq_vbuc1_then_la1 lda #6 cmp.z i bne __b1 // printother::@return // } - // [9] return + // [8] return rts } // incval incval: { // val++; - // [10] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 + // [9] (byte) val ← ++ (byte) val -- vbuz1=_inc_vbuz1 inc.z val // incval::@return // } - // [11] return + // [10] return rts } // printval printval: { // SCREEN[0] = val - // [12] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 + // [11] *((const byte*) SCREEN) ← (byte) val -- _deref_pbuc1=vbuz1 lda.z val sta SCREEN // printval::@return // } - // [13] return + // [12] return rts } // ival ival: { // incval() - // [14] callprepare incval - // [15] callexecute incval -- jsr + // [13] callprepare incval + // [14] callexecute incval -- jsr jsr incval - // [16] callfinalize incval // ival::@return // } - // [17] return + // [15] return rts } // pval pval: { // printval() - // [18] callprepare printval - // [19] callexecute printval -- jsr + // [16] callprepare printval + // [17] callexecute printval -- jsr jsr printval - // [20] callfinalize printval // pval::@return // } - // [21] return + // [18] return rts } // main main: { .label i = 4 // for(char i:0..5) - // [22] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 + // [19] (byte) main::i ← (byte) 0 -- vbuz1=vbuc1 lda #0 sta.z i // main::@1 __b1: // pval() - // [23] callprepare pval - // [24] callexecute pval -- jsr + // [20] callprepare pval + // [21] callexecute pval -- jsr jsr pval - // [25] callfinalize pval // printother() - // [26] callprepare printother - // [27] callexecute printother -- jsr + // [22] callprepare printother + // [23] callexecute printother -- jsr jsr printother - // [28] callfinalize printother // ival() - // [29] callprepare ival - // [30] callexecute ival -- jsr + // [24] callprepare ival + // [25] callexecute ival -- jsr jsr ival - // [31] callfinalize ival // for(char i:0..5) - // [32] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 + // [26] (byte) main::i ← ++ (byte) main::i -- vbuz1=_inc_vbuz1 inc.z i - // [33] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + // [27] if((byte) main::i!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 lda #6 cmp.z i bne __b1 // main::@return // } - // [34] return + // [28] return rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-9.sym b/src/test/ref/procedure-callingconvention-stack-9.sym index df2fa05e8..878ab6e64 100644 --- a/src/test/ref/procedure-callingconvention-stack-9.sym +++ b/src/test/ref/procedure-callingconvention-stack-9.sym @@ -9,7 +9,7 @@ __stackcall (void()) ival() __stackcall (void()) main() (label) main::@1 (label) main::@return -(byte) main::i loadstore zp[1]:4 2.9166666666666665 +(byte) main::i loadstore zp[1]:4 3.8888888888888893 __stackcall (void()) printother() (label) printother::@1 (label) printother::@return @@ -18,7 +18,7 @@ __stackcall (void()) printval() (label) printval::@return __stackcall (void()) pval() (label) pval::@return -(byte) val loadstore zp[1]:2 0.3076923076923077 +(byte) val loadstore zp[1]:2 0.38095238095238093 zp[1]:2 [ val ] zp[1]:3 [ printother::i ]