From ad6eadad0b96ba1076ec3512e815c18ae36bd30e Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 16 Jun 2019 21:48:13 +0200 Subject: [PATCH] Added another struct address-of test passing the pointer to a procedure. --- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/struct-ptr-14.kc | 19 + src/test/ref/struct-ptr-14.asm | 28 + src/test/ref/struct-ptr-14.cfg | 28 + src/test/ref/struct-ptr-14.log | 487 ++++++++++++++++++ src/test/ref/struct-ptr-14.sym | 24 + 6 files changed, 591 insertions(+) create mode 100644 src/test/kc/struct-ptr-14.kc create mode 100644 src/test/ref/struct-ptr-14.asm create mode 100644 src/test/ref/struct-ptr-14.cfg create mode 100644 src/test/ref/struct-ptr-14.log create mode 100644 src/test/ref/struct-ptr-14.sym diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index edd1f35fa..2d457d916 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -68,6 +68,11 @@ public class TestPrograms { compileAndCompare("textbox"); } + @Test + public void testStructPtr14() throws IOException, URISyntaxException { + compileAndCompare("struct-ptr-14"); + } + @Test public void testStructPtr13() throws IOException, URISyntaxException { compileAndCompare("struct-ptr-13"); diff --git a/src/test/kc/struct-ptr-14.kc b/src/test/kc/struct-ptr-14.kc new file mode 100644 index 000000000..0d8e0d5cf --- /dev/null +++ b/src/test/kc/struct-ptr-14.kc @@ -0,0 +1,19 @@ +// Minimal struct - using address-of and passing it to a function +struct Point { + byte x; + byte y; +}; + +void main() { + volatile struct Point p = { 2, 3 }; + struct Point *q = &p; + set(q); + const byte* SCREEN = 0x0400; + SCREEN[0] = q->x; + SCREEN[1] = q->y; +} + +void set(struct Point *ptr) { + ptr->x = 4; + ptr->y = 5; +} \ No newline at end of file diff --git a/src/test/ref/struct-ptr-14.asm b/src/test/ref/struct-ptr-14.asm new file mode 100644 index 000000000..fd831283c --- /dev/null +++ b/src/test/ref/struct-ptr-14.asm @@ -0,0 +1,28 @@ +// Minimal struct - using address-of and passing it to a function +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const OFFSET_STRUCT_POINT_Y = 1 +main: { + .label q = p_x + .label SCREEN = $400 + .label p_x = 2 + .label p_y = 3 + lda #2 + sta p_x + lda #3 + sta p_y + jsr set + lda q + sta SCREEN + lda q+OFFSET_STRUCT_POINT_Y + sta SCREEN+1 + rts +} +set: { + lda #4 + sta main.q + lda #5 + sta main.q+OFFSET_STRUCT_POINT_Y + rts +} diff --git a/src/test/ref/struct-ptr-14.cfg b/src/test/ref/struct-ptr-14.cfg new file mode 100644 index 000000000..7a3301bf6 --- /dev/null +++ b/src/test/ref/struct-ptr-14.cfg @@ -0,0 +1,28 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() +main: scope:[main] from @1 + [4] (byte) main::p_x#0 ← (byte) 2 + [5] (byte) main::p_y#0 ← (byte) 3 + [6] call set + to:main::@1 +main::@1: scope:[main] from main + [7] *((const byte*) main::SCREEN#0) ← *((byte*)(const struct Point*) main::q#0) + [8] *((const byte*) main::SCREEN#0+(byte) 1) ← *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return + to:@return +set: scope:[set] from main + [10] *((byte*)(const struct Point*) main::q#0) ← (byte) 4 + [11] *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 + to:set::@return +set::@return: scope:[set] from set + [12] return + to:@return diff --git a/src/test/ref/struct-ptr-14.log b/src/test/ref/struct-ptr-14.log new file mode 100644 index 000000000..c8c06ff01 --- /dev/null +++ b/src/test/ref/struct-ptr-14.log @@ -0,0 +1,487 @@ +Created struct value member variable (byte) main::p_x +Created struct value member variable (byte) main::p_y +Converted struct value to member variables (struct Point) main::p +Adding struct value list initializer (byte) main::p_x ← (number) 2 +Adding struct value list initializer (byte) main::p_y ← (number) 3 +Rewriting struct pointer member access *((struct Point*) main::q).x +Rewriting struct pointer member access *((struct Point*) main::q).y +Rewriting struct pointer member access *((struct Point*) set::ptr).x +Rewriting struct pointer member access *((struct Point*) set::ptr).y +Adding pointer type conversion cast (byte*) main::SCREEN in (byte*) main::SCREEN ← (number) $400 +Culled Empty Block (label) @1 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@2 +main: scope:[main] from @2 + (byte) main::p_x#0 ← (number) 2 + (byte) main::p_y#0 ← (number) 3 + (struct Point) main::p#0 ← struct-unwound {(byte) main::p_x#0, (byte) main::p_y#0} + (struct Point*~) main::$0 ← & (struct Point) main::p#0 + (struct Point*) main::q#0 ← (struct Point*~) main::$0 + (struct Point*) set::ptr#0 ← (struct Point*) main::q#0 + call set + to:main::@1 +main::@1: scope:[main] from main + (struct Point*) main::q#1 ← phi( main/(struct Point*) main::q#0 ) + (byte*) main::SCREEN#0 ← ((byte*)) (number) $400 + (byte*) main::$2 ← (byte*)(struct Point*) main::q#1 + (const byte) OFFSET_STRUCT_POINT_X + *((byte*) main::SCREEN#0 + (number) 0) ← *((byte*) main::$2) + (byte*) main::$3 ← (byte*)(struct Point*) main::q#1 + (const byte) OFFSET_STRUCT_POINT_Y + *((byte*) main::SCREEN#0 + (number) 1) ← *((byte*) main::$3) + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +set: scope:[set] from main + (struct Point*) set::ptr#1 ← phi( main/(struct Point*) set::ptr#0 ) + (byte*) set::$0 ← (byte*)(struct Point*) set::ptr#1 + (const byte) OFFSET_STRUCT_POINT_X + *((byte*) set::$0) ← (number) 4 + (byte*) set::$1 ← (byte*)(struct Point*) set::ptr#1 + (const byte) OFFSET_STRUCT_POINT_Y + *((byte*) set::$1) ← (number) 5 + to:set::@return +set::@return: scope:[set] from set + return + to:@return +@2: scope:[] from @begin + call main + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +SYMBOL TABLE SSA +(label) @2 +(label) @3 +(label) @begin +(label) @end +(const byte) OFFSET_STRUCT_POINT_X = (byte) 0 +(const byte) OFFSET_STRUCT_POINT_Y = (byte) 1 +(byte) Point::x +(byte) Point::y +(void()) main() +(struct Point*~) main::$0 +(byte*) main::$2 +(byte*) main::$3 +(label) main::@1 +(label) main::@return +(byte*) main::SCREEN +(byte*) main::SCREEN#0 +(struct Point) main::p +(struct Point) main::p#0 +(byte) main::p_x +(byte) main::p_x#0 +(byte) main::p_y +(byte) main::p_y#0 +(struct Point*) main::q +(struct Point*) main::q#0 +(struct Point*) main::q#1 +(void()) set((struct Point*) set::ptr) +(byte*) set::$0 +(byte*) set::$1 +(label) set::@return +(struct Point*) set::ptr +(struct Point*) set::ptr#0 +(struct Point*) set::ptr#1 + +Adding number conversion cast (unumber) 2 in (byte) main::p_x#0 ← (number) 2 +Adding number conversion cast (unumber) 3 in (byte) main::p_y#0 ← (number) 3 +Adding number conversion cast (unumber) 0 in *((byte*) main::SCREEN#0 + (number) 0) ← *((byte*) main::$2) +Adding number conversion cast (unumber) 1 in *((byte*) main::SCREEN#0 + (number) 1) ← *((byte*) main::$3) +Adding number conversion cast (unumber) 4 in *((byte*) set::$0) ← (number) 4 +Adding number conversion cast (unumber) 5 in *((byte*) set::$1) ← (number) 5 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (byte) main::p_x#0 ← (unumber)(number) 2 +Inlining cast (byte) main::p_y#0 ← (unumber)(number) 3 +Inlining cast (byte*) main::SCREEN#0 ← (byte*)(number) $400 +Inlining cast *((byte*) set::$0) ← (unumber)(number) 4 +Inlining cast *((byte*) set::$1) ← (unumber)(number) 5 +Successful SSA optimization Pass2InlineCast +Simplifying constant integer cast 2 +Simplifying constant integer cast 3 +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast 0 +Simplifying constant integer cast 1 +Simplifying constant integer cast 4 +Simplifying constant integer cast 5 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 2 +Finalized unsigned number type (byte) 3 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 1 +Finalized unsigned number type (byte) 4 +Finalized unsigned number type (byte) 5 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias (struct Point*) main::q#0 = (struct Point*~) main::$0 (struct Point*) main::q#1 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values (struct Point*) set::ptr#1 (struct Point*) set::ptr#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Rewriting struct address-of to first member [3] (struct Point*) main::q#0 ← (struct Point*)&(byte) main::p_x#0 +Successful SSA optimization PassNStructAddressOfRewriting +Constant right-side identified [3] (struct Point*) main::q#0 ← (struct Point*)&(byte) main::p_x#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const struct Point*) main::q#0 = (struct Point*)&main::p_x#0 +Constant (const byte*) main::SCREEN#0 = (byte*) 1024 +Successful SSA optimization Pass2ConstantIdentification +Constant (const struct Point*) set::ptr#0 = main::q#0 +Successful SSA optimization Pass2ConstantIdentification +Constant value identified (byte*)main::q#0 in [9] (byte*) main::$2 ← (byte*)(const struct Point*) main::q#0 + (const byte) OFFSET_STRUCT_POINT_X +Constant value identified (byte*)main::q#0 in [11] (byte*) main::$3 ← (byte*)(const struct Point*) main::q#0 + (const byte) OFFSET_STRUCT_POINT_Y +Constant value identified (byte*)set::ptr#0 in [15] (byte*) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X +Constant value identified (byte*)set::ptr#0 in [17] (byte*) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y +Successful SSA optimization Pass2ConstantValues +Converting *(pointer+n) to pointer[n] [10] *((const byte*) main::SCREEN#0 + (byte) 0) ← *((byte*) main::$2) -- *((byte*)main::q#0 + OFFSET_STRUCT_POINT_X) +Converting *(pointer+n) to pointer[n] [12] *((const byte*) main::SCREEN#0 + (byte) 1) ← *((byte*) main::$3) -- *((byte*)main::q#0 + OFFSET_STRUCT_POINT_Y) +Converting *(pointer+n) to pointer[n] [16] *((byte*) set::$0) ← (byte) 4 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_X) +Converting *(pointer+n) to pointer[n] [18] *((byte*) set::$1) ← (byte) 5 -- *((byte*)set::ptr#0 + OFFSET_STRUCT_POINT_Y) +Successful SSA optimization Pass2InlineDerefIdx +Simplifying expression containing zero (byte*)main::q#0 in [9] (byte*) main::$2 ← (byte*)(const struct Point*) main::q#0 + (const byte) OFFSET_STRUCT_POINT_X +Simplifying expression containing zero (byte*)main::q#0 in [10] *((const byte*) main::SCREEN#0 + (byte) 0) ← *((byte*)(const struct Point*) main::q#0 + (const byte) OFFSET_STRUCT_POINT_X) +Simplifying expression containing zero main::SCREEN#0 in [10] *((const byte*) main::SCREEN#0 + (byte) 0) ← *((byte*)(const struct Point*) main::q#0) +Simplifying expression containing zero (byte*)set::ptr#0 in [15] (byte*) set::$0 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X +Simplifying expression containing zero (byte*)set::ptr#0 in [16] *((byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) 4 +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused variable (struct Point) main::p#0 and assignment [2] (struct Point) main::p#0 ← struct-unwound {(byte) main::p_x#0, (byte) main::p_y#0} +Eliminating unused variable (byte*) main::$2 and assignment [4] (byte*) main::$2 ← (byte*)(const struct Point*) main::q#0 +Eliminating unused variable (byte*) main::$3 and assignment [6] (byte*) main::$3 ← (byte*)(const struct Point*) main::q#0 + (const byte) OFFSET_STRUCT_POINT_Y +Eliminating unused variable (byte*) set::$0 and assignment [9] (byte*) set::$0 ← (byte*)(const struct Point*) set::ptr#0 +Eliminating unused variable (byte*) set::$1 and assignment [11] (byte*) set::$1 ← (byte*)(const struct Point*) set::ptr#0 + (const byte) OFFSET_STRUCT_POINT_Y +Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X +Successful SSA optimization PassNEliminateUnusedVars +Constant inlined set::ptr#0 = (const struct Point*) main::q#0 +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *((byte*)main::q#0+OFFSET_STRUCT_POINT_Y) +Consolidated array index constant in *(main::SCREEN#0+1) +Consolidated array index constant in *((byte*)main::q#0+OFFSET_STRUCT_POINT_Y) +Successful SSA optimization Pass2ConstantAdditionElimination +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @3 +Adding NOP phi() at start of @end +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to set:7 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @3 +Renumbering block @2 to @1 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end + +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() +main: scope:[main] from @1 + [4] (byte) main::p_x#0 ← (byte) 2 + [5] (byte) main::p_y#0 ← (byte) 3 + [6] call set + to:main::@1 +main::@1: scope:[main] from main + [7] *((const byte*) main::SCREEN#0) ← *((byte*)(const struct Point*) main::q#0) + [8] *((const byte*) main::SCREEN#0+(byte) 1) ← *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) + to:main::@return +main::@return: scope:[main] from main::@1 + [9] return + to:@return +set: scope:[set] from main + [10] *((byte*)(const struct Point*) main::q#0) ← (byte) 4 + [11] *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 + to:set::@return +set::@return: scope:[set] from set + [12] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) Point::x +(byte) Point::y +(void()) main() +(byte*) main::SCREEN +(struct Point) main::p +(byte) main::p_x +(byte) main::p_x#0 20.0 +(byte) main::p_y +(byte) main::p_y#0 20.0 +(struct Point*) main::q +(void()) set((struct Point*) set::ptr) +(struct Point*) set::ptr + +Initial phi equivalence classes +Complete equivalence classes +[ main::p_x#0 ] +[ main::p_y#0 ] +Allocated zp ZP_BYTE:2 [ main::p_x#0 ] +Allocated zp ZP_BYTE:3 [ main::p_y#0 ] + +INITIAL ASM +//SEG0 File Comments +// Minimal struct - using address-of and passing it to a function +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const OFFSET_STRUCT_POINT_Y = 1 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + .label q = p_x + .label SCREEN = $400 + .label p_x = 2 + .label p_y = 3 + //SEG10 [4] (byte) main::p_x#0 ← (byte) 2 -- vbuz1=vbuc1 + lda #2 + sta p_x + //SEG11 [5] (byte) main::p_y#0 ← (byte) 3 -- vbuz1=vbuc1 + lda #3 + sta p_y + //SEG12 [6] call set + jsr set + jmp b1 + //SEG13 main::@1 + b1: + //SEG14 [7] *((const byte*) main::SCREEN#0) ← *((byte*)(const struct Point*) main::q#0) -- _deref_pbuc1=_deref_pbuc2 + lda q + sta SCREEN + //SEG15 [8] *((const byte*) main::SCREEN#0+(byte) 1) ← *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda q+OFFSET_STRUCT_POINT_Y + sta SCREEN+1 + jmp breturn + //SEG16 main::@return + breturn: + //SEG17 [9] return + rts +} +//SEG18 set +set: { + //SEG19 [10] *((byte*)(const struct Point*) main::q#0) ← (byte) 4 -- _deref_pbuc1=vbuc2 + lda #4 + sta main.q + //SEG20 [11] *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2 + lda #5 + sta main.q+OFFSET_STRUCT_POINT_Y + jmp breturn + //SEG21 set::@return + breturn: + //SEG22 [12] return + rts +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] (byte) main::p_x#0 ← (byte) 2 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [5] (byte) main::p_y#0 ← (byte) 3 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [7] *((const byte*) main::SCREEN#0) ← *((byte*)(const struct Point*) main::q#0) [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [8] *((const byte*) main::SCREEN#0+(byte) 1) ← *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [10] *((byte*)(const struct Point*) main::q#0) ← (byte) 4 [ ] ( main:2::set:6 [ ] ) always clobbers reg byte a +Statement [11] *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 [ ] ( main:2::set:6 [ ] ) always clobbers reg byte a +Potential registers zp ZP_BYTE:2 [ main::p_x#0 ] : zp ZP_BYTE:2 , +Potential registers zp ZP_BYTE:3 [ main::p_y#0 ] : zp ZP_BYTE:3 , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 20: zp ZP_BYTE:2 [ main::p_x#0 ] 20: zp ZP_BYTE:3 [ main::p_y#0 ] +Uplift Scope [Point] +Uplift Scope [set] +Uplift Scope [] + +Uplifting [main] best 77 combination zp ZP_BYTE:2 [ main::p_x#0 ] zp ZP_BYTE:3 [ main::p_y#0 ] +Uplifting [Point] best 77 combination +Uplifting [set] best 77 combination +Uplifting [] best 77 combination +Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::p_x#0 ] +Uplifting [main] best 77 combination zp ZP_BYTE:2 [ main::p_x#0 ] +Attempting to uplift remaining variables inzp ZP_BYTE:3 [ main::p_y#0 ] +Uplifting [main] best 77 combination zp ZP_BYTE:3 [ main::p_y#0 ] + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 File Comments +// Minimal struct - using address-of and passing it to a function +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const OFFSET_STRUCT_POINT_Y = 1 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + .label q = p_x + .label SCREEN = $400 + .label p_x = 2 + .label p_y = 3 + //SEG10 [4] (byte) main::p_x#0 ← (byte) 2 -- vbuz1=vbuc1 + lda #2 + sta p_x + //SEG11 [5] (byte) main::p_y#0 ← (byte) 3 -- vbuz1=vbuc1 + lda #3 + sta p_y + //SEG12 [6] call set + jsr set + jmp b1 + //SEG13 main::@1 + b1: + //SEG14 [7] *((const byte*) main::SCREEN#0) ← *((byte*)(const struct Point*) main::q#0) -- _deref_pbuc1=_deref_pbuc2 + lda q + sta SCREEN + //SEG15 [8] *((const byte*) main::SCREEN#0+(byte) 1) ← *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda q+OFFSET_STRUCT_POINT_Y + sta SCREEN+1 + jmp breturn + //SEG16 main::@return + breturn: + //SEG17 [9] return + rts +} +//SEG18 set +set: { + //SEG19 [10] *((byte*)(const struct Point*) main::q#0) ← (byte) 4 -- _deref_pbuc1=vbuc2 + lda #4 + sta main.q + //SEG20 [11] *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2 + lda #5 + sta main.q+OFFSET_STRUCT_POINT_Y + jmp breturn + //SEG21 set::@return + breturn: + //SEG22 [12] return + rts +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp breturn +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction bend_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction b1: +Removing instruction breturn: +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 +(const byte) OFFSET_STRUCT_POINT_Y OFFSET_STRUCT_POINT_Y = (byte) 1 +(byte) Point::x +(byte) Point::y +(void()) main() +(label) main::@1 +(label) main::@return +(byte*) main::SCREEN +(const byte*) main::SCREEN#0 SCREEN = (byte*) 1024 +(struct Point) main::p +(byte) main::p_x +(byte) main::p_x#0 p_x zp ZP_BYTE:2 20.0 +(byte) main::p_y +(byte) main::p_y#0 p_y zp ZP_BYTE:3 20.0 +(struct Point*) main::q +(const struct Point*) main::q#0 q = (struct Point*)&(byte) main::p_x#0 +(void()) set((struct Point*) set::ptr) +(label) set::@return +(struct Point*) set::ptr + +zp ZP_BYTE:2 [ main::p_x#0 ] +zp ZP_BYTE:3 [ main::p_y#0 ] + + +FINAL ASSEMBLER +Score: 56 + +//SEG0 File Comments +// Minimal struct - using address-of and passing it to a function +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const OFFSET_STRUCT_POINT_Y = 1 +//SEG3 @begin +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG5 @1 +//SEG6 [2] call main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +//SEG8 @end +//SEG9 main +main: { + .label q = p_x + .label SCREEN = $400 + .label p_x = 2 + .label p_y = 3 + //SEG10 [4] (byte) main::p_x#0 ← (byte) 2 -- vbuz1=vbuc1 + lda #2 + sta p_x + //SEG11 [5] (byte) main::p_y#0 ← (byte) 3 -- vbuz1=vbuc1 + lda #3 + sta p_y + //SEG12 [6] call set + jsr set + //SEG13 main::@1 + //SEG14 [7] *((const byte*) main::SCREEN#0) ← *((byte*)(const struct Point*) main::q#0) -- _deref_pbuc1=_deref_pbuc2 + lda q + sta SCREEN + //SEG15 [8] *((const byte*) main::SCREEN#0+(byte) 1) ← *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) -- _deref_pbuc1=_deref_pbuc2 + lda q+OFFSET_STRUCT_POINT_Y + sta SCREEN+1 + //SEG16 main::@return + //SEG17 [9] return + rts +} +//SEG18 set +set: { + //SEG19 [10] *((byte*)(const struct Point*) main::q#0) ← (byte) 4 -- _deref_pbuc1=vbuc2 + lda #4 + sta main.q + //SEG20 [11] *((byte*)(const struct Point*) main::q#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) 5 -- _deref_pbuc1=vbuc2 + lda #5 + sta main.q+OFFSET_STRUCT_POINT_Y + //SEG21 set::@return + //SEG22 [12] return + rts +} + diff --git a/src/test/ref/struct-ptr-14.sym b/src/test/ref/struct-ptr-14.sym new file mode 100644 index 000000000..0c98c6cc8 --- /dev/null +++ b/src/test/ref/struct-ptr-14.sym @@ -0,0 +1,24 @@ +(label) @1 +(label) @begin +(label) @end +(const byte) OFFSET_STRUCT_POINT_Y OFFSET_STRUCT_POINT_Y = (byte) 1 +(byte) Point::x +(byte) Point::y +(void()) main() +(label) main::@1 +(label) main::@return +(byte*) main::SCREEN +(const byte*) main::SCREEN#0 SCREEN = (byte*) 1024 +(struct Point) main::p +(byte) main::p_x +(byte) main::p_x#0 p_x zp ZP_BYTE:2 20.0 +(byte) main::p_y +(byte) main::p_y#0 p_y zp ZP_BYTE:3 20.0 +(struct Point*) main::q +(const struct Point*) main::q#0 q = (struct Point*)&(byte) main::p_x#0 +(void()) set((struct Point*) set::ptr) +(label) set::@return +(struct Point*) set::ptr + +zp ZP_BYTE:2 [ main::p_x#0 ] +zp ZP_BYTE:3 [ main::p_y#0 ]