1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Added test refs.

This commit is contained in:
jespergravgaard 2019-07-26 14:31:37 +02:00
parent a30939e72c
commit f336907efd
8 changed files with 2286 additions and 0 deletions

View File

@ -0,0 +1,58 @@
// Demonstrates problem with returning a dereferenced pointer to a struct
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
.label p0 = $a000
.label p1 = $b000
.label p2 = $e000
main: {
.label _1_x = 3
.label _1_y = 4
lda #0
jsr get
lda get.return_y
stx SCREEN
sta SCREEN+OFFSET_STRUCT_POINT_Y
ldy #1
b1:
tya
jsr get
lda get.return_y
stx _1_x
sta _1_y
tya
asl
tax
lda _1_x
sta SCREEN,x
lda _1_y
sta SCREEN+OFFSET_STRUCT_POINT_Y,x
iny
cpy #3
bne b1
rts
}
// get(byte register(A) i)
get: {
.label return_y = 2
cmp #0
beq b1
cmp #1
beq b2
ldx p2
lda p2+OFFSET_STRUCT_POINT_Y
sta return_y
rts
b2:
ldx p1
lda p1+OFFSET_STRUCT_POINT_Y
sta return_y
rts
b1:
ldx p0
lda p0+OFFSET_STRUCT_POINT_Y
sta return_y
rts
}

View File

