diff --git a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java index 90896ad5e..2f43646d1 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ConstantBinary.java @@ -6,6 +6,8 @@ import dk.camelot64.kickc.model.symbols.ProgramScope; import dk.camelot64.kickc.model.types.SymbolType; import dk.camelot64.kickc.model.types.SymbolTypeInference; +import java.util.Objects; + /** A constant defined by a binary operator applied to two constants */ public class ConstantBinary implements ConstantValue { @@ -74,4 +76,18 @@ public class ConstantBinary implements ConstantValue { return toString(null); } + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + ConstantBinary that = (ConstantBinary) o; + return left.equals(that.left) && + operator.equals(that.operator) && + right.equals(that.right); + } + + @Override + public int hashCode() { + return Objects.hash(left, operator, right); + } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 9994af70e..cf068b11a 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -165,6 +165,11 @@ public class TestPrograms { compileAndCompare("examples/conio/nacht-screen.c"); } + @Test + public void testPostIncrementProblem2() throws IOException, URISyntaxException { + compileAndCompare("post-increment-problem-2.c"); + } + @Test public void testPostIncrementProblem() throws IOException, URISyntaxException { compileAndCompare("post-increment-problem.c"); diff --git a/src/test/kc/post-increment-problem-2.c b/src/test/kc/post-increment-problem-2.c new file mode 100644 index 000000000..9e9123d78 --- /dev/null +++ b/src/test/kc/post-increment-problem-2.c @@ -0,0 +1,14 @@ +const byte *screen=$0400; +void main() { + word offset=40*10; + for (char x=0;x<254;x++) + incscreen(offset); +} + + +void incscreen(word ptr) { + --(*(screen+ptr)); + (*(screen+ptr+1))--; + ++(*(screen+ptr)); + (*(screen+ptr+1))++; +} diff --git a/src/test/ref/post-increment-problem-2.asm b/src/test/ref/post-increment-problem-2.asm new file mode 100644 index 000000000..e90fed9ca --- /dev/null +++ b/src/test/ref/post-increment-problem-2.asm @@ -0,0 +1,32 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label screen = $400 +main: { + .label offset = $28*$a + ldx #0 + __b1: + // for (char x=0;x<254;x++) + cpx #$fe + bcc __b2 + // } + rts + __b2: + // incscreen(offset) + jsr incscreen + // for (char x=0;x<254;x++) + inx + jmp __b1 +} +incscreen: { + // --(*(screen+ptr)); + dec screen+main.offset + // (*(screen+ptr+1))--; + dec screen+main.offset+1 + // ++(*(screen+ptr)); + inc screen+main.offset + // (*(screen+ptr+1))++; + inc screen+main.offset+1 + // } + rts +} diff --git a/src/test/ref/post-increment-problem-2.cfg b/src/test/ref/post-increment-problem-2.cfg new file mode 100644 index 000000000..5b4c14a0c --- /dev/null +++ b/src/test/ref/post-increment-problem-2.cfg @@ -0,0 +1,39 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@3 + [5] (byte) main::x#2 ← phi( main/(byte) 0 main::@3/(byte) main::x#1 ) + [6] if((byte) main::x#2<(byte) $fe) goto main::@2 + to:main::@return +main::@return: scope:[main] from main::@1 + [7] return + to:@return +main::@2: scope:[main] from main::@1 + [8] phi() + [9] call incscreen + to:main::@3 +main::@3: scope:[main] from main::@2 + [10] (byte) main::x#1 ← ++ (byte) main::x#2 + to:main::@1 + +(void()) incscreen((word) incscreen::ptr) +incscreen: scope:[incscreen] from main::@2 + [11] *((const to_nomodify byte*) screen+(const word) main::offset) ← -- *((const to_nomodify byte*) screen+(const word) main::offset) + [12] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← -- *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) + [13] *((const to_nomodify byte*) screen+(const word) main::offset) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset) + [14] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) + to:incscreen::@return +incscreen::@return: scope:[incscreen] from incscreen + [15] return + to:@return diff --git a/src/test/ref/post-increment-problem-2.log b/src/test/ref/post-increment-problem-2.log new file mode 100644 index 000000000..451d2d82a --- /dev/null +++ b/src/test/ref/post-increment-problem-2.log @@ -0,0 +1,499 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @1 + (byte) main::x#0 ← (byte) 0 + to:main::@1 +main::@1: scope:[main] from main main::@3 + (byte) main::x#2 ← phi( main/(byte) main::x#0 main::@3/(byte) main::x#1 ) + (bool~) main::$0 ← (byte) main::x#2 < (number) $fe + if((bool~) main::$0) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + (byte) main::x#4 ← phi( main::@1/(byte) main::x#2 ) + (word) incscreen::ptr#0 ← (const word) main::offset + call incscreen + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte) main::x#3 ← phi( main::@2/(byte) main::x#4 ) + (byte) main::x#1 ← ++ (byte) main::x#3 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return + +(void()) incscreen((word) incscreen::ptr) +incscreen: scope:[incscreen] from main::@2 + (word) incscreen::ptr#1 ← phi( main::@2/(word) incscreen::ptr#0 ) + (byte*~) incscreen::$0 ← (const to_nomodify byte*) screen + (word) incscreen::ptr#1 + *((byte*~) incscreen::$0) ← -- *((byte*~) incscreen::$0) + (byte*~) incscreen::$9 ← (const to_nomodify byte*) screen + (word) incscreen::ptr#1 + (byte*~) incscreen::$10 ← (byte*~) incscreen::$9 + (number) 1 + *((byte*~) incscreen::$10) ← -- *((byte*~) incscreen::$10) + (byte*~) incscreen::$11 ← (const to_nomodify byte*) screen + (word) incscreen::ptr#1 + *((byte*~) incscreen::$11) ← ++ *((byte*~) incscreen::$11) + (byte*~) incscreen::$20 ← (const to_nomodify byte*) screen + (word) incscreen::ptr#1 + (byte*~) incscreen::$21 ← (byte*~) incscreen::$20 + (number) 1 + *((byte*~) incscreen::$21) ← ++ *((byte*~) incscreen::$21) + to:incscreen::@return +incscreen::@return: scope:[incscreen] from incscreen + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(void()) incscreen((word) incscreen::ptr) +(byte*~) incscreen::$0 +(byte*~) incscreen::$10 +(byte*~) incscreen::$11 +(byte*~) incscreen::$20 +(byte*~) incscreen::$21 +(byte*~) incscreen::$9 +(label) incscreen::@return +(word) incscreen::ptr +(word) incscreen::ptr#0 +(word) incscreen::ptr#1 +(void()) main() +(bool~) main::$0 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(const word) main::offset = (word)(number) $28*(number) $a +(byte) main::x +(byte) main::x#0 +(byte) main::x#1 +(byte) main::x#2 +(byte) main::x#3 +(byte) main::x#4 +(const to_nomodify byte*) screen = (byte*)(number) $400 + +Adding number conversion cast (unumber) $fe in (bool~) main::$0 ← (byte) main::x#2 < (number) $fe +Adding number conversion cast (unumber) 1 in (byte*~) incscreen::$10 ← (byte*~) incscreen::$9 + (number) 1 +Adding number conversion cast (unumber) 1 in (byte*~) incscreen::$21 ← (byte*~) incscreen::$20 + (number) 1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast $fe +Simplifying constant integer cast 1 +Simplifying constant integer cast 1 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) $fe +Finalized unsigned number type (byte) 1 +Finalized unsigned number type (byte) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias main::x#2 = main::x#4 main::x#3 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values (word) incscreen::ptr#1 (word) incscreen::ptr#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Simple Condition (bool~) main::$0 [3] if((byte) main::x#2<(byte) $fe) goto main::@2 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte) main::x#0 = 0 +Constant (const word) incscreen::ptr#0 = main::offset +Successful SSA optimization Pass2ConstantIdentification +Converting *(pointer+n) to pointer[n] [13] *((byte*~) incscreen::$10) ← -- *((byte*~) incscreen::$10) -- *(incscreen::$9 + 1) +Converting *(pointer+n) to pointer[n] [13] *((byte*~) incscreen::$10) ← -- *((byte*~) incscreen::$9 + (byte) 1) -- *(incscreen::$9 + 1) +Converting *(pointer+n) to pointer[n] [18] *((byte*~) incscreen::$21) ← ++ *((byte*~) incscreen::$21) -- *(incscreen::$20 + 1) +Converting *(pointer+n) to pointer[n] [18] *((byte*~) incscreen::$21) ← ++ *((byte*~) incscreen::$20 + (byte) 1) -- *(incscreen::$20 + 1) +Successful SSA optimization Pass2InlineDerefIdx +Eliminating unused variable (byte*~) incscreen::$10 and assignment [8] (byte*~) incscreen::$10 ← (byte*~) incscreen::$9 + (byte) 1 +Eliminating unused variable (byte*~) incscreen::$21 and assignment [13] (byte*~) incscreen::$21 ← (byte*~) incscreen::$20 + (byte) 1 +Successful SSA optimization PassNEliminateUnusedVars +Constant right-side identified [5] (byte*~) incscreen::$0 ← (const to_nomodify byte*) screen + (const word) incscreen::ptr#0 +Constant right-side identified [7] (byte*~) incscreen::$9 ← (const to_nomodify byte*) screen + (const word) incscreen::ptr#0 +Constant right-side identified [9] (byte*~) incscreen::$11 ← (const to_nomodify byte*) screen + (const word) incscreen::ptr#0 +Constant right-side identified [11] (byte*~) incscreen::$20 ← (const to_nomodify byte*) screen + (const word) incscreen::ptr#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte*) incscreen::$0 = screen+incscreen::ptr#0 +Constant (const byte*) incscreen::$9 = screen+incscreen::ptr#0 +Constant (const byte*) incscreen::$11 = screen+incscreen::ptr#0 +Constant (const byte*) incscreen::$20 = screen+incscreen::ptr#0 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with var siblings (const byte) main::x#0 +Constant inlined incscreen::$0 = (const to_nomodify byte*) screen+(const word) main::offset +Constant inlined incscreen::$9 = (const to_nomodify byte*) screen+(const word) main::offset +Constant inlined incscreen::$20 = (const to_nomodify byte*) screen+(const word) main::offset +Constant inlined main::x#0 = (byte) 0 +Constant inlined incscreen::$11 = (const to_nomodify byte*) screen+(const word) main::offset +Constant inlined incscreen::ptr#0 = (const word) main::offset +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(screen+main::offset+1) +Consolidated array index constant in *(screen+main::offset+1) +Consolidated array index constant in *(screen+main::offset+1) +Consolidated array index constant in *(screen+main::offset+1) +Successful SSA optimization Pass2ConstantAdditionElimination +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@2 +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to incscreen:10 + +Created 1 initial phi equivalence classes +Coalesced [12] main::x#5 ← main::x#1 +Coalesced down to 1 phi equivalence classes +Culled Empty Block (label) @2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@2 + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() + +(void()) main() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@3 + [5] (byte) main::x#2 ← phi( main/(byte) 0 main::@3/(byte) main::x#1 ) + [6] if((byte) main::x#2<(byte) $fe) goto main::@2 + to:main::@return +main::@return: scope:[main] from main::@1 + [7] return + to:@return +main::@2: scope:[main] from main::@1 + [8] phi() + [9] call incscreen + to:main::@3 +main::@3: scope:[main] from main::@2 + [10] (byte) main::x#1 ← ++ (byte) main::x#2 + to:main::@1 + +(void()) incscreen((word) incscreen::ptr) +incscreen: scope:[incscreen] from main::@2 + [11] *((const to_nomodify byte*) screen+(const word) main::offset) ← -- *((const to_nomodify byte*) screen+(const word) main::offset) + [12] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← -- *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) + [13] *((const to_nomodify byte*) screen+(const word) main::offset) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset) + [14] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) + to:incscreen::@return +incscreen::@return: scope:[incscreen] from incscreen + [15] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) incscreen((word) incscreen::ptr) +(word) incscreen::ptr +(void()) main() +(byte) main::x +(byte) main::x#1 202.0 +(byte) main::x#2 75.75 + +Initial phi equivalence classes +[ main::x#2 main::x#1 ] +Complete equivalence classes +[ main::x#2 main::x#1 ] +Allocated zp[1]:2 [ main::x#2 main::x#1 ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label screen = $400 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from___b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .label offset = $28*$a + .label x = 2 + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) main::x#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z x + jmp __b1 + // main::@1 + __b1: + // [6] if((byte) main::x#2<(byte) $fe) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + lda.z x + cmp #$fe + bcc __b2_from___b1 + jmp __breturn + // main::@return + __breturn: + // [7] return + rts + // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + __b2_from___b1: + jmp __b2 + // main::@2 + __b2: + // [9] call incscreen + jsr incscreen + jmp __b3 + // main::@3 + __b3: + // [10] (byte) main::x#1 ← ++ (byte) main::x#2 -- vbuz1=_inc_vbuz1 + inc.z x + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + __b1_from___b3: + // [5] phi (byte) main::x#2 = (byte) main::x#1 [phi:main::@3->main::@1#0] -- register_copy + jmp __b1 +} + // incscreen +incscreen: { + // [11] *((const to_nomodify byte*) screen+(const word) main::offset) ← -- *((const to_nomodify byte*) screen+(const word) main::offset) -- _deref_pbuc1=_dec__deref_pbuc1 + dec screen+main.offset + // [12] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← -- *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) -- _deref_pbuc1=_dec__deref_pbuc1 + dec screen+main.offset+1 + // [13] *((const to_nomodify byte*) screen+(const word) main::offset) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset) -- _deref_pbuc1=_inc__deref_pbuc1 + inc screen+main.offset + // [14] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) -- _deref_pbuc1=_inc__deref_pbuc1 + inc screen+main.offset+1 + jmp __breturn + // incscreen::@return + __breturn: + // [15] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Potential registers zp[1]:2 [ main::x#2 main::x#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 277.75: zp[1]:2 [ main::x#2 main::x#1 ] +Uplift Scope [incscreen] +Uplift Scope [] + +Uplifting [main] best 346 combination reg byte x [ main::x#2 main::x#1 ] +Uplifting [incscreen] best 346 combination +Uplifting [] best 346 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label screen = $400 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from___b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .label offset = $28*$a + // [5] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [5] phi (byte) main::x#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + jmp __b1 + // main::@1 + __b1: + // [6] if((byte) main::x#2<(byte) $fe) goto main::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$fe + bcc __b2_from___b1 + jmp __breturn + // main::@return + __breturn: + // [7] return + rts + // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + __b2_from___b1: + jmp __b2 + // main::@2 + __b2: + // [9] call incscreen + jsr incscreen + jmp __b3 + // main::@3 + __b3: + // [10] (byte) main::x#1 ← ++ (byte) main::x#2 -- vbuxx=_inc_vbuxx + inx + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + __b1_from___b3: + // [5] phi (byte) main::x#2 = (byte) main::x#1 [phi:main::@3->main::@1#0] -- register_copy + jmp __b1 +} + // incscreen +incscreen: { + // [11] *((const to_nomodify byte*) screen+(const word) main::offset) ← -- *((const to_nomodify byte*) screen+(const word) main::offset) -- _deref_pbuc1=_dec__deref_pbuc1 + dec screen+main.offset + // [12] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← -- *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) -- _deref_pbuc1=_dec__deref_pbuc1 + dec screen+main.offset+1 + // [13] *((const to_nomodify byte*) screen+(const word) main::offset) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset) -- _deref_pbuc1=_inc__deref_pbuc1 + inc screen+main.offset + // [14] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) -- _deref_pbuc1=_inc__deref_pbuc1 + inc screen+main.offset+1 + jmp __breturn + // incscreen::@return + __breturn: + // [15] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b2 +Removing instruction jmp __b3 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __b2_from___b1 with __b2 +Removing instruction __b1_from___bbegin: +Removing instruction __b1: +Removing instruction main_from___b1: +Removing instruction __bend_from___b1: +Removing instruction __b2_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __bend: +Removing instruction __b1_from_main: +Removing instruction __breturn: +Removing instruction __b3: +Removing instruction __b1_from___b3: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction __bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) incscreen((word) incscreen::ptr) +(label) incscreen::@return +(word) incscreen::ptr +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(const word) main::offset = (word)(number) $28*(number) $a +(byte) main::x +(byte) main::x#1 reg byte x 202.0 +(byte) main::x#2 reg byte x 75.75 +(const to_nomodify byte*) screen = (byte*) 1024 + +reg byte x [ main::x#2 main::x#1 ] + + +FINAL ASSEMBLER +Score: 211 + + // File Comments + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label screen = $400 + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [4] phi from @1 to main [phi:@1->main] + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + .label offset = $28*$a + // [5] phi from main to main::@1 [phi:main->main::@1] + // [5] phi (byte) main::x#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + // main::@1 + __b1: + // for (char x=0;x<254;x++) + // [6] if((byte) main::x#2<(byte) $fe) goto main::@2 -- vbuxx_lt_vbuc1_then_la1 + cpx #$fe + bcc __b2 + // main::@return + // } + // [7] return + rts + // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + // main::@2 + __b2: + // incscreen(offset) + // [9] call incscreen + jsr incscreen + // main::@3 + // for (char x=0;x<254;x++) + // [10] (byte) main::x#1 ← ++ (byte) main::x#2 -- vbuxx=_inc_vbuxx + inx + // [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + // [5] phi (byte) main::x#2 = (byte) main::x#1 [phi:main::@3->main::@1#0] -- register_copy + jmp __b1 +} + // incscreen +incscreen: { + // --(*(screen+ptr)); + // [11] *((const to_nomodify byte*) screen+(const word) main::offset) ← -- *((const to_nomodify byte*) screen+(const word) main::offset) -- _deref_pbuc1=_dec__deref_pbuc1 + dec screen+main.offset + // (*(screen+ptr+1))--; + // [12] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← -- *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) -- _deref_pbuc1=_dec__deref_pbuc1 + dec screen+main.offset+1 + // ++(*(screen+ptr)); + // [13] *((const to_nomodify byte*) screen+(const word) main::offset) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset) -- _deref_pbuc1=_inc__deref_pbuc1 + inc screen+main.offset + // (*(screen+ptr+1))++; + // [14] *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) ← ++ *((const to_nomodify byte*) screen+(const word) main::offset+(byte) 1) -- _deref_pbuc1=_inc__deref_pbuc1 + inc screen+main.offset+1 + // incscreen::@return + // } + // [15] return + rts +} + // File Data + diff --git a/src/test/ref/post-increment-problem-2.sym b/src/test/ref/post-increment-problem-2.sym new file mode 100644 index 000000000..d783dace9 --- /dev/null +++ b/src/test/ref/post-increment-problem-2.sym @@ -0,0 +1,18 @@ +(label) @1 +(label) @begin +(label) @end +(void()) incscreen((word) incscreen::ptr) +(label) incscreen::@return +(word) incscreen::ptr +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(const word) main::offset = (word)(number) $28*(number) $a +(byte) main::x +(byte) main::x#1 reg byte x 202.0 +(byte) main::x#2 reg byte x 75.75 +(const to_nomodify byte*) screen = (byte*) 1024 + +reg byte x [ main::x#2 main::x#1 ]