mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-26 12:49:21 +00:00
Added missing ref files.
This commit is contained in:
parent
8b6fabc9c8
commit
c1af79cf47
58
src/test/ref/struct-unwinding-1.asm
Normal file
58
src/test/ref/struct-unwinding-1.asm
Normal file
@ -0,0 +1,58 @@
|
||||
// Test combining unwind structs with classic structs
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.const SIZEOF_STRUCT_POINT = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.label p1 = 2
|
||||
// p1 = { 1, 2 }
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta p1-1,y
|
||||
dey
|
||||
bne !-
|
||||
// SCREEN[0] = p1
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN-1,y
|
||||
dey
|
||||
bne !-
|
||||
// p2 = p1
|
||||
lda.z p1
|
||||
ldx p1+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[2] = p2
|
||||
sta SCREEN+2*SIZEOF_STRUCT_POINT
|
||||
stx SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
|
||||
// p1.x = 3
|
||||
// Set in classic struct
|
||||
lda #3
|
||||
sta.z p1
|
||||
// SCREEN[4] = p1
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN+4*SIZEOF_STRUCT_POINT-1,y
|
||||
dey
|
||||
bne !-
|
||||
// SCREEN[6] = p2
|
||||
lda #4
|
||||
sta SCREEN+6*SIZEOF_STRUCT_POINT
|
||||
stx SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
|
||||
// p1 = p2
|
||||
sta.z p1
|
||||
stx p1+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[8] = p1
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN+8*SIZEOF_STRUCT_POINT-1,y
|
||||
dey
|
||||
bne !-
|
||||
// }
|
||||
rts
|
||||
}
|
||||
__0: .byte 1, 2
|
20
src/test/ref/struct-unwinding-1.cfg
Normal file
20
src/test/ref/struct-unwinding-1.cfg
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[2] main::p2_x#0 = *((byte*)&main::p1)
|
||||
[3] main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
|
||||
[4] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT) = main::p2_x#0
|
||||
[5] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
|
||||
[6] *((byte*)&main::p1) = 3
|
||||
[7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4
|
||||
[9] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
|
||||
[10] *((byte*)&main::p1) = 4
|
||||
[11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
|
||||
[12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[13] return
|
||||
to:@return
|
423
src/test/ref/struct-unwinding-1.log
Normal file
423
src/test/ref/struct-unwinding-1.log
Normal file
@ -0,0 +1,423 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
*(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
|
||||
main::p1 = struct-unwound {*(&main::p1)}
|
||||
main::$0 = 0 * SIZEOF_STRUCT_POINT
|
||||
SCREEN[main::$0] = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
main::p2_x#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_X)
|
||||
main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
|
||||
main::$1 = 2 * SIZEOF_STRUCT_POINT
|
||||
main::$5 = (byte*)SCREEN + main::$1
|
||||
main::$5[OFFSET_STRUCT_POINT_X] = main::p2_x#0
|
||||
main::$6 = (byte*)SCREEN + main::$1
|
||||
main::$6[OFFSET_STRUCT_POINT_Y] = main::p2_y#0
|
||||
*((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = 3
|
||||
main::$2 = 4 * SIZEOF_STRUCT_POINT
|
||||
SCREEN[main::$2] = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
main::p2_x#1 = 4
|
||||
main::$3 = 6 * SIZEOF_STRUCT_POINT
|
||||
main::$7 = (byte*)SCREEN + main::$3
|
||||
main::$7[OFFSET_STRUCT_POINT_X] = main::p2_x#1
|
||||
main::$8 = (byte*)SCREEN + main::$3
|
||||
main::$8[OFFSET_STRUCT_POINT_Y] = main::p2_y#0
|
||||
*((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = main::p2_x#1
|
||||
*((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
|
||||
main::p1 = struct-unwound {*((byte*)&main::p1+OFFSET_STRUCT_POINT_X), *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)}
|
||||
main::$4 = 8 * SIZEOF_STRUCT_POINT
|
||||
SCREEN[main::$4] = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
return
|
||||
to:@return
|
||||
|
||||
void __start()
|
||||
__start: scope:[__start] from
|
||||
call main
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start
|
||||
to:__start::@return
|
||||
__start::@return: scope:[__start] from __start::@1
|
||||
return
|
||||
to:@return
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
const struct Point $0 = { x: 1, y: 2 }
|
||||
const byte OFFSET_STRUCT_POINT_X = 0
|
||||
const byte OFFSET_STRUCT_POINT_Y = 1
|
||||
const nomodify struct Point* SCREEN = (struct Point*)$400
|
||||
const byte SIZEOF_STRUCT_POINT = 2
|
||||
void __start()
|
||||
void main()
|
||||
number~ main::$0
|
||||
number~ main::$1
|
||||
number~ main::$2
|
||||
number~ main::$3
|
||||
number~ main::$4
|
||||
byte*~ main::$5
|
||||
byte*~ main::$6
|
||||
byte*~ main::$7
|
||||
byte*~ main::$8
|
||||
struct Point main::p1 loadstore
|
||||
byte main::p2_x
|
||||
byte main::p2_x#0
|
||||
byte main::p2_x#1
|
||||
byte main::p2_y
|
||||
byte main::p2_y#0
|
||||
|
||||
Adding number conversion cast (unumber) 0 in main::$0 = 0 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$0 in main::$0 = (unumber)0 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) 2 in main::$1 = 2 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$1 in main::$1 = (unumber)2 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) 3 in *((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = 3
|
||||
Adding number conversion cast (unumber) 4 in main::$2 = 4 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$2 in main::$2 = (unumber)4 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) 4 in main::p2_x#1 = 4
|
||||
Adding number conversion cast (unumber) 6 in main::$3 = 6 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$3 in main::$3 = (unumber)6 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) 8 in main::$4 = 8 * SIZEOF_STRUCT_POINT
|
||||
Adding number conversion cast (unumber) main::$4 in main::$4 = (unumber)8 * SIZEOF_STRUCT_POINT
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast *((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = (unumber)3
|
||||
Inlining cast main::p2_x#1 = (unumber)4
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (struct Point*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 3
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 6
|
||||
Simplifying constant integer cast 8
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type 0
|
||||
Finalized unsigned number type 2
|
||||
Finalized unsigned number type 3
|
||||
Finalized unsigned number type 4
|
||||
Finalized unsigned number type 4
|
||||
Finalized unsigned number type 6
|
||||
Finalized unsigned number type 8
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Inferred type updated to byte in main::$0 = 0 * SIZEOF_STRUCT_POINT
|
||||
Inferred type updated to byte in main::$1 = 2 * SIZEOF_STRUCT_POINT
|
||||
Inferred type updated to byte in main::$2 = 4 * SIZEOF_STRUCT_POINT
|
||||
Inferred type updated to byte in main::$3 = 6 * SIZEOF_STRUCT_POINT
|
||||
Inferred type updated to byte in main::$4 = 8 * SIZEOF_STRUCT_POINT
|
||||
Removing C-classic struct-unwound assignment [1] main::p1 = struct-unwound {*(&main::p1)}
|
||||
Removing C-classic struct-unwound assignment [22] main::p1 = struct-unwound {*((byte*)&main::p1+OFFSET_STRUCT_POINT_X), *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)}
|
||||
Constant right-side identified [2] main::$0 = 0 * SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [6] main::$1 = 2 * SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [12] main::$2 = 4 * SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [15] main::$3 = 6 * SIZEOF_STRUCT_POINT
|
||||
Constant right-side identified [23] main::$4 = 8 * SIZEOF_STRUCT_POINT
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant main::$0 = 0*SIZEOF_STRUCT_POINT
|
||||
Constant main::$1 = 2*SIZEOF_STRUCT_POINT
|
||||
Constant main::$2 = 4*SIZEOF_STRUCT_POINT
|
||||
Constant main::p2_x#1 = 4
|
||||
Constant main::$3 = 6*SIZEOF_STRUCT_POINT
|
||||
Constant main::$4 = 8*SIZEOF_STRUCT_POINT
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying constant evaluating to zero 0*SIZEOF_STRUCT_POINT in
|
||||
Successful SSA optimization PassNSimplifyConstantZero
|
||||
Simplifying expression containing zero SCREEN in [3] SCREEN[main::$0] = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
Simplifying expression containing zero (byte*)&main::p1 in [4] main::p2_x#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_X)
|
||||
Simplifying expression containing zero main::$5 in [8] main::$5[OFFSET_STRUCT_POINT_X] = main::p2_x#0
|
||||
Simplifying expression containing zero (byte*)&main::p1 in [11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = 3
|
||||
Simplifying expression containing zero main::$7 in [17] main::$7[OFFSET_STRUCT_POINT_X] = main::p2_x#1
|
||||
Simplifying expression containing zero (byte*)&main::p1 in [20] *((byte*)&main::p1+OFFSET_STRUCT_POINT_X) = main::p2_x#1
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused constant main::$0
|
||||
Eliminating unused constant OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Removing unused procedure __start
|
||||
Removing unused procedure block __start
|
||||
Removing unused procedure block __start::@1
|
||||
Removing unused procedure block __start::@return
|
||||
Successful SSA optimization PassNEliminateEmptyStart
|
||||
Constant right-side identified [4] main::$5 = (byte*)SCREEN + main::$1
|
||||
Constant right-side identified [6] main::$6 = (byte*)SCREEN + main::$1
|
||||
Constant right-side identified [10] main::$7 = (byte*)SCREEN + main::$3
|
||||
Constant right-side identified [12] main::$8 = (byte*)SCREEN + main::$3
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant main::$5 = (byte*)SCREEN+main::$1
|
||||
Constant main::$6 = (byte*)SCREEN+main::$1
|
||||
Constant main::$7 = (byte*)SCREEN+main::$3
|
||||
Constant main::$8 = (byte*)SCREEN+main::$3
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining constant with var siblings main::p2_x#1
|
||||
Constant inlined main::$1 = 2*SIZEOF_STRUCT_POINT
|
||||
Constant inlined main::$2 = 4*SIZEOF_STRUCT_POINT
|
||||
Constant inlined main::$5 = (byte*)SCREEN+2*SIZEOF_STRUCT_POINT
|
||||
Constant inlined main::$6 = (byte*)SCREEN+2*SIZEOF_STRUCT_POINT
|
||||
Constant inlined main::$3 = 6*SIZEOF_STRUCT_POINT
|
||||
Constant inlined main::$4 = 8*SIZEOF_STRUCT_POINT
|
||||
Constant inlined main::$7 = (byte*)SCREEN+6*SIZEOF_STRUCT_POINT
|
||||
Constant inlined main::p2_x#1 = 4
|
||||
Constant inlined main::$8 = (byte*)SCREEN+6*SIZEOF_STRUCT_POINT
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Consolidated array index constant in *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+4*SIZEOF_STRUCT_POINT)
|
||||
Consolidated array index constant in *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y)
|
||||
Consolidated array index constant in *(SCREEN+8*SIZEOF_STRUCT_POINT)
|
||||
Successful SSA optimization Pass2ConstantAdditionElimination
|
||||
CALL GRAPH
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[2] main::p2_x#0 = *((byte*)&main::p1)
|
||||
[3] main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
|
||||
[4] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT) = main::p2_x#0
|
||||
[5] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
|
||||
[6] *((byte*)&main::p1) = 3
|
||||
[7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4
|
||||
[9] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
|
||||
[10] *((byte*)&main::p1) = 4
|
||||
[11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0
|
||||
[12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[13] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
struct Point main::p1 loadstore
|
||||
byte main::p2_x
|
||||
byte main::p2_x#0 2.0
|
||||
byte main::p2_y
|
||||
byte main::p2_y#0 1.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
Added variable main::p2_x#0 to live range equivalence class [ main::p2_x#0 ]
|
||||
Added variable main::p2_y#0 to live range equivalence class [ main::p2_y#0 ]
|
||||
Added variable main::p1 to live range equivalence class [ main::p1 ]
|
||||
Complete equivalence classes
|
||||
[ main::p2_x#0 ]
|
||||
[ main::p2_y#0 ]
|
||||
[ main::p1 ]
|
||||
Allocated zp[1]:2 [ main::p2_x#0 ]
|
||||
Allocated zp[1]:3 [ main::p2_y#0 ]
|
||||
Allocated zp[2]:4 [ main::p1 ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 ] ( [ main::p1 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 ] ( [ main::p1 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [6] *((byte*)&main::p1) = 3 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::p2_y#0 ]
|
||||
Statement [7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a reg byte y
|
||||
Removing always clobbered register reg byte y as potential for zp[1]:3 [ main::p2_y#0 ]
|
||||
Statement [8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
|
||||
Statement [10] *((byte*)&main::p1) = 4 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
|
||||
Statement [12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 ] ( [ main::p1 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 ] ( [ main::p1 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [6] *((byte*)&main::p1) = 3 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
|
||||
Statement [7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
|
||||
Statement [10] *((byte*)&main::p1) = 4 [ main::p1 main::p2_y#0 ] ( [ main::p1 main::p2_y#0 ] { } ) always clobbers reg byte a
|
||||
Statement [12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ ] ( [ ] { } ) always clobbers reg byte a reg byte y
|
||||
Potential registers zp[1]:2 [ main::p2_x#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:3 [ main::p2_y#0 ] : zp[1]:3 , reg byte x ,
|
||||
Potential registers zp[2]:4 [ main::p1 ] : zp[2]:4 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 2: zp[1]:2 [ main::p2_x#0 ] 1: zp[1]:3 [ main::p2_y#0 ] 0: zp[2]:4 [ main::p1 ]
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 112 combination reg byte a [ main::p2_x#0 ] reg byte x [ main::p2_y#0 ] zp[2]:4 [ main::p1 ]
|
||||
Uplifting [Point] best 112 combination
|
||||
Uplifting [] best 112 combination
|
||||
Allocated (was zp[2]:4) zp[2]:2 [ main::p1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test combining unwind structs with classic structs
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_POINT = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
.label p1 = 2
|
||||
// [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta p1-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [2] main::p2_x#0 = *((byte*)&main::p1) -- vbuaa=_deref_pbuc1
|
||||
lda.z p1
|
||||
// [3] main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
|
||||
ldx p1+OFFSET_STRUCT_POINT_Y
|
||||
// [4] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT) = main::p2_x#0 -- _deref_pbuc1=vbuaa
|
||||
sta SCREEN+2*SIZEOF_STRUCT_POINT
|
||||
// [5] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
|
||||
stx SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
|
||||
// [6] *((byte*)&main::p1) = 3 -- _deref_pbuc1=vbuc2
|
||||
// Set in classic struct
|
||||
lda #3
|
||||
sta.z p1
|
||||
// [7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN+4*SIZEOF_STRUCT_POINT-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta SCREEN+6*SIZEOF_STRUCT_POINT
|
||||
// [9] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
|
||||
stx SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
|
||||
// [10] *((byte*)&main::p1) = 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta.z p1
|
||||
// [11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
|
||||
stx p1+OFFSET_STRUCT_POINT_Y
|
||||
// [12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN+8*SIZEOF_STRUCT_POINT-1,y
|
||||
dey
|
||||
bne !-
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 1, 2
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #4
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
const struct Point $0 = { x: 1, y: 2 }
|
||||
const byte OFFSET_STRUCT_POINT_Y = 1
|
||||
const nomodify struct Point* SCREEN = (struct Point*) 1024
|
||||
const byte SIZEOF_STRUCT_POINT = 2
|
||||
void main()
|
||||
struct Point main::p1 loadstore zp[2]:2
|
||||
byte main::p2_x
|
||||
byte main::p2_x#0 reg byte a 2.0
|
||||
byte main::p2_y
|
||||
byte main::p2_y#0 reg byte x 1.0
|
||||
|
||||
reg byte a [ main::p2_x#0 ]
|
||||
reg byte x [ main::p2_y#0 ]
|
||||
zp[2]:2 [ main::p1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 107
|
||||
|
||||
// File Comments
|
||||
// Test combining unwind structs with classic structs
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_POINT = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
.label p1 = 2
|
||||
// p1 = { 1, 2 }
|
||||
// [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta p1-1,y
|
||||
dey
|
||||
bne !-
|
||||
// SCREEN[0] = p1
|
||||
// [1] *SCREEN = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN-1,y
|
||||
dey
|
||||
bne !-
|
||||
// p2 = p1
|
||||
// [2] main::p2_x#0 = *((byte*)&main::p1) -- vbuaa=_deref_pbuc1
|
||||
lda.z p1
|
||||
// [3] main::p2_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
|
||||
ldx p1+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[2] = p2
|
||||
// [4] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT) = main::p2_x#0 -- _deref_pbuc1=vbuaa
|
||||
sta SCREEN+2*SIZEOF_STRUCT_POINT
|
||||
// [5] *((byte*)SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
|
||||
stx SCREEN+2*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
|
||||
// p1.x = 3
|
||||
// [6] *((byte*)&main::p1) = 3 -- _deref_pbuc1=vbuc2
|
||||
// Set in classic struct
|
||||
lda #3
|
||||
sta.z p1
|
||||
// SCREEN[4] = p1
|
||||
// [7] *(SCREEN+4*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN+4*SIZEOF_STRUCT_POINT-1,y
|
||||
dey
|
||||
bne !-
|
||||
// SCREEN[6] = p2
|
||||
// [8] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT) = 4 -- _deref_pbuc1=vbuc2
|
||||
lda #4
|
||||
sta SCREEN+6*SIZEOF_STRUCT_POINT
|
||||
// [9] *((byte*)SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
|
||||
stx SCREEN+6*SIZEOF_STRUCT_POINT+OFFSET_STRUCT_POINT_Y
|
||||
// p1 = p2
|
||||
// [10] *((byte*)&main::p1) = 4 -- _deref_pbuc1=vbuc2
|
||||
sta.z p1
|
||||
// [11] *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) = main::p2_y#0 -- _deref_pbuc1=vbuxx
|
||||
stx p1+OFFSET_STRUCT_POINT_Y
|
||||
// SCREEN[8] = p1
|
||||
// [12] *(SCREEN+8*SIZEOF_STRUCT_POINT) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta SCREEN+8*SIZEOF_STRUCT_POINT-1,y
|
||||
dey
|
||||
bne !-
|
||||
// main::@return
|
||||
// }
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 1, 2
|
||||
|
14
src/test/ref/struct-unwinding-1.sym
Normal file
14
src/test/ref/struct-unwinding-1.sym
Normal file
@ -0,0 +1,14 @@
|
||||
const struct Point $0 = { x: 1, y: 2 }
|
||||
const byte OFFSET_STRUCT_POINT_Y = 1
|
||||
const nomodify struct Point* SCREEN = (struct Point*) 1024
|
||||
const byte SIZEOF_STRUCT_POINT = 2
|
||||
void main()
|
||||
struct Point main::p1 loadstore zp[2]:2
|
||||
byte main::p2_x
|
||||
byte main::p2_x#0 reg byte a 2.0
|
||||
byte main::p2_y
|
||||
byte main::p2_y#0 reg byte x 1.0
|
||||
|
||||
reg byte a [ main::p2_x#0 ]
|
||||
reg byte x [ main::p2_y#0 ]
|
||||
zp[2]:2 [ main::p1 ]
|
86
src/test/ref/struct-unwinding-2.asm
Normal file
86
src/test/ref/struct-unwinding-2.asm
Normal file
@ -0,0 +1,86 @@
|
||||
// Test combining unwind structs with classic structs
|
||||
// Function calls parameter passing
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.const SIZEOF_STRUCT_POINT = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
main: {
|
||||
.const p2_x = 3
|
||||
.const p2_y = 4
|
||||
.label p1 = 3
|
||||
// p1 = { 1, 2 }
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta p1-1,y
|
||||
dey
|
||||
bne !-
|
||||
// print1(p1, 0)
|
||||
ldy.z p1
|
||||
ldx p1+OFFSET_STRUCT_POINT_Y
|
||||
// Pass classic struct to function taking unwound struct
|
||||
lda #0
|
||||
jsr print1
|
||||
// print2(p1, 2)
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta print2.p-1,y
|
||||
dey
|
||||
bne !-
|
||||
// Pass classic struct to function taking classic struct
|
||||
lda #2
|
||||
jsr print2
|
||||
// print1(p2, 4)
|
||||
// Pass unwound struct to function taking unwound struct
|
||||
ldx #p2_y
|
||||
ldy #p2_x
|
||||
lda #4
|
||||
jsr print1
|
||||
// print2(p2, 6)
|
||||
lda #p2_x
|
||||
sta.z print2.p
|
||||
lda #p2_y
|
||||
sta print2.p+OFFSET_STRUCT_POINT_Y
|
||||
// Pass unwound struct to function taking classic struct
|
||||
lda #6
|
||||
jsr print2
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// Function taking unwound struct as parameter
|
||||
// print1(byte register(Y) p_x, byte register(X) p_y, byte register(A) idx)
|
||||
print1: {
|
||||
.label __0 = 2
|
||||
// SCREEN[idx] = p
|
||||
asl
|
||||
sta.z __0
|
||||
tya
|
||||
ldy.z __0
|
||||
sta SCREEN,y
|
||||
txa
|
||||
sta SCREEN+OFFSET_STRUCT_POINT_Y,y
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// Function taking classic struct as parameter
|
||||
// print2(struct Point zp(5) p, byte register(A) idx)
|
||||
print2: {
|
||||
.label p = 5
|
||||
// SCREEN[idx] = p
|
||||
asl
|
||||
tay
|
||||
ldx #0
|
||||
!:
|
||||
lda.z p,x
|
||||
sta SCREEN,y
|
||||
iny
|
||||
inx
|
||||
cpx #SIZEOF_STRUCT_POINT
|
||||
bne !-
|
||||
// }
|
||||
rts
|
||||
}
|
||||
__0: .byte 1, 2
|
47
src/test/ref/struct-unwinding-2.cfg
Normal file
47
src/test/ref/struct-unwinding-2.cfg
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[1] print1::p_x#0 = *((byte*)&main::p1)
|
||||
[2] print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
|
||||
[3] call print1
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[5] call print2
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[6] phi()
|
||||
[7] call print1
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[8] *((byte*)&print2::p) = main::p2_x
|
||||
[9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y
|
||||
[10] call print2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
[11] return
|
||||
to:@return
|
||||
|
||||
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
|
||||
print1: scope:[print1] from main main::@2
|
||||
[12] print1::p_y#2 = phi( main/print1::p_y#0, main::@2/main::p2_y )
|
||||
[12] print1::p_x#2 = phi( main/print1::p_x#0, main::@2/main::p2_x )
|
||||
[12] print1::idx#2 = phi( main/0, main::@2/4 )
|
||||
[13] print1::$0 = print1::idx#2 << 1
|
||||
[14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2
|
||||
[15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2
|
||||
to:print1::@return
|
||||
print1::@return: scope:[print1] from print1
|
||||
[16] return
|
||||
to:@return
|
||||
|
||||
void print2(struct Point print2::p , byte print2::idx)
|
||||
print2: scope:[print2] from main::@1 main::@3
|
||||
[17] print2::idx#2 = phi( main::@1/2, main::@3/6 )
|
||||
[18] print2::$0 = print2::idx#2 << 1
|
||||
[19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT)
|
||||
to:print2::@return
|
||||
print2::@return: scope:[print2] from print2
|
||||
[20] return
|
||||
to:@return
|
660
src/test/ref/struct-unwinding-2.log
Normal file
660
src/test/ref/struct-unwinding-2.log
Normal file
@ -0,0 +1,660 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
*(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
|
||||
main::p1 = struct-unwound {*(&main::p1)}
|
||||
print1::p_x#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_X)
|
||||
print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
|
||||
print1::idx#0 = 0
|
||||
call print1
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
*(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
print2::p = struct-unwound {*(&print2::p)}
|
||||
print2::idx#0 = 2
|
||||
call print2
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
main::p2#0 = struct-unwound {main::p2_x, main::p2_y}
|
||||
print1::p_x#1 = main::p2_x
|
||||
print1::p_y#1 = main::p2_y
|
||||
print1::idx#1 = 4
|
||||
call print1
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
*((byte*)&print2::p+OFFSET_STRUCT_POINT_X) = main::p2_x
|
||||
*((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y
|
||||
print2::p = struct-unwound {*((byte*)&print2::p+OFFSET_STRUCT_POINT_X), *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y)}
|
||||
print2::idx#1 = 6
|
||||
call print2
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@3
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@4
|
||||
return
|
||||
to:@return
|
||||
|
||||
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
|
||||
print1: scope:[print1] from main main::@2
|
||||
print1::p_y#2 = phi( main/print1::p_y#0, main::@2/print1::p_y#1 )
|
||||
print1::p_x#2 = phi( main/print1::p_x#0, main::@2/print1::p_x#1 )
|
||||
print1::idx#2 = phi( main/print1::idx#0, main::@2/print1::idx#1 )
|
||||
print1::$0 = print1::idx#2 * SIZEOF_STRUCT_POINT
|
||||
((byte*)SCREEN+OFFSET_STRUCT_POINT_X)[print1::$0] = print1::p_x#2
|
||||
((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2
|
||||
to:print1::@return
|
||||
print1::@return: scope:[print1] from print1
|
||||
return
|
||||
to:@return
|
||||
|
||||
void print2(struct Point print2::p , byte print2::idx)
|
||||
print2: scope:[print2] from main::@1 main::@3
|
||||
print2::idx#2 = phi( main::@1/print2::idx#0, main::@3/print2::idx#1 )
|
||||
print2::$0 = print2::idx#2 * SIZEOF_STRUCT_POINT
|
||||
SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT)
|
||||
to:print2::@return
|
||||
print2::@return: scope:[print2] from print2
|
||||
return
|
||||
to:@return
|
||||
|
||||
void __start()
|
||||
__start: scope:[__start] from
|
||||
call main
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start
|
||||
to:__start::@return
|
||||
__start::@return: scope:[__start] from __start::@1
|
||||
return
|
||||
to:@return
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
const struct Point $0 = { x: 1, y: 2 }
|
||||
const byte OFFSET_STRUCT_POINT_X = 0
|
||||
const byte OFFSET_STRUCT_POINT_Y = 1
|
||||
const nomodify struct Point* SCREEN = (struct Point*)$400
|
||||
const byte SIZEOF_STRUCT_POINT = 2
|
||||
void __start()
|
||||
void main()
|
||||
struct Point main::p1 loadstore
|
||||
struct Point main::p2
|
||||
struct Point main::p2#0
|
||||
const byte main::p2_x = 3
|
||||
const byte main::p2_y = 4
|
||||
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
|
||||
byte~ print1::$0
|
||||
byte print1::idx
|
||||
byte print1::idx#0
|
||||
byte print1::idx#1
|
||||
byte print1::idx#2
|
||||
struct Point print1::p
|
||||
byte print1::p_x
|
||||
byte print1::p_x#0
|
||||
byte print1::p_x#1
|
||||
byte print1::p_x#2
|
||||
byte print1::p_y
|
||||
byte print1::p_y#0
|
||||
byte print1::p_y#1
|
||||
byte print1::p_y#2
|
||||
void print2(struct Point print2::p , byte print2::idx)
|
||||
byte~ print2::$0
|
||||
byte print2::idx
|
||||
byte print2::idx#0
|
||||
byte print2::idx#1
|
||||
byte print2::idx#2
|
||||
struct Point print2::p loadstore
|
||||
|
||||
Adding number conversion cast (unumber) 0 in print1::idx#0 = 0
|
||||
Adding number conversion cast (unumber) 2 in print2::idx#0 = 2
|
||||
Adding number conversion cast (unumber) 4 in print1::idx#1 = 4
|
||||
Adding number conversion cast (unumber) 6 in print2::idx#1 = 6
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast print1::idx#0 = (unumber)0
|
||||
Inlining cast print2::idx#0 = (unumber)2
|
||||
Inlining cast print1::idx#1 = (unumber)4
|
||||
Inlining cast print2::idx#1 = (unumber)6
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (struct Point*) 1024
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 4
|
||||
Simplifying constant integer cast 6
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type 0
|
||||
Finalized unsigned number type 2
|
||||
Finalized unsigned number type 4
|
||||
Finalized unsigned number type 6
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Removing C-classic struct-unwound assignment [1] main::p1 = struct-unwound {*(&main::p1)}
|
||||
Removing C-classic struct-unwound assignment [7] print2::p = struct-unwound {*(&print2::p)}
|
||||
Removing C-classic struct-unwound assignment [17] print2::p = struct-unwound {*((byte*)&print2::p+OFFSET_STRUCT_POINT_X), *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y)}
|
||||
Constant print1::idx#0 = 0
|
||||
Constant print2::idx#0 = 2
|
||||
Constant print1::p_x#1 = main::p2_x
|
||||
Constant print1::p_y#1 = main::p2_y
|
||||
Constant print1::idx#1 = 4
|
||||
Constant print2::idx#1 = 6
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Simplifying expression containing zero (byte*)&main::p1 in [2] print1::p_x#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_X)
|
||||
Simplifying expression containing zero (byte*)&print2::p in [15] *((byte*)&print2::p+OFFSET_STRUCT_POINT_X) = main::p2_x
|
||||
Simplifying expression containing zero (byte*)SCREEN in [23] ((byte*)SCREEN+OFFSET_STRUCT_POINT_X)[print1::$0] = print1::p_x#2
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Eliminating unused variable main::p2#0 and assignment [6] main::p2#0 = struct-unwound {main::p2_x, main::p2_y}
|
||||
Eliminating unused constant OFFSET_STRUCT_POINT_X
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Removing unused procedure __start
|
||||
Removing unused procedure block __start
|
||||
Removing unused procedure block __start::@1
|
||||
Removing unused procedure block __start::@return
|
||||
Successful SSA optimization PassNEliminateEmptyStart
|
||||
Rewriting multiplication to use shift [12] print1::$0 = print1::idx#2 * SIZEOF_STRUCT_POINT
|
||||
Rewriting multiplication to use shift [17] print2::$0 = print2::idx#2 * SIZEOF_STRUCT_POINT
|
||||
Successful SSA optimization Pass2MultiplyToShiftRewriting
|
||||
Inlining constant with var siblings print1::idx#0
|
||||
Inlining constant with var siblings print1::p_x#1
|
||||
Inlining constant with var siblings print1::p_y#1
|
||||
Inlining constant with var siblings print1::idx#1
|
||||
Inlining constant with var siblings print2::idx#0
|
||||
Inlining constant with var siblings print2::idx#1
|
||||
Constant inlined print1::idx#1 = 4
|
||||
Constant inlined print1::idx#0 = 0
|
||||
Constant inlined print1::p_x#1 = main::p2_x
|
||||
Constant inlined print1::p_y#1 = main::p2_y
|
||||
Constant inlined print2::idx#0 = 2
|
||||
Constant inlined print2::idx#1 = 6
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of main::@2
|
||||
Adding NOP phi() at start of main::@4
|
||||
CALL GRAPH
|
||||
Calls in [main] to print1:5 print2:7 print1:9 print2:12
|
||||
|
||||
Created 4 initial phi equivalence classes
|
||||
Coalesced [3] print1::p_x#3 = print1::p_x#0
|
||||
Coalesced [4] print1::p_y#3 = print1::p_y#0
|
||||
Coalesced down to 4 phi equivalence classes
|
||||
Culled Empty Block label main::@4
|
||||
Adding NOP phi() at start of main::@2
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[1] print1::p_x#0 = *((byte*)&main::p1)
|
||||
[2] print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y)
|
||||
[3] call print1
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT)
|
||||
[5] call print2
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[6] phi()
|
||||
[7] call print1
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[8] *((byte*)&print2::p) = main::p2_x
|
||||
[9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y
|
||||
[10] call print2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@3
|
||||
[11] return
|
||||
to:@return
|
||||
|
||||
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
|
||||
print1: scope:[print1] from main main::@2
|
||||
[12] print1::p_y#2 = phi( main/print1::p_y#0, main::@2/main::p2_y )
|
||||
[12] print1::p_x#2 = phi( main/print1::p_x#0, main::@2/main::p2_x )
|
||||
[12] print1::idx#2 = phi( main/0, main::@2/4 )
|
||||
[13] print1::$0 = print1::idx#2 << 1
|
||||
[14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2
|
||||
[15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2
|
||||
to:print1::@return
|
||||
print1::@return: scope:[print1] from print1
|
||||
[16] return
|
||||
to:@return
|
||||
|
||||
void print2(struct Point print2::p , byte print2::idx)
|
||||
print2: scope:[print2] from main::@1 main::@3
|
||||
[17] print2::idx#2 = phi( main::@1/2, main::@3/6 )
|
||||
[18] print2::$0 = print2::idx#2 << 1
|
||||
[19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT)
|
||||
to:print2::@return
|
||||
print2::@return: scope:[print2] from print2
|
||||
[20] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
struct Point main::p1 loadstore
|
||||
struct Point main::p2
|
||||
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
|
||||
byte~ print1::$0 16.5
|
||||
byte print1::idx
|
||||
byte print1::idx#2 11.0
|
||||
struct Point print1::p
|
||||
byte print1::p_x
|
||||
byte print1::p_x#0 2.0
|
||||
byte print1::p_x#2 6.5
|
||||
byte print1::p_y
|
||||
byte print1::p_y#0 4.0
|
||||
byte print1::p_y#2 4.333333333333333
|
||||
void print2(struct Point print2::p , byte print2::idx)
|
||||
byte~ print2::$0 22.0
|
||||
byte print2::idx
|
||||
byte print2::idx#2 11.0
|
||||
struct Point print2::p loadstore
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ print1::idx#2 ]
|
||||
[ print1::p_x#2 print1::p_x#0 ]
|
||||
[ print1::p_y#2 print1::p_y#0 ]
|
||||
[ print2::idx#2 ]
|
||||
Added variable print1::$0 to live range equivalence class [ print1::$0 ]
|
||||
Added variable print2::$0 to live range equivalence class [ print2::$0 ]
|
||||
Added variable main::p1 to live range equivalence class [ main::p1 ]
|
||||
Added variable print2::p to live range equivalence class [ print2::p ]
|
||||
Complete equivalence classes
|
||||
[ print1::idx#2 ]
|
||||
[ print1::p_x#2 print1::p_x#0 ]
|
||||
[ print1::p_y#2 print1::p_y#0 ]
|
||||
[ print2::idx#2 ]
|
||||
[ print1::$0 ]
|
||||
[ print2::$0 ]
|
||||
[ main::p1 ]
|
||||
[ print2::p ]
|
||||
Allocated zp[1]:2 [ print1::idx#2 ]
|
||||
Allocated zp[1]:3 [ print1::p_x#2 print1::p_x#0 ]
|
||||
Allocated zp[1]:4 [ print1::p_y#2 print1::p_y#0 ]
|
||||
Allocated zp[1]:5 [ print2::idx#2 ]
|
||||
Allocated zp[1]:6 [ print1::$0 ]
|
||||
Allocated zp[1]:7 [ print2::$0 ]
|
||||
Allocated zp[2]:8 [ main::p1 ]
|
||||
Allocated zp[2]:10 [ print2::p ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 print2::p ] ( [ main::p1 print2::p ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } ) always clobbers reg byte a reg byte y
|
||||
Statement [4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [8] *((byte*)&print2::p) = main::p2_x [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a
|
||||
Statement [9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a
|
||||
Statement [13] print1::$0 = print1::idx#2 << 1 [ print1::p_x#2 print1::p_y#2 print1::$0 ] ( print1:3 [ main::p1 print2::p print1::p_x#2 print1::p_y#2 print1::$0 ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p print1::p_x#2 print1::p_y#2 print1::$0 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:3 [ print1::p_x#2 print1::p_x#0 ]
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:4 [ print1::p_y#2 print1::p_y#0 ]
|
||||
Statement [14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2 [ print1::p_y#2 print1::$0 ] ( print1:3 [ main::p1 print2::p print1::p_y#2 print1::$0 ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p print1::p_y#2 print1::$0 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:6 [ print1::$0 ]
|
||||
Statement [15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2 [ ] ( print1:3 [ main::p1 print2::p ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p ] { } ) always clobbers reg byte a
|
||||
Statement [18] print2::$0 = print2::idx#2 << 1 [ print2::p print2::$0 ] ( print2:5 [ print2::p print2::$0 ] { } print2:10 [ print2::p print2::$0 ] { } ) always clobbers reg byte a
|
||||
Statement [19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT) [ print2::p ] ( print2:5 [ print2::p ] { } print2:10 [ print2::p ] { } ) always clobbers reg byte a reg byte x reg byte y
|
||||
Statement [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) [ main::p1 print2::p ] ( [ main::p1 print2::p ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } ) always clobbers reg byte a reg byte y
|
||||
Statement [4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a reg byte y
|
||||
Statement [8] *((byte*)&print2::p) = main::p2_x [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a
|
||||
Statement [9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y [ print2::p ] ( [ print2::p ] { } ) always clobbers reg byte a
|
||||
Statement [13] print1::$0 = print1::idx#2 << 1 [ print1::p_x#2 print1::p_y#2 print1::$0 ] ( print1:3 [ main::p1 print2::p print1::p_x#2 print1::p_y#2 print1::$0 ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p print1::p_x#2 print1::p_y#2 print1::$0 ] { } ) always clobbers reg byte a
|
||||
Statement [14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2 [ print1::p_y#2 print1::$0 ] ( print1:3 [ main::p1 print2::p print1::p_y#2 print1::$0 ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p print1::p_y#2 print1::$0 ] { } ) always clobbers reg byte a
|
||||
Statement [15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2 [ ] ( print1:3 [ main::p1 print2::p ] { { print1::p_x#0 = print1::p_x#2 } { print1::p_y#0 = print1::p_y#2 } } print1:7 [ print2::p ] { } ) always clobbers reg byte a
|
||||
Statement [18] print2::$0 = print2::idx#2 << 1 [ print2::p print2::$0 ] ( print2:5 [ print2::p print2::$0 ] { } print2:10 [ print2::p print2::$0 ] { } ) always clobbers reg byte a
|
||||
Statement [19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT) [ print2::p ] ( print2:5 [ print2::p ] { } print2:10 [ print2::p ] { } ) always clobbers reg byte a reg byte x reg byte y
|
||||
Potential registers zp[1]:2 [ print1::idx#2 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:3 [ print1::p_x#2 print1::p_x#0 ] : zp[1]:3 , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:4 [ print1::p_y#2 print1::p_y#0 ] : zp[1]:4 , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:5 [ print2::idx#2 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:6 [ print1::$0 ] : zp[1]:6 , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:7 [ print2::$0 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[2]:8 [ main::p1 ] : zp[2]:8 ,
|
||||
Potential registers zp[2]:10 [ print2::p ] : zp[2]:10 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [print1] 16.5: zp[1]:6 [ print1::$0 ] 11: zp[1]:2 [ print1::idx#2 ] 8.5: zp[1]:3 [ print1::p_x#2 print1::p_x#0 ] 8.33: zp[1]:4 [ print1::p_y#2 print1::p_y#0 ]
|
||||
Uplift Scope [print2] 22: zp[1]:7 [ print2::$0 ] 11: zp[1]:5 [ print2::idx#2 ] 0: zp[2]:10 [ print2::p ]
|
||||
Uplift Scope [Point]
|
||||
Uplift Scope [main] 0: zp[2]:8 [ main::p1 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [print1] best 184 combination zp[1]:6 [ print1::$0 ] reg byte a [ print1::idx#2 ] reg byte y [ print1::p_x#2 print1::p_x#0 ] reg byte x [ print1::p_y#2 print1::p_y#0 ]
|
||||
Limited combination testing to 100 combinations of 108 possible.
|
||||
Uplifting [print2] best 170 combination reg byte y [ print2::$0 ] reg byte a [ print2::idx#2 ] zp[2]:10 [ print2::p ]
|
||||
Uplifting [Point] best 170 combination
|
||||
Uplifting [main] best 170 combination zp[2]:8 [ main::p1 ]
|
||||
Uplifting [] best 170 combination
|
||||
Attempting to uplift remaining variables inzp[1]:6 [ print1::$0 ]
|
||||
Uplifting [print1] best 170 combination zp[1]:6 [ print1::$0 ]
|
||||
Allocated (was zp[1]:6) zp[1]:2 [ print1::$0 ]
|
||||
Allocated (was zp[2]:8) zp[2]:3 [ main::p1 ]
|
||||
Allocated (was zp[2]:10) zp[2]:5 [ print2::p ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test combining unwind structs with classic structs
|
||||
// Function calls parameter passing
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_POINT = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
.const p2_x = 3
|
||||
.const p2_y = 4
|
||||
.label p1 = 3
|
||||
// [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta p1-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [1] print1::p_x#0 = *((byte*)&main::p1) -- vbuyy=_deref_pbuc1
|
||||
ldy.z p1
|
||||
// [2] print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
|
||||
ldx p1+OFFSET_STRUCT_POINT_Y
|
||||
// [3] call print1
|
||||
// Pass classic struct to function taking unwound struct
|
||||
// [12] phi from main to print1 [phi:main->print1]
|
||||
print1_from_main:
|
||||
// [12] phi print1::p_y#2 = print1::p_y#0 [phi:main->print1#0] -- register_copy
|
||||
// [12] phi print1::p_x#2 = print1::p_x#0 [phi:main->print1#1] -- register_copy
|
||||
// [12] phi print1::idx#2 = 0 [phi:main->print1#2] -- vbuaa=vbuc1
|
||||
lda #0
|
||||
jsr print1
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta print2.p-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [5] call print2
|
||||
// Pass classic struct to function taking classic struct
|
||||
// [17] phi from main::@1 to print2 [phi:main::@1->print2]
|
||||
print2_from___b1:
|
||||
// [17] phi print2::idx#2 = 2 [phi:main::@1->print2#0] -- vbuaa=vbuc1
|
||||
lda #2
|
||||
jsr print2
|
||||
// [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
__b2_from___b1:
|
||||
jmp __b2
|
||||
// main::@2
|
||||
__b2:
|
||||
// [7] call print1
|
||||
// Pass unwound struct to function taking unwound struct
|
||||
// [12] phi from main::@2 to print1 [phi:main::@2->print1]
|
||||
print1_from___b2:
|
||||
// [12] phi print1::p_y#2 = main::p2_y [phi:main::@2->print1#0] -- vbuxx=vbuc1
|
||||
ldx #p2_y
|
||||
// [12] phi print1::p_x#2 = main::p2_x [phi:main::@2->print1#1] -- vbuyy=vbuc1
|
||||
ldy #p2_x
|
||||
// [12] phi print1::idx#2 = 4 [phi:main::@2->print1#2] -- vbuaa=vbuc1
|
||||
lda #4
|
||||
jsr print1
|
||||
jmp __b3
|
||||
// main::@3
|
||||
__b3:
|
||||
// [8] *((byte*)&print2::p) = main::p2_x -- _deref_pbuc1=vbuc2
|
||||
lda #p2_x
|
||||
sta.z print2.p
|
||||
// [9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y -- _deref_pbuc1=vbuc2
|
||||
lda #p2_y
|
||||
sta print2.p+OFFSET_STRUCT_POINT_Y
|
||||
// [10] call print2
|
||||
// Pass unwound struct to function taking classic struct
|
||||
// [17] phi from main::@3 to print2 [phi:main::@3->print2]
|
||||
print2_from___b3:
|
||||
// [17] phi print2::idx#2 = 6 [phi:main::@3->print2#0] -- vbuaa=vbuc1
|
||||
lda #6
|
||||
jsr print2
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [11] return
|
||||
rts
|
||||
}
|
||||
// print1
|
||||
// Function taking unwound struct as parameter
|
||||
// print1(byte register(Y) p_x, byte register(X) p_y, byte register(A) idx)
|
||||
print1: {
|
||||
.label __0 = 2
|
||||
// [13] print1::$0 = print1::idx#2 << 1 -- vbuz1=vbuaa_rol_1
|
||||
asl
|
||||
sta.z __0
|
||||
// [14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2 -- pbuc1_derefidx_vbuz1=vbuyy
|
||||
tya
|
||||
ldy.z __0
|
||||
sta SCREEN,y
|
||||
// [15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2 -- pbuc1_derefidx_vbuz1=vbuxx
|
||||
ldy.z __0
|
||||
txa
|
||||
sta SCREEN+OFFSET_STRUCT_POINT_Y,y
|
||||
jmp __breturn
|
||||
// print1::@return
|
||||
__breturn:
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// print2
|
||||
// Function taking classic struct as parameter
|
||||
// print2(struct Point zp(5) p, byte register(A) idx)
|
||||
print2: {
|
||||
.label p = 5
|
||||
// [18] print2::$0 = print2::idx#2 << 1 -- vbuyy=vbuaa_rol_1
|
||||
asl
|
||||
tay
|
||||
// [19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT) -- pssc1_derefidx_vbuyy=_deref_pssc2_memcpy_vbuc3
|
||||
ldx #0
|
||||
!:
|
||||
lda.z p,x
|
||||
sta SCREEN,y
|
||||
iny
|
||||
inx
|
||||
cpx #SIZEOF_STRUCT_POINT
|
||||
bne !-
|
||||
jmp __breturn
|
||||
// print2::@return
|
||||
__breturn:
|
||||
// [20] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 1, 2
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __b2
|
||||
Removing instruction jmp __b3
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction ldy.z __0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Removing instruction __b2_from___b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction print1_from_main:
|
||||
Removing instruction __b1:
|
||||
Removing instruction print2_from___b1:
|
||||
Removing instruction __b2:
|
||||
Removing instruction print1_from___b2:
|
||||
Removing instruction __b3:
|
||||
Removing instruction print2_from___b3:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
const struct Point $0 = { x: 1, y: 2 }
|
||||
const byte OFFSET_STRUCT_POINT_Y = 1
|
||||
const nomodify struct Point* SCREEN = (struct Point*) 1024
|
||||
const byte SIZEOF_STRUCT_POINT = 2
|
||||
void main()
|
||||
struct Point main::p1 loadstore zp[2]:3
|
||||
struct Point main::p2
|
||||
const byte main::p2_x = 3
|
||||
const byte main::p2_y = 4
|
||||
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
|
||||
byte~ print1::$0 zp[1]:2 16.5
|
||||
byte print1::idx
|
||||
byte print1::idx#2 reg byte a 11.0
|
||||
struct Point print1::p
|
||||
byte print1::p_x
|
||||
byte print1::p_x#0 reg byte y 2.0
|
||||
byte print1::p_x#2 reg byte y 6.5
|
||||
byte print1::p_y
|
||||
byte print1::p_y#0 reg byte x 4.0
|
||||
byte print1::p_y#2 reg byte x 4.333333333333333
|
||||
void print2(struct Point print2::p , byte print2::idx)
|
||||
byte~ print2::$0 reg byte y 22.0
|
||||
byte print2::idx
|
||||
byte print2::idx#2 reg byte a 11.0
|
||||
struct Point print2::p loadstore zp[2]:5
|
||||
|
||||
reg byte a [ print1::idx#2 ]
|
||||
reg byte y [ print1::p_x#2 print1::p_x#0 ]
|
||||
reg byte x [ print1::p_y#2 print1::p_y#0 ]
|
||||
reg byte a [ print2::idx#2 ]
|
||||
zp[1]:2 [ print1::$0 ]
|
||||
reg byte y [ print2::$0 ]
|
||||
zp[2]:3 [ main::p1 ]
|
||||
zp[2]:5 [ print2::p ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 149
|
||||
|
||||
// File Comments
|
||||
// Test combining unwind structs with classic structs
|
||||
// Function calls parameter passing
|
||||
// Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_POINT = 2
|
||||
.const OFFSET_STRUCT_POINT_Y = 1
|
||||
.label SCREEN = $400
|
||||
// main
|
||||
main: {
|
||||
.const p2_x = 3
|
||||
.const p2_y = 4
|
||||
.label p1 = 3
|
||||
// p1 = { 1, 2 }
|
||||
// [0] *(&main::p1) = memcpy(*(&$0), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda __0-1,y
|
||||
sta p1-1,y
|
||||
dey
|
||||
bne !-
|
||||
// print1(p1, 0)
|
||||
// [1] print1::p_x#0 = *((byte*)&main::p1) -- vbuyy=_deref_pbuc1
|
||||
ldy.z p1
|
||||
// [2] print1::p_y#0 = *((byte*)&main::p1+OFFSET_STRUCT_POINT_Y) -- vbuxx=_deref_pbuc1
|
||||
ldx p1+OFFSET_STRUCT_POINT_Y
|
||||
// [3] call print1
|
||||
// Pass classic struct to function taking unwound struct
|
||||
// [12] phi from main to print1 [phi:main->print1]
|
||||
// [12] phi print1::p_y#2 = print1::p_y#0 [phi:main->print1#0] -- register_copy
|
||||
// [12] phi print1::p_x#2 = print1::p_x#0 [phi:main->print1#1] -- register_copy
|
||||
// [12] phi print1::idx#2 = 0 [phi:main->print1#2] -- vbuaa=vbuc1
|
||||
lda #0
|
||||
jsr print1
|
||||
// main::@1
|
||||
// print2(p1, 2)
|
||||
// [4] *(&print2::p) = memcpy(*(&main::p1), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3
|
||||
ldy #SIZEOF_STRUCT_POINT
|
||||
!:
|
||||
lda p1-1,y
|
||||
sta print2.p-1,y
|
||||
dey
|
||||
bne !-
|
||||
// [5] call print2
|
||||
// Pass classic struct to function taking classic struct
|
||||
// [17] phi from main::@1 to print2 [phi:main::@1->print2]
|
||||
// [17] phi print2::idx#2 = 2 [phi:main::@1->print2#0] -- vbuaa=vbuc1
|
||||
lda #2
|
||||
jsr print2
|
||||
// [6] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
// main::@2
|
||||
// print1(p2, 4)
|
||||
// [7] call print1
|
||||
// Pass unwound struct to function taking unwound struct
|
||||
// [12] phi from main::@2 to print1 [phi:main::@2->print1]
|
||||
// [12] phi print1::p_y#2 = main::p2_y [phi:main::@2->print1#0] -- vbuxx=vbuc1
|
||||
ldx #p2_y
|
||||
// [12] phi print1::p_x#2 = main::p2_x [phi:main::@2->print1#1] -- vbuyy=vbuc1
|
||||
ldy #p2_x
|
||||
// [12] phi print1::idx#2 = 4 [phi:main::@2->print1#2] -- vbuaa=vbuc1
|
||||
lda #4
|
||||
jsr print1
|
||||
// main::@3
|
||||
// print2(p2, 6)
|
||||
// [8] *((byte*)&print2::p) = main::p2_x -- _deref_pbuc1=vbuc2
|
||||
lda #p2_x
|
||||
sta.z print2.p
|
||||
// [9] *((byte*)&print2::p+OFFSET_STRUCT_POINT_Y) = main::p2_y -- _deref_pbuc1=vbuc2
|
||||
lda #p2_y
|
||||
sta print2.p+OFFSET_STRUCT_POINT_Y
|
||||
// [10] call print2
|
||||
// Pass unwound struct to function taking classic struct
|
||||
// [17] phi from main::@3 to print2 [phi:main::@3->print2]
|
||||
// [17] phi print2::idx#2 = 6 [phi:main::@3->print2#0] -- vbuaa=vbuc1
|
||||
lda #6
|
||||
jsr print2
|
||||
// main::@return
|
||||
// }
|
||||
// [11] return
|
||||
rts
|
||||
}
|
||||
// print1
|
||||
// Function taking unwound struct as parameter
|
||||
// print1(byte register(Y) p_x, byte register(X) p_y, byte register(A) idx)
|
||||
print1: {
|
||||
.label __0 = 2
|
||||
// SCREEN[idx] = p
|
||||
// [13] print1::$0 = print1::idx#2 << 1 -- vbuz1=vbuaa_rol_1
|
||||
asl
|
||||
sta.z __0
|
||||
// [14] ((byte*)SCREEN)[print1::$0] = print1::p_x#2 -- pbuc1_derefidx_vbuz1=vbuyy
|
||||
tya
|
||||
ldy.z __0
|
||||
sta SCREEN,y
|
||||
// [15] ((byte*)SCREEN+OFFSET_STRUCT_POINT_Y)[print1::$0] = print1::p_y#2 -- pbuc1_derefidx_vbuz1=vbuxx
|
||||
txa
|
||||
sta SCREEN+OFFSET_STRUCT_POINT_Y,y
|
||||
// print1::@return
|
||||
// }
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// print2
|
||||
// Function taking classic struct as parameter
|
||||
// print2(struct Point zp(5) p, byte register(A) idx)
|
||||
print2: {
|
||||
.label p = 5
|
||||
// SCREEN[idx] = p
|
||||
// [18] print2::$0 = print2::idx#2 << 1 -- vbuyy=vbuaa_rol_1
|
||||
asl
|
||||
tay
|
||||
// [19] SCREEN[print2::$0] = memcpy(*(&print2::p), struct Point, SIZEOF_STRUCT_POINT) -- pssc1_derefidx_vbuyy=_deref_pssc2_memcpy_vbuc3
|
||||
ldx #0
|
||||
!:
|
||||
lda.z p,x
|
||||
sta SCREEN,y
|
||||
iny
|
||||
inx
|
||||
cpx #SIZEOF_STRUCT_POINT
|
||||
bne !-
|
||||
// print2::@return
|
||||
// }
|
||||
// [20] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
__0: .byte 1, 2
|
||||
|
34
src/test/ref/struct-unwinding-2.sym
Normal file
34
src/test/ref/struct-unwinding-2.sym
Normal file
@ -0,0 +1,34 @@
|
||||
const struct Point $0 = { x: 1, y: 2 }
|
||||
const byte OFFSET_STRUCT_POINT_Y = 1
|
||||
const nomodify struct Point* SCREEN = (struct Point*) 1024
|
||||
const byte SIZEOF_STRUCT_POINT = 2
|
||||
void main()
|
||||
struct Point main::p1 loadstore zp[2]:3
|
||||
struct Point main::p2
|
||||
const byte main::p2_x = 3
|
||||
const byte main::p2_y = 4
|
||||
void print1(byte print1::p_x , byte print1::p_y , byte print1::idx)
|
||||
byte~ print1::$0 zp[1]:2 16.5
|
||||
byte print1::idx
|
||||
byte print1::idx#2 reg byte a 11.0
|
||||
struct Point print1::p
|
||||
byte print1::p_x
|
||||
byte print1::p_x#0 reg byte y 2.0
|
||||
byte print1::p_x#2 reg byte y 6.5
|
||||
byte print1::p_y
|
||||
byte print1::p_y#0 reg byte x 4.0
|
||||
byte print1::p_y#2 reg byte x 4.333333333333333
|
||||
void print2(struct Point print2::p , byte print2::idx)
|
||||
byte~ print2::$0 reg byte y 22.0
|
||||
byte print2::idx
|
||||
byte print2::idx#2 reg byte a 11.0
|
||||
struct Point print2::p loadstore zp[2]:5
|
||||
|
||||
reg byte a [ print1::idx#2 ]
|
||||
reg byte y [ print1::p_x#2 print1::p_x#0 ]
|
||||
reg byte x [ print1::p_y#2 print1::p_y#0 ]
|
||||
reg byte a [ print2::idx#2 ]
|
||||
zp[1]:2 [ print1::$0 ]
|
||||
reg byte y [ print2::$0 ]
|
||||
zp[2]:3 [ main::p1 ]
|
||||
zp[2]:5 [ print2::p ]
|
Loading…
Reference in New Issue
Block a user