@ -0,0 +1,64 @@
@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] phi()
[5] call get
[6] (byte) get::return_x#0 ← (byte) get::return_x#5
[7] (byte) get::return_y#0 ← (byte) get::return_y#5
to:main::@2
main::@2: scope:[main] from main
[8] (byte) main::$0_x ← (byte) get::return_x#0
[9] (byte) main::$0_y ← (byte) get::return_y#0
[10] *((byte*)(const struct Point*) SCREEN#0) ← (byte) main::$0_x
[11] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (byte) main::$0_y
to:main::@1
main::@1: scope:[main] from main::@2 main::@3
[12] (byte) main::i#2 ← phi( main::@2/(byte) 1 main::@3/(byte) main::i#1 )
[13] (byte) get::i#1 ← (byte) main::i#2
[14] call get
[15] (byte) get::return_x#1 ← (byte) get::return_x#5
[16] (byte) get::return_y#1 ← (byte) get::return_y#5
to:main::@3
main::@3: scope:[main] from main::@1
[17] (byte) main::$1_x ← (byte) get::return_x#1
[18] (byte) main::$1_y ← (byte) get::return_y#1
[19] (byte~) main::$3 ← (byte) main::i#2 << (byte) 1
[20] *((byte*)(const struct Point*) SCREEN#0 + (byte~) main::$3) ← (byte) main::$1_x
[21] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$3) ← (byte) main::$1_y
[22] (byte) main::i#1 ← ++ (byte) main::i#2
[23] if((byte) main::i#1!=(byte) 3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
[24] return
to:@return
get: scope:[get] from main main::@1
[25] (byte) get::i#2 ← phi( main/(byte) 0 main::@1/(byte) get::i#1 )
[26] if((byte) get::i#2==(byte) 0) goto get::@1
to:get::@3
get::@3: scope:[get] from get
[27] if((byte) get::i#2==(byte) 1) goto get::@2
to:get::@4
get::@4: scope:[get] from get::@3
[28] (byte) get::return_x#4 ← *((byte*)(const struct Point*) p2#0)
[29] (byte) get::return_y#4 ← *((byte*)(const struct Point*) p2#0+(const byte) OFFSET_STRUCT_POINT_Y)
to:get::@return
get::@return: scope:[get] from get::@1 get::@2 get::@4
[30] (byte) get::return_y#5 ← phi( get::@1/(byte) get::return_y#2 get::@2/(byte) get::return_y#3 get::@4/(byte) get::return_y#4 )
[30] (byte) get::return_x#5 ← phi( get::@1/(byte) get::return_x#2 get::@2/(byte) get::return_x#3 get::@4/(byte) get::return_x#4 )
[31] return
to:@return
get::@2: scope:[get] from get::@3
[32] (byte) get::return_x#3 ← *((byte*)(const struct Point*) p1#0)
[33] (byte) get::return_y#3 ← *((byte*)(const struct Point*) p1#0+(const byte) OFFSET_STRUCT_POINT_Y)
to:get::@return
get::@1: scope:[get] from get
[34] (byte) get::return_x#2 ← *((byte*)(const struct Point*) p0#0)
[35] (byte) get::return_y#2 ← *((byte*)(const struct Point*) p0#0+(const byte) OFFSET_STRUCT_POINT_Y)
to:get::@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,67 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(struct Point*) SCREEN
(const struct Point*) SCREEN#0 SCREEN = (struct Point*) 1024
(struct Point()) get((byte) get::i)
(label) get::@1
(label) get::@2
(label) get::@3
(label) get::@4
(label) get::@return
(byte) get::i
(byte) get::i#1 reg byte a 22.0
(byte) get::i#2 reg byte a 7.5
(struct Point) get::return
(byte) get::return_x
(byte) get::return_x#0 reg byte x 2.0
(byte) get::return_x#1 reg byte x 11.0
(byte) get::return_x#2 reg byte x 2.0
(byte) get::return_x#3 reg byte x 2.0
(byte) get::return_x#4 reg byte x 2.0
(byte) get::return_x#5 reg byte x 4.75
(byte) get::return_y
(byte) get::return_y#0 reg byte a 2.0
(byte) get::return_y#1 reg byte a 11.0
(byte) get::return_y#2 return_y zp ZP_BYTE:2 4.0
(byte) get::return_y#3 return_y zp ZP_BYTE:2 4.0
(byte) get::return_y#4 return_y zp ZP_BYTE:2 4.0
(byte) get::return_y#5 return_y zp ZP_BYTE:2 3.166666666666667
(void()) main()
(struct Point~) main::$0
(byte) main::$0_x reg byte x 2.0
(byte) main::$0_y reg byte a 2.0
(struct Point~) main::$1
(byte) main::$1_x $1_x zp ZP_BYTE:3 7.333333333333333
(byte) main::$1_y $1_y zp ZP_BYTE:4 7.333333333333333
(byte~) main::$3 reg byte x 16.5
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte y 16.5
(byte) main::i#2 reg byte y 4.4
(struct Point*) p0
(const struct Point*) p0#0 p0 = (struct Point*) 40960
(struct Point*) p1
(const struct Point*) p1#0 p1 = (struct Point*) 45056
(struct Point*) p2
(const struct Point*) p2#0 p2 = (struct Point*) 57344
reg byte y [ main::i#2 main::i#1 ]
reg byte a [ get::i#2 get::i#1 ]
reg byte x [ get::return_x#5 get::return_x#2 get::return_x#3 get::return_x#4 ]
zp ZP_BYTE:2 [ get::return_y#5 get::return_y#2 get::return_y#3 get::return_y#4 ]
reg byte x [ get::return_x#0 ]
reg byte a [ get::return_y#0 ]
reg byte x [ main::$0_x ]
reg byte a [ main::$0_y ]
reg byte x [ get::return_x#1 ]
reg byte a [ get::return_y#1 ]
zp ZP_BYTE:3 [ main::$1_x ]
zp ZP_BYTE:4 [ main::$1_y ]
reg byte x [ main::$3 ]

View File

@ -0,0 +1,35 @@
// Demonstrates problem with returning a struct into a dereferenced pointer to a struct
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.const OFFSET_STRUCT_POINT_Y = 1
.label SCREEN = $400
main: {
.label _1_x = 2
lda #0
jsr get
sta SCREEN
lda #get.p_y
sta SCREEN+OFFSET_STRUCT_POINT_Y
ldy #1
b1:
tya
jsr get
sta _1_x
tya
asl
tax
lda _1_x
sta SCREEN,x
lda #get.p_y
sta SCREEN+OFFSET_STRUCT_POINT_Y,x
iny
cpy #3
bne b1
rts
}
// get(byte register(A) i)
get: {
.label p_y = 7
rts
}

View File

@ -0,0 +1,42 @@
@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] phi()
[5] call get
[6] (byte) get::return_x#0 ← (byte) get::return_x#2
to:main::@2
main::@2: scope:[main] from main
[7] (byte) main::$0_x ← (byte) get::return_x#0
[8] *((byte*)(const struct Point*) SCREEN#0) ← (byte) main::$0_x
[9] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) get::p_y#0
to:main::@1
main::@1: scope:[main] from main::@2 main::@3
[10] (byte) main::i#2 ← phi( main::@2/(byte) 1 main::@3/(byte) main::i#1 )
[11] (byte) get::i#1 ← (byte) main::i#2
[12] call get
[13] (byte) get::return_x#1 ← (byte) get::return_x#2
to:main::@3
main::@3: scope:[main] from main::@1
[14] (byte) main::$1_x ← (byte) get::return_x#1
[15] (byte~) main::$3 ← (byte) main::i#2 << (byte) 1
[16] *((byte*)(const struct Point*) SCREEN#0 + (byte~) main::$3) ← (byte) main::$1_x
[17] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$3) ← (const byte) get::p_y#0
[18] (byte) main::i#1 ← ++ (byte) main::i#2
[19] if((byte) main::i#1!=(byte) 3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
[20] return
to:@return
get: scope:[get] from main main::@1
[21] (byte) get::return_x#2 ← phi( main/(byte) 0 main::@1/(byte) get::i#1 )
to:get::@return
get::@return: scope:[get] from get
[22] return
to:@return

View File

@ -0,0 +1,800 @@
Fixing pointer array-indexing *((struct Point*) SCREEN + (byte) main::i)
Created struct value member variable (byte) main::$0_x
Created struct value member variable (byte) main::$0_y
Converted struct value to member variables (struct Point~) main::$0
Created struct value member variable (byte) main::$1_x
Created struct value member variable (byte) main::$1_y
Converted struct value to member variables (struct Point~) main::$1
Created struct value member variable (byte) get::return_x
Created struct value member variable (byte) get::return_y
Converted struct value to member variables (struct Point) get::return
Created struct value member variable (byte) get::p_x
Created struct value member variable (byte) get::p_y
Converted struct value to member variables (struct Point) get::p
Converted procedure call LValue to member unwinding { (byte) main::$0_x, (byte) main::$0_y } ← call get (number) 0
Adding struct value member variable copy *((byte*) main::$4) ← (byte) main::$0_x
Adding struct value member variable copy *((byte*) main::$5) ← (byte) main::$0_y
Converted procedure call LValue to member unwinding { (byte) main::$1_x, (byte) main::$1_y } ← call get (byte) main::i
Adding struct value member variable copy *((byte*) main::$6 + (byte~) main::$3) ← (byte) main::$1_x
Adding struct value member variable copy *((byte*) main::$7 + (byte~) main::$3) ← (byte) main::$1_y
Adding struct value list initializer (byte) get::p_x ← (byte) get::i
Adding struct value list initializer (byte) get::p_y ← (number) 7
Adding struct value member variable copy (byte) get::return_x ← (byte) get::p_x
Adding struct value member variable copy (byte) get::return_y ← (byte) get::p_y
Adding struct value member variable copy (byte) get::return_x ← (byte) get::return_x
Adding struct value member variable copy (byte) get::return_y ← (byte) get::return_y
Converted procedure struct return value to member unwinding return { (byte) get::return_x, (byte) get::return_y }
Identified constant variable (byte) idx
Identified constant variable (byte) get::p_y
Culled Empty Block (label) main::@2
Culled Empty Block (label) @1
Culled Empty Block (label) get::@1
Unwinding list assignment { (byte) main::$0_x, (byte) main::$0_y } ← { (byte) get::return_x, (byte) get::return_y }
Unwinding list assignment { (byte) main::$1_x, (byte) main::$1_y } ← { (byte) get::return_x, (byte) get::return_y }
Unwinding list assignment { (byte) get::return_x#0, (byte) get::return_y#0 } ← { (byte) get::return_x#3, (byte) get::return_y#3 }
Unwinding list assignment { (byte) get::return_x#1, (byte) get::return_y#1 } ← { (byte) get::return_x#3, (byte) get::return_y#3 }
Adding versioned struct unwinding for (struct Point) get::return#0
Adding versioned struct unwinding for (struct Point) get::return#1
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(struct Point*) SCREEN#0 ← ((struct Point*)) (number) $400
to:@2
main: scope:[main] from @2
(byte) get::i#0 ← (number) 0
call get
(byte) get::return_x#0 ← (byte) get::return_x#3
(byte) get::return_y#0 ← (byte) get::return_y#3
to:main::@3
main::@3: scope:[main] from main
(byte) get::return_y#4 ← phi( main/(byte) get::return_y#0 )
(byte) get::return_x#4 ← phi( main/(byte) get::return_x#0 )
(byte) main::$0_x ← (byte) get::return_x#4
(byte) main::$0_y ← (byte) get::return_y#4
(byte*) main::$4 ← (byte*)(struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*) main::$4) ← (byte) main::$0_x
(byte*) main::$5 ← (byte*)(struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*) main::$5) ← (byte) main::$0_y
(byte) main::i#0 ← (byte) 1
to:main::@1
main::@1: scope:[main] from main::@3 main::@4
(byte) main::i#2 ← phi( main::@3/(byte) main::i#0 main::@4/(byte) main::i#1 )
(byte) get::i#1 ← (byte) main::i#2
call get
(byte) get::return_x#1 ← (byte) get::return_x#3
(byte) get::return_y#1 ← (byte) get::return_y#3
to:main::@4
main::@4: scope:[main] from main::@1
(byte) main::i#3 ← phi( main::@1/(byte) main::i#2 )
(byte) get::return_y#5 ← phi( main::@1/(byte) get::return_y#1 )
(byte) get::return_x#5 ← phi( main::@1/(byte) get::return_x#1 )
(byte) main::$1_x ← (byte) get::return_x#5
(byte) main::$1_y ← (byte) get::return_y#5
(byte~) main::$3 ← (byte) main::i#3 * (const byte) SIZEOF_STRUCT_POINT
(byte*) main::$6 ← (byte*)(struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_X
*((byte*) main::$6 + (byte~) main::$3) ← (byte) main::$1_x
(byte*) main::$7 ← (byte*)(struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_Y
*((byte*) main::$7 + (byte~) main::$3) ← (byte) main::$1_y
(byte) main::i#1 ← (byte) main::i#3 + rangenext(1,2)
(bool~) main::$2 ← (byte) main::i#1 != rangelast(1,2)
if((bool~) main::$2) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
return
to:@return
get: scope:[get] from main main::@1
(byte) get::i#2 ← phi( main/(byte) get::i#0 main::@1/(byte) get::i#1 )
(byte) get::p_x#0 ← (byte) get::i#2
(byte) get::p_y#0 ← (number) 7
(byte) get::return_x#2 ← (byte) get::p_x#0
(byte) get::return_y#2 ← (byte) get::p_y#0
(struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#2, (byte) get::return_y#2}
to:get::@return
get::@return: scope:[get] from get
(byte) get::return_y#6 ← phi( get/(byte) get::return_y#2 )
(byte) get::return_x#6 ← phi( get/(byte) get::return_x#2 )
(byte) get::return_x#3 ← (byte) get::return_x#6
(byte) get::return_y#3 ← (byte) get::return_y#6
(struct Point) get::return#1 ← struct-unwound {(byte) get::return_x#3, (byte) get::return_y#3}
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
(struct Point*) SCREEN
(struct Point*) SCREEN#0
(const byte) SIZEOF_STRUCT_POINT = (byte) 2
(struct Point()) get((byte) get::i)
(label) get::@return
(byte) get::i
(byte) get::i#0
(byte) get::i#1
(byte) get::i#2
(byte) get::p_x
(byte) get::p_x#0
(byte) get::p_y
(byte) get::p_y#0
(struct Point) get::return
(struct Point) get::return#0
(struct Point) get::return#1
(byte) get::return_x
(byte) get::return_x#0
(byte) get::return_x#1
(byte) get::return_x#2
(byte) get::return_x#3
(byte) get::return_x#4
(byte) get::return_x#5
(byte) get::return_x#6
(byte) get::return_y
(byte) get::return_y#0
(byte) get::return_y#1
(byte) get::return_y#2
(byte) get::return_y#3
(byte) get::return_y#4
(byte) get::return_y#5
(byte) get::return_y#6
(void()) main()
(struct Point~) main::$0
(byte) main::$0_x
(byte) main::$0_y
(struct Point~) main::$1
(byte) main::$1_x
(byte) main::$1_y
(bool~) main::$2
(byte~) main::$3
(byte*) main::$4
(byte*) main::$5
(byte*) main::$6
(byte*) main::$7
(label) main::@1
(label) main::@3
(label) main::@4
(label) main::@return
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte) main::i#3
Adding number conversion cast (unumber) 0 in (byte) get::i#0 ← (number) 0
Adding number conversion cast (unumber) 7 in (byte) get::p_y#0 ← (number) 7
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (struct Point*) SCREEN#0 ← (struct Point*)(number) $400
Inlining cast (byte) get::i#0 ← (unumber)(number) 0
Inlining cast (byte) get::p_y#0 ← (unumber)(number) 7
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (struct Point*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 7
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 7
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (byte) get::return_x#0 = (byte) get::return_x#4
Alias (byte) get::return_y#0 = (byte) get::return_y#4
Alias (byte) get::return_x#1 = (byte) get::return_x#5
Alias (byte) get::return_y#1 = (byte) get::return_y#5
Alias (byte) main::i#2 = (byte) main::i#3
Alias (byte) get::return_x#2 = (byte) get::p_x#0 (byte) get::i#2 (byte) get::return_x#6 (byte) get::return_x#3
Alias (byte) get::p_y#0 = (byte) get::return_y#2 (byte) get::return_y#6 (byte) get::return_y#3
Successful SSA optimization Pass2AliasElimination
Simple Condition (bool~) main::$2 [28] if((byte) main::i#1!=rangelast(1,2)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const struct Point*) SCREEN#0 = (struct Point*) 1024
Constant (const byte) get::i#0 = 0
Constant (const byte) main::i#0 = 1
Constant (const byte) get::p_y#0 = 7
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte) get::return_y#0 = get::p_y#0
Constant (const byte) get::return_y#1 = get::p_y#0
Successful SSA optimization Pass2ConstantIdentification
Constant (const byte) main::$0_y = get::return_y#0
Constant (const byte) main::$1_y = get::return_y#1
Successful SSA optimization Pass2ConstantIdentification
Constant value identified (byte*)SCREEN#0 in [8] (byte*) main::$4 ← (byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)SCREEN#0 in [10] (byte*) main::$5 ← (byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_Y
Constant value identified (byte*)SCREEN#0 in [22] (byte*) main::$6 ← (byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_X
Constant value identified (byte*)SCREEN#0 in [24] (byte*) main::$7 ← (byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantValues
Resolved ranged next value [26] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [28] if(main::i#1!=rangelast(1,2)) goto main::@1 to (number) 3
Converting *(pointer+n) to pointer[n] [9] *((byte*) main::$4) ← (byte) main::$0_x -- *((byte*)SCREEN#0 + OFFSET_STRUCT_POINT_X)
Converting *(pointer+n) to pointer[n] [11] *((byte*) main::$5) ← (const byte) main::$0_y -- *((byte*)SCREEN#0 + OFFSET_STRUCT_POINT_Y)
Successful SSA optimization Pass2InlineDerefIdx
Simplifying expression containing zero (byte*)SCREEN#0 in [8] (byte*) main::$4 ← (byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_X
Simplifying expression containing zero (byte*)SCREEN#0 in [9] *((byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_X) ← (byte) main::$0_x
Simplifying expression containing zero (byte*)SCREEN#0 in [22] (byte*) main::$6 ← (byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (byte*) main::$4 and assignment [3] (byte*) main::$4 ← (byte*)(const struct Point*) SCREEN#0
Eliminating unused variable (byte*) main::$5 and assignment [5] (byte*) main::$5 ← (byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_Y
Eliminating unused variable (struct Point) get::return#0 and assignment [21] (struct Point) get::return#0 ← struct-unwound {(byte) get::return_x#2, (const byte) get::p_y#0}
Eliminating unused variable (struct Point) get::return#1 and assignment [22] (struct Point) get::return#1 ← struct-unwound {(byte) get::return_x#2, (const byte) get::p_y#0}
Eliminating unused constant (const byte) OFFSET_STRUCT_POINT_X
Successful SSA optimization PassNEliminateUnusedVars
Adding number conversion cast (unumber) 3 in if((byte) main::i#1!=(number) 3) goto main::@1
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 3
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 3
Successful SSA optimization PassNFinalizeNumberTypeConversions
Constant right-side identified [13] (byte*) main::$7 ← (byte*)(const struct Point*) SCREEN#0 + (const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte*) main::$6 = (byte*)SCREEN#0
Constant (const byte*) main::$7 = (byte*)SCREEN#0+OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantIdentification
Rewriting multiplication to use shift [10] (byte~) main::$3 ← (byte) main::i#2 * (const byte) SIZEOF_STRUCT_POINT
Successful SSA optimization Pass2MultiplyToShiftRewriting
Inlining constant with var siblings (const byte) main::i#0
Inlining constant with var siblings (const byte) get::i#0
Constant inlined main::$1_y = (const byte) get::p_y#0
Constant inlined main::$0_y = (const byte) get::p_y#0
Constant inlined main::i#0 = (byte) 1
Constant inlined main::$6 = (byte*)(const struct Point*) SCREEN#0
Constant inlined get::return_y#0 = (const byte) get::p_y#0
Constant inlined get::i#0 = (byte) 0
Constant inlined get::return_y#1 = (const byte) get::p_y#0
Constant inlined main::$7 = (byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *((byte*)SCREEN#0+OFFSET_STRUCT_POINT_Y)
Successful SSA optimization Pass2ConstantAdditionElimination
Eliminating unused constant (const byte) SIZEOF_STRUCT_POINT
Successful SSA optimization PassNEliminateUnusedVars
Added new block during phi lifting main::@5(between main::@4 and main::@1)
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
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Calls in [main] to get:6 get:14
Created 2 initial phi equivalence classes
Coalesced [13] get::return_x#7 ← get::i#1
Coalesced [23] main::i#4 ← main::i#1
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) @3
Culled Empty Block (label) main::@5
Renumbering block @2 to @1
Renumbering block main::@3 to main::@2
Renumbering block main::@4 to main::@3
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
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] phi()
[5] call get
[6] (byte) get::return_x#0 ← (byte) get::return_x#2
to:main::@2
main::@2: scope:[main] from main
[7] (byte) main::$0_x ← (byte) get::return_x#0
[8] *((byte*)(const struct Point*) SCREEN#0) ← (byte) main::$0_x
[9] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) get::p_y#0
to:main::@1
main::@1: scope:[main] from main::@2 main::@3
[10] (byte) main::i#2 ← phi( main::@2/(byte) 1 main::@3/(byte) main::i#1 )
[11] (byte) get::i#1 ← (byte) main::i#2
[12] call get
[13] (byte) get::return_x#1 ← (byte) get::return_x#2
to:main::@3
main::@3: scope:[main] from main::@1
[14] (byte) main::$1_x ← (byte) get::return_x#1
[15] (byte~) main::$3 ← (byte) main::i#2 << (byte) 1
[16] *((byte*)(const struct Point*) SCREEN#0 + (byte~) main::$3) ← (byte) main::$1_x
[17] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$3) ← (const byte) get::p_y#0
[18] (byte) main::i#1 ← ++ (byte) main::i#2
[19] if((byte) main::i#1!=(byte) 3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
[20] return
to:@return
get: scope:[get] from main main::@1
[21] (byte) get::return_x#2 ← phi( main/(byte) 0 main::@1/(byte) get::i#1 )
to:get::@return
get::@return: scope:[get] from get
[22] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte) Point::x
(byte) Point::y
(struct Point*) SCREEN
(struct Point()) get((byte) get::i)
(byte) get::i
(byte) get::i#1 22.0
(byte) get::p_x
(byte) get::p_y
(struct Point) get::return
(byte) get::return_x
(byte) get::return_x#0 4.0
(byte) get::return_x#1 22.0
(byte) get::return_x#2 6.0
(byte) get::return_y
(void()) main()
(struct Point~) main::$0
(byte) main::$0_x 4.0
(struct Point~) main::$1
(byte) main::$1_x 11.0
(byte~) main::$3 16.5
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 5.5
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
[ get::return_x#2 get::i#1 ]
Added variable get::return_x#0 to zero page equivalence class [ get::return_x#0 ]
Added variable main::$0_x to zero page equivalence class [ main::$0_x ]
Added variable get::return_x#1 to zero page equivalence class [ get::return_x#1 ]
Added variable main::$1_x to zero page equivalence class [ main::$1_x ]
Added variable main::$3 to zero page equivalence class [ main::$3 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ get::return_x#2 get::i#1 ]
[ get::return_x#0 ]
[ main::$0_x ]
[ get::return_x#1 ]
[ main::$1_x ]
[ main::$3 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:3 [ get::return_x#2 get::i#1 ]
Allocated zp ZP_BYTE:4 [ get::return_x#0 ]
Allocated zp ZP_BYTE:5 [ main::$0_x ]
Allocated zp ZP_BYTE:6 [ get::return_x#1 ]
Allocated zp ZP_BYTE:7 [ main::$1_x ]
Allocated zp ZP_BYTE:8 [ main::$3 ]
INITIAL ASM
Target platform is c64basic
// File Comments
// Demonstrates problem with returning a struct into a dereferenced pointer to a struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_POINT_Y = 1
.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 _3 = 8
.label _0_x = 5
.label _1_x = 7
.label i = 2
// [5] call get
// [21] phi from main to get [phi:main->get]
get_from_main:
// [21] phi (byte) get::return_x#2 = (byte) 0 [phi:main->get#0] -- vbuz1=vbuc1
lda #0
sta get.return_x_2
jsr get
// [6] (byte) get::return_x#0 ← (byte) get::return_x#2 -- vbuz1=vbuz2
lda get.return_x_2
sta get.return_x
jmp b2
// main::@2
b2:
// [7] (byte) main::$0_x ← (byte) get::return_x#0 -- vbuz1=vbuz2
lda get.return_x
sta _0_x
// [8] *((byte*)(const struct Point*) SCREEN#0) ← (byte) main::$0_x -- _deref_pbuc1=vbuz1
lda _0_x
sta SCREEN
// [9] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) get::p_y#0 -- _deref_pbuc1=vbuc2
lda #get.p_y
sta SCREEN+OFFSET_STRUCT_POINT_Y
// [10] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
b1_from_b2:
// [10] phi (byte) main::i#2 = (byte) 1 [phi:main::@2->main::@1#0] -- vbuz1=vbuc1
lda #1
sta i
jmp b1
// [10] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
// [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
// main::@1
b1:
// [11] (byte) get::i#1 ← (byte) main::i#2 -- vbuz1=vbuz2
lda i
sta get.i
// [12] call get
// [21] phi from main::@1 to get [phi:main::@1->get]
get_from_b1:
// [21] phi (byte) get::return_x#2 = (byte) get::i#1 [phi:main::@1->get#0] -- register_copy
jsr get
// [13] (byte) get::return_x#1 ← (byte) get::return_x#2 -- vbuz1=vbuz2
lda get.return_x_2
sta get.return_x_1
jmp b3
// main::@3
b3:
// [14] (byte) main::$1_x ← (byte) get::return_x#1 -- vbuz1=vbuz2
lda get.return_x_1
sta _1_x
// [15] (byte~) main::$3 ← (byte) main::i#2 << (byte) 1 -- vbuz1=vbuz2_rol_1
lda i
asl
sta _3
// [16] *((byte*)(const struct Point*) SCREEN#0 + (byte~) main::$3) ← (byte) main::$1_x -- pbuc1_derefidx_vbuz1=vbuz2
lda _1_x
ldy _3
sta SCREEN,y
// [17] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$3) ← (const byte) get::p_y#0 -- pbuc1_derefidx_vbuz1=vbuc2
lda #get.p_y
ldy _3
sta SCREEN+OFFSET_STRUCT_POINT_Y,y
// [18] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc i
// [19] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #3
cmp i
bne b1_from_b3
jmp breturn
// main::@return
breturn:
// [20] return
rts
}
// get
// get(byte zeropage(3) i)
get: {
.label p_y = 7
.label return_x = 4
.label i = 3
.label return_x_1 = 6
.label return_x_2 = 3
jmp breturn
// get::@return
breturn:
// [22] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [9] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) get::p_y#0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [15] (byte~) main::$3 ← (byte) main::i#2 << (byte) 1 [ main::i#2 main::$1_x main::$3 ] ( main:2 [ main::i#2 main::$1_x main::$3 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:7 [ main::$1_x ]
Statement [16] *((byte*)(const struct Point*) SCREEN#0 + (byte~) main::$3) ← (byte) main::$1_x [ main::i#2 main::$3 ] ( main:2 [ main::i#2 main::$3 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:8 [ main::$3 ]
Statement [17] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$3) ← (const byte) get::p_y#0 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [9] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) get::p_y#0 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [15] (byte~) main::$3 ← (byte) main::i#2 << (byte) 1 [ main::i#2 main::$1_x main::$3 ] ( main:2 [ main::i#2 main::$1_x main::$3 ] ) always clobbers reg byte a
Statement [16] *((byte*)(const struct Point*) SCREEN#0 + (byte~) main::$3) ← (byte) main::$1_x [ main::i#2 main::$3 ] ( main:2 [ main::i#2 main::$3 ] ) always clobbers reg byte a
Statement [17] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$3) ← (const byte) get::p_y#0 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:3 [ get::return_x#2 get::i#1 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:4 [ get::return_x#0 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:5 [ main::$0_x ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:6 [ get::return_x#1 ] : zp ZP_BYTE:6 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:7 [ main::$1_x ] : zp ZP_BYTE:7 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:8 [ main::$3 ] : zp ZP_BYTE:8 , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [get] 28: zp ZP_BYTE:3 [ get::return_x#2 get::i#1 ] 22: zp ZP_BYTE:6 [ get::return_x#1 ] 4: zp ZP_BYTE:4 [ get::return_x#0 ]
Uplift Scope [main] 22: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 16.5: zp ZP_BYTE:8 [ main::$3 ] 11: zp ZP_BYTE:7 [ main::$1_x ] 4: zp ZP_BYTE:5 [ main::$0_x ]
Uplift Scope [Point]
Uplift Scope []
Uplifting [get] best 732 combination reg byte a [ get::return_x#2 get::i#1 ] reg byte a [ get::return_x#1 ] reg byte a [ get::return_x#0 ]
Uplifting [main] best 546 combination reg byte y [ main::i#2 main::i#1 ] reg byte x [ main::$3 ] zp ZP_BYTE:7 [ main::$1_x ] reg byte a [ main::$0_x ]
Limited combination testing to 100 combinations of 108 possible.
Uplifting [Point] best 546 combination
Uplifting [] best 546 combination
Attempting to uplift remaining variables inzp ZP_BYTE:7 [ main::$1_x ]
Uplifting [main] best 546 combination zp ZP_BYTE:7 [ main::$1_x ]
Allocated (was zp ZP_BYTE:7) zp ZP_BYTE:2 [ main::$1_x ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Demonstrates problem with returning a struct into a dereferenced pointer to a struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_POINT_Y = 1
.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 _1_x = 2
// [5] call get
// [21] phi from main to get [phi:main->get]
get_from_main:
// [21] phi (byte) get::return_x#2 = (byte) 0 [phi:main->get#0] -- vbuaa=vbuc1
lda #0
jsr get
// [6] (byte) get::return_x#0 ← (byte) get::return_x#2
jmp b2
// main::@2
b2:
// [7] (byte) main::$0_x ← (byte) get::return_x#0
// [8] *((byte*)(const struct Point*) SCREEN#0) ← (byte) main::$0_x -- _deref_pbuc1=vbuaa
sta SCREEN
// [9] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) get::p_y#0 -- _deref_pbuc1=vbuc2
lda #get.p_y
sta SCREEN+OFFSET_STRUCT_POINT_Y
// [10] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
b1_from_b2:
// [10] phi (byte) main::i#2 = (byte) 1 [phi:main::@2->main::@1#0] -- vbuyy=vbuc1
ldy #1
jmp b1
// [10] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
// [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
// main::@1
b1:
// [11] (byte) get::i#1 ← (byte) main::i#2 -- vbuaa=vbuyy
tya
// [12] call get
// [21] phi from main::@1 to get [phi:main::@1->get]
get_from_b1:
// [21] phi (byte) get::return_x#2 = (byte) get::i#1 [phi:main::@1->get#0] -- register_copy
jsr get
// [13] (byte) get::return_x#1 ← (byte) get::return_x#2
jmp b3
// main::@3
b3:
// [14] (byte) main::$1_x ← (byte) get::return_x#1 -- vbuz1=vbuaa
sta _1_x
// [15] (byte~) main::$3 ← (byte) main::i#2 << (byte) 1 -- vbuxx=vbuyy_rol_1
tya
asl
tax
// [16] *((byte*)(const struct Point*) SCREEN#0 + (byte~) main::$3) ← (byte) main::$1_x -- pbuc1_derefidx_vbuxx=vbuz1
lda _1_x
sta SCREEN,x
// [17] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$3) ← (const byte) get::p_y#0 -- pbuc1_derefidx_vbuxx=vbuc2
lda #get.p_y
sta SCREEN+OFFSET_STRUCT_POINT_Y,x
// [18] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuyy=_inc_vbuyy
iny
// [19] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
cpy #3
bne b1_from_b3
jmp breturn
// main::@return
breturn:
// [20] return
rts
}
// get
// get(byte register(A) i)
get: {
.label p_y = 7
jmp breturn
// get::@return
breturn:
// [22] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b2
Removing instruction jmp b1
Removing instruction jmp b3
Removing instruction jmp breturn
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1_from_b3 with b1
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Removing instruction b1_from_b3:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction get_from_main:
Removing instruction b2:
Removing instruction b1_from_b2:
Removing instruction get_from_b1:
Removing instruction b3:
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 jmp b1
Succesful ASM optimization Pass5NextJumpElimination
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
(struct Point*) SCREEN
(const struct Point*) SCREEN#0 SCREEN = (struct Point*) 1024
(struct Point()) get((byte) get::i)
(label) get::@return
(byte) get::i
(byte) get::i#1 reg byte a 22.0
(byte) get::p_x
(byte) get::p_y
(const byte) get::p_y#0 p_y = (byte) 7
(struct Point) get::return
(byte) get::return_x
(byte) get::return_x#0 reg byte a 4.0
(byte) get::return_x#1 reg byte a 22.0
(byte) get::return_x#2 reg byte a 6.0
(byte) get::return_y
(void()) main()
(struct Point~) main::$0
(byte) main::$0_x reg byte a 4.0
(struct Point~) main::$1
(byte) main::$1_x $1_x zp ZP_BYTE:2 11.0
(byte~) main::$3 reg byte x 16.5
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte y 16.5
(byte) main::i#2 reg byte y 5.5
reg byte y [ main::i#2 main::i#1 ]
reg byte a [ get::return_x#2 get::i#1 ]
reg byte a [ get::return_x#0 ]
reg byte a [ main::$0_x ]
reg byte a [ get::return_x#1 ]
zp ZP_BYTE:2 [ main::$1_x ]
reg byte x [ main::$3 ]
FINAL ASSEMBLER
Score: 381
// File Comments
// Demonstrates problem with returning a struct into a dereferenced pointer to a struct
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_POINT_Y = 1
.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 _1_x = 2
// get(0)
// [5] call get
// [21] phi from main to get [phi:main->get]
// [21] phi (byte) get::return_x#2 = (byte) 0 [phi:main->get#0] -- vbuaa=vbuc1
lda #0
jsr get
// get(0)
// [6] (byte) get::return_x#0 ← (byte) get::return_x#2
// main::@2
// [7] (byte) main::$0_x ← (byte) get::return_x#0
// *SCREEN = get(0)
// [8] *((byte*)(const struct Point*) SCREEN#0) ← (byte) main::$0_x -- _deref_pbuc1=vbuaa
sta SCREEN
// [9] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y) ← (const byte) get::p_y#0 -- _deref_pbuc1=vbuc2
lda #get.p_y
sta SCREEN+OFFSET_STRUCT_POINT_Y
// [10] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
// [10] phi (byte) main::i#2 = (byte) 1 [phi:main::@2->main::@1#0] -- vbuyy=vbuc1
ldy #1
// [10] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
// [10] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
// main::@1
b1:
// get(i)
// [11] (byte) get::i#1 ← (byte) main::i#2 -- vbuaa=vbuyy
tya
// [12] call get
// [21] phi from main::@1 to get [phi:main::@1->get]
// [21] phi (byte) get::return_x#2 = (byte) get::i#1 [phi:main::@1->get#0] -- register_copy
jsr get
// get(i)
// [13] (byte) get::return_x#1 ← (byte) get::return_x#2
// main::@3
// [14] (byte) main::$1_x ← (byte) get::return_x#1 -- vbuz1=vbuaa
sta _1_x
// SCREEN[i] = get(i)
// [15] (byte~) main::$3 ← (byte) main::i#2 << (byte) 1 -- vbuxx=vbuyy_rol_1
tya
asl
tax
// [16] *((byte*)(const struct Point*) SCREEN#0 + (byte~) main::$3) ← (byte) main::$1_x -- pbuc1_derefidx_vbuxx=vbuz1
lda _1_x
sta SCREEN,x
// [17] *((byte*)(const struct Point*) SCREEN#0+(const byte) OFFSET_STRUCT_POINT_Y + (byte~) main::$3) ← (const byte) get::p_y#0 -- pbuc1_derefidx_vbuxx=vbuc2
lda #get.p_y
sta SCREEN+OFFSET_STRUCT_POINT_Y,x
// for ( char i: 1..2)
// [18] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuyy=_inc_vbuyy
iny
// [19] if((byte) main::i#1!=(byte) 3) goto main::@1 -- vbuyy_neq_vbuc1_then_la1
cpy #3
bne b1
// main::@return
// }
// [20] return
rts
}
// get
// get(byte register(A) i)
get: {
.label p_y = 7
// get::@return
// [22] return
rts
}
// File Data

View File

@ -0,0 +1,42 @@
(label) @1
(label) @begin
(label) @end
(const byte) OFFSET_STRUCT_POINT_Y OFFSET_STRUCT_POINT_Y = (byte) 1
(byte) Point::x
(byte) Point::y
(struct Point*) SCREEN
(const struct Point*) SCREEN#0 SCREEN = (struct Point*) 1024
(struct Point()) get((byte) get::i)
(label) get::@return
(byte) get::i
(byte) get::i#1 reg byte a 22.0
(byte) get::p_x
(byte) get::p_y
(const byte) get::p_y#0 p_y = (byte) 7
(struct Point) get::return
(byte) get::return_x
(byte) get::return_x#0 reg byte a 4.0
(byte) get::return_x#1 reg byte a 22.0
(byte) get::return_x#2 reg byte a 6.0
(byte) get::return_y
(void()) main()
(struct Point~) main::$0
(byte) main::$0_x reg byte a 4.0
(struct Point~) main::$1
(byte) main::$1_x $1_x zp ZP_BYTE:2 11.0
(byte~) main::$3 reg byte x 16.5
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte y 16.5
(byte) main::i#2 reg byte y 5.5
reg byte y [ main::i#2 main::i#1 ]
reg byte a [ get::return_x#2 get::i#1 ]
reg byte a [ get::return_x#0 ]
reg byte a [ main::$0_x ]
reg byte a [ get::return_x#1 ]
zp ZP_BYTE:2 [ main::$1_x ]
reg byte x [ main::$3 ]