1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-10-02 22:56:11 +00:00
kickc/src/test/ref/struct-ptr-28.log

1029 lines
44 KiB
Plaintext

Setting inferred volatile on symbol affected by address-of (struct Person*~) main::$0 ← & (struct Person) main::jesper
Setting inferred volatile on symbol affected by address-of (struct Person*~) main::$2 ← & (struct Person) main::henriette
Created struct value member variable (byte) main::jesper_id
Created struct value member variable (byte[$10]) main::jesper_name
Converted struct value to member variables (struct Person) main::jesper
Created struct value member variable (byte) main::henriette_id
Created struct value member variable (byte[$10]) main::henriette_name
Converted struct value to member variables (struct Person) main::henriette
Adding struct value list initializer (byte) main::jesper_id ← (number) 4
Adding struct value list initializer (byte[$10]) main::jesper_name ← (string) "jesper"
Adding struct value list initializer (byte) main::henriette_id ← (number) 7
Adding struct value list initializer (byte[$10]) main::henriette_name ← (string) "henriette"
Rewriting struct pointer member access *((struct Person*) print_person::person).id
Rewriting struct pointer member access *((struct Person*) print_person::person).name
Rewriting struct pointer member access *((struct Person*) print_person::person).name
Warning! Adding boolean cast to non-boolean condition *(*((byte[$10]*) print_person::$1) + (byte) print_person::i)
Culled Empty Block (label) print_person::@4
Culled Empty Block (label) print_person::@5
Culled Empty Block (label) print_person::@6
Adding versioned struct unwinding for (struct Person) main::jesper#0
Adding versioned struct unwinding for (struct Person) main::henriette#0
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
main: scope:[main] from @2
(byte) idx#18 ← phi( @2/(byte) idx#20 )
(byte) main::jesper_id#0 ← (number) 4
(byte[$10]) main::jesper_name#0 ← (const string) main::$4
(struct Person) main::jesper#0 ← struct-unwound {(byte) main::jesper_id#0, (byte[$10]) main::jesper_name#0}
(struct Person*~) main::$0 ← & (struct Person) main::jesper#0
(struct Person*) print_person::person#0 ← (struct Person*~) main::$0
call print_person
to:main::@1
main::@1: scope:[main] from main
(byte) idx#10 ← phi( main/(byte) idx#8 )
(byte) idx#0 ← (byte) idx#10
(byte) main::henriette_id#0 ← (number) 7
(byte[$10]) main::henriette_name#0 ← (const string) main::$5
(struct Person) main::henriette#0 ← struct-unwound {(byte) main::henriette_id#0, (byte[$10]) main::henriette_name#0}
(struct Person*~) main::$2 ← & (struct Person) main::henriette#0
(struct Person*) print_person::person#1 ← (struct Person*~) main::$2
call print_person
to:main::@2
main::@2: scope:[main] from main::@1
(byte) idx#11 ← phi( main::@1/(byte) idx#8 )
(byte) idx#1 ← (byte) idx#11
to:main::@return
main::@return: scope:[main] from main::@2
(byte) idx#12 ← phi( main::@2/(byte) idx#1 )
(byte) idx#2 ← (byte) idx#12
return
to:@return
@1: scope:[] from @begin
(byte*) SCREEN#0 ← ((byte*)) (number) $400
(byte) idx#3 ← (number) 0
(byte[]) DIGIT#0 ← (const string) $0
to:@2
print_person: scope:[print_person] from main main::@1
(byte) idx#13 ← phi( main/(byte) idx#18 main::@1/(byte) idx#0 )
(struct Person*) print_person::person#2 ← phi( main/(struct Person*) print_person::person#0 main::@1/(struct Person*) print_person::person#1 )
(byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID
*((byte*) SCREEN#0 + (byte) idx#13) ← *((byte[]) DIGIT#0 + *((byte*) print_person::$0))
(byte) idx#4 ← ++ (byte) idx#13
*((byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
(byte) idx#5 ← ++ (byte) idx#4
(byte) print_person::i#0 ← (number) 0
to:print_person::@1
print_person::@1: scope:[print_person] from print_person print_person::@2
(byte) idx#19 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
(byte) print_person::i#2 ← phi( print_person/(byte) print_person::i#0 print_person::@2/(byte) print_person::i#1 )
(struct Person*) print_person::person#3 ← phi( print_person/(struct Person*) print_person::person#2 print_person::@2/(struct Person*) print_person::person#4 )
(byte[$10]*) print_person::$1 ← (byte[$10]*)(struct Person*) print_person::person#3 + (const byte) OFFSET_STRUCT_PERSON_NAME
(bool~) print_person::$3 ← (number) 0 != *(*((byte[$10]*) print_person::$1) + (byte) print_person::i#2)
if((bool~) print_person::$3) goto print_person::@2
to:print_person::@3
print_person::@2: scope:[print_person] from print_person::@1
(byte) idx#14 ← phi( print_person::@1/(byte) idx#19 )
(byte) print_person::i#3 ← phi( print_person::@1/(byte) print_person::i#2 )
(struct Person*) print_person::person#4 ← phi( print_person::@1/(struct Person*) print_person::person#3 )
(byte[$10]*) print_person::$2 ← (byte[$10]*)(struct Person*) print_person::person#4 + (const byte) OFFSET_STRUCT_PERSON_NAME
*((byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*) print_person::$2) + (byte) print_person::i#3)
(byte) idx#6 ← ++ (byte) idx#14
(byte) print_person::i#1 ← ++ (byte) print_person::i#3
to:print_person::@1
print_person::@3: scope:[print_person] from print_person::@1
(byte) idx#15 ← phi( print_person::@1/(byte) idx#19 )
*((byte*) SCREEN#0 + (byte) idx#15) ← (byte) ' '
(byte) idx#7 ← ++ (byte) idx#15
to:print_person::@return
print_person::@return: scope:[print_person] from print_person::@3
(byte) idx#16 ← phi( print_person::@3/(byte) idx#7 )
(byte) idx#8 ← (byte) idx#16
return
to:@return
@2: scope:[] from @1
(byte) idx#20 ← phi( @1/(byte) idx#3 )
call main
to:@3
@3: scope:[] from @2
(byte) idx#17 ← phi( @2/(byte) idx#2 )
(byte) idx#9 ← (byte) idx#17
to:@end
@end: scope:[] from @3
SYMBOL TABLE SSA
(const string) $0 = (string) "0123456789"
(label) @1
(label) @2
(label) @3
(label) @begin
(label) @end
(byte[]) DIGIT
(byte[]) DIGIT#0
(const byte) OFFSET_STRUCT_PERSON_ID = (byte) 0
(const byte) OFFSET_STRUCT_PERSON_NAME = (byte) 1
(byte) Person::id
(byte[$10]) Person::name
(byte*) SCREEN
(byte*) SCREEN#0
(byte) idx
(byte) idx#0
(byte) idx#1
(byte) idx#10
(byte) idx#11
(byte) idx#12
(byte) idx#13
(byte) idx#14
(byte) idx#15
(byte) idx#16
(byte) idx#17
(byte) idx#18
(byte) idx#19
(byte) idx#2
(byte) idx#20
(byte) idx#3
(byte) idx#4
(byte) idx#5
(byte) idx#6
(byte) idx#7
(byte) idx#8
(byte) idx#9
(void()) main()
(struct Person*~) main::$0
(struct Person*~) main::$2
(const string) main::$4 = (string) "jesper"
(const string) main::$5 = (string) "henriette"
(label) main::@1
(label) main::@2
(label) main::@return
(struct Person) main::henriette
(struct Person) main::henriette#0
(byte) main::henriette_id
(byte) main::henriette_id#0
(byte[$10]) main::henriette_name
(byte[$10]) main::henriette_name#0
(struct Person) main::jesper
(struct Person) main::jesper#0
(byte) main::jesper_id
(byte) main::jesper_id#0
(byte[$10]) main::jesper_name
(byte[$10]) main::jesper_name#0
(void()) print_person((struct Person*) print_person::person)
(byte*) print_person::$0
(byte[$10]*) print_person::$1
(byte[$10]*) print_person::$2
(bool~) print_person::$3
(label) print_person::@1
(label) print_person::@2
(label) print_person::@3
(label) print_person::@return
(byte) print_person::i
(byte) print_person::i#0
(byte) print_person::i#1
(byte) print_person::i#2
(byte) print_person::i#3
(struct Person*) print_person::person
(struct Person*) print_person::person#0
(struct Person*) print_person::person#1
(struct Person*) print_person::person#2
(struct Person*) print_person::person#3
(struct Person*) print_person::person#4
Adding number conversion cast (unumber) 4 in (byte) main::jesper_id#0 ← (number) 4
Adding number conversion cast (unumber) 7 in (byte) main::henriette_id#0 ← (number) 7
Adding number conversion cast (unumber) 0 in (byte) idx#3 ← (number) 0
Adding number conversion cast (unumber) 0 in (byte) print_person::i#0 ← (number) 0
Adding number conversion cast (unumber) 0 in (bool~) print_person::$3 ← (number) 0 != *(*((byte[$10]*) print_person::$1) + (byte) print_person::i#2)
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte) main::jesper_id#0 ← (unumber)(number) 4
Inlining cast (byte) main::henriette_id#0 ← (unumber)(number) 7
Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400
Inlining cast (byte) idx#3 ← (unumber)(number) 0
Inlining cast (byte) print_person::i#0 ← (unumber)(number) 0
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast 4
Simplifying constant integer cast 7
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 4
Finalized unsigned number type (byte) 7
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias (struct Person*) print_person::person#0 = (struct Person*~) main::$0
Alias (byte) idx#0 = (byte) idx#10
Alias (struct Person*) print_person::person#1 = (struct Person*~) main::$2
Alias (byte) idx#1 = (byte) idx#11 (byte) idx#12 (byte) idx#2
Alias (struct Person*) print_person::person#3 = (struct Person*) print_person::person#4
Alias (byte) print_person::i#2 = (byte) print_person::i#3
Alias (byte) idx#14 = (byte) idx#19 (byte) idx#15
Alias (byte) idx#16 = (byte) idx#7 (byte) idx#8
Alias (byte) idx#20 = (byte) idx#3
Alias (byte) idx#17 = (byte) idx#9
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte) idx#18 (byte) idx#20
Identical Phi Values (byte) idx#0 (byte) idx#16
Identical Phi Values (byte) idx#1 (byte) idx#16
Identical Phi Values (struct Person*) print_person::person#3 (struct Person*) print_person::person#2
Identical Phi Values (byte) idx#17 (byte) idx#1
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) print_person::$3 [33] if((byte) 0!=*(*((byte[$10]*) print_person::$1) + (byte) print_person::i#2)) goto print_person::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Rewriting struct address-of to first member [4] (struct Person*) print_person::person#0 ← (struct Person*)&(byte) main::jesper_id#0
Rewriting struct address-of to first member [12] (struct Person*) print_person::person#1 ← (struct Person*)&(byte) main::henriette_id#0
Successful SSA optimization PassNStructAddressOfRewriting
Constant right-side identified [4] (struct Person*) print_person::person#0 ← (struct Person*)&(byte) main::jesper_id#0
Constant right-side identified [12] (struct Person*) print_person::person#1 ← (struct Person*)&(byte) main::henriette_id#0
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const struct Person*) print_person::person#0 = (struct Person*)&main::jesper_id#0
Constant (const struct Person*) print_person::person#1 = (struct Person*)&main::henriette_id#0
Constant (const byte*) SCREEN#0 = (byte*) 1024
Constant (const byte) idx#20 = 0
Constant (const byte[]) DIGIT#0 = $0
Constant (const byte) print_person::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Converting *(pointer+n) to pointer[n] [25] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*) print_person::$0)) -- *((byte*)print_person::person#2 + OFFSET_STRUCT_PERSON_ID)
Converting *(pointer+n) to pointer[n] [33] if((byte) 0!=*(*((byte[$10]*) print_person::$1) + (byte) print_person::i#2)) goto print_person::@2 -- *((byte[$10]*)print_person::person#2 + OFFSET_STRUCT_PERSON_NAME)
Converting *(pointer+n) to pointer[n] [36] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*) print_person::$2) + (byte) print_person::i#2) -- *((byte[$10]*)print_person::person#2 + OFFSET_STRUCT_PERSON_NAME)
Successful SSA optimization Pass2InlineDerefIdx
Simplifying expression containing zero (byte*)print_person::person#2 in [24] (byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID
Simplifying expression containing zero (byte*)print_person::person#2 in [25] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_ID))
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused variable (struct Person) main::jesper#0 and assignment [2] (struct Person) main::jesper#0 ← struct-unwound {(byte) main::jesper_id#0, (byte[$10]) main::jesper_name#0}
Eliminating unused variable (struct Person) main::henriette#0 and assignment [6] (struct Person) main::henriette#0 ← struct-unwound {(byte) main::henriette_id#0, (byte[$10]) main::henriette_name#0}
Eliminating unused variable (byte*) print_person::$0 and assignment [10] (byte*) print_person::$0 ← (byte*)(struct Person*) print_person::person#2
Eliminating unused variable (byte[$10]*) print_person::$1 and assignment [16] (byte[$10]*) print_person::$1 ← (byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME
Eliminating unused variable (byte[$10]*) print_person::$2 and assignment [18] (byte[$10]*) print_person::$2 ← (byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME
Eliminating unused constant (const byte) OFFSET_STRUCT_PERSON_ID
Successful SSA optimization PassNEliminateUnusedVars
Inlining constant with var siblings (const struct Person*) print_person::person#0
Inlining constant with var siblings (const struct Person*) print_person::person#1
Inlining constant with var siblings (const byte) print_person::i#0
Inlining constant with var siblings (const byte) idx#20
Constant inlined idx#20 = (byte) 0
Constant inlined $0 = (const byte[]) DIGIT#0
Constant inlined print_person::person#0 = (struct Person*)&(byte) main::jesper_id#0
Constant inlined print_person::i#0 = (byte) 0
Constant inlined print_person::person#1 = (struct Person*)&(byte) main::henriette_id#0
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @2
Adding NOP phi() at start of @3
Adding NOP phi() at start of @end
Adding NOP phi() at start of main::@2
CALL GRAPH
Calls in [] to main:3
Calls in [main] to print_person:8 print_person:12
Created 4 initial phi equivalence classes
Coalesced [11] idx#21 ← idx#16
Coalesced [20] idx#22 ← idx#5
Coalesced [29] print_person::i#4 ← print_person::i#1
Coalesced [30] idx#23 ← idx#6
Coalesced down to 4 phi equivalence classes
Culled Empty Block (label) @1
Culled Empty Block (label) @3
Culled Empty Block (label) main::@2
Renumbering block @2 to @1
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] (byte) main::jesper_id#0 ← (byte) 4
[5] (byte[$10]) main::jesper_name#0 ← (const string) main::$4
[6] call print_person
to:main::@1
main::@1: scope:[main] from main
[7] (byte) main::henriette_id#0 ← (byte) 7
[8] (byte[$10]) main::henriette_name#0 ← (const string) main::$5
[9] call print_person
to:main::@return
main::@return: scope:[main] from main::@1
[10] return
to:@return
print_person: scope:[print_person] from main main::@1
[11] (byte) idx#13 ← phi( main/(byte) 0 main::@1/(byte) idx#16 )
[11] (struct Person*) print_person::person#2 ← phi( main/(struct Person*)&(byte) main::jesper_id#0 main::@1/(struct Person*)&(byte) main::henriette_id#0 )
[12] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2))
[13] (byte) idx#4 ← ++ (byte) idx#13
[14] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' '
[15] (byte) idx#5 ← ++ (byte) idx#4
to:print_person::@1
print_person::@1: scope:[print_person] from print_person print_person::@2
[16] (byte) idx#14 ← phi( print_person/(byte) idx#5 print_person::@2/(byte) idx#6 )
[16] (byte) print_person::i#2 ← phi( print_person/(byte) 0 print_person::@2/(byte) print_person::i#1 )
[17] if((byte) 0!=*(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2
to:print_person::@3
print_person::@3: scope:[print_person] from print_person::@1
[18] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' '
[19] (byte) idx#16 ← ++ (byte) idx#14
to:print_person::@return
print_person::@return: scope:[print_person] from print_person::@3
[20] return
to:@return
print_person::@2: scope:[print_person] from print_person::@1
[21] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)
[22] (byte) idx#6 ← ++ (byte) idx#14
[23] (byte) print_person::i#1 ← ++ (byte) print_person::i#2
to:print_person::@1
VARIABLE REGISTER WEIGHTS
(byte[]) DIGIT
(byte) Person::id
(byte[$10]) Person::name
(byte*) SCREEN
(byte) idx
(byte) idx#13 3.0
(byte) idx#14 9.75
(byte) idx#16 0.8
(byte) idx#4 3.0
(byte) idx#5 4.0
(byte) idx#6 11.0
(void()) main()
(struct Person) main::henriette
(byte) main::henriette_id
(byte) main::henriette_id#0 20.0
(byte[$10]) main::henriette_name
(byte[$10]) main::henriette_name#0 20.0
(struct Person) main::jesper
(byte) main::jesper_id
(byte) main::jesper_id#0 20.0
(byte[$10]) main::jesper_name
(byte[$10]) main::jesper_name#0 20.0
(void()) print_person((struct Person*) print_person::person)
(byte) print_person::i
(byte) print_person::i#1 22.0
(byte) print_person::i#2 11.0
(struct Person*) print_person::person
(struct Person*) print_person::person#2
Initial phi equivalence classes
[ print_person::person#2 ]
[ idx#13 idx#16 ]
[ print_person::i#2 print_person::i#1 ]
[ idx#14 idx#5 idx#6 ]
Added variable idx#4 to zero page equivalence class [ idx#4 ]
Complete equivalence classes
[ print_person::person#2 ]
[ idx#13 idx#16 ]
[ print_person::i#2 print_person::i#1 ]
[ idx#14 idx#5 idx#6 ]
[ main::jesper_id#0 ]
[ main::jesper_name#0 ]
[ main::henriette_id#0 ]
[ main::henriette_name#0 ]
[ idx#4 ]
Allocated zp ZP_WORD:2 [ print_person::person#2 ]
Allocated zp ZP_BYTE:4 [ idx#13 idx#16 ]
Allocated zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
Allocated zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ]
Allocated zp ZP_BYTE:7 [ main::jesper_id#0 ]
Allocated zp ZP_WORD:8 [ main::jesper_name#0 ]
Allocated zp ZP_BYTE:10 [ main::henriette_id#0 ]
Allocated zp ZP_WORD:11 [ main::henriette_name#0 ]
Allocated zp ZP_BYTE:13 [ idx#4 ]
INITIAL ASM
Target platform is c64basic / MOS6502X
// File Comments
// Example of a struct containing an array
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
// https://gitlab.com/camelot/kickc/issues/312
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_PERSON_NAME = 1
.label SCREEN = $400
.label idx = $d
.label idx_5 = 6
.label idx_6 = 6
.label idx_13 = 4
.label idx_14 = 6
.label idx_16 = 4
// @begin
bbegin:
// [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
// @1
b1:
// [2] call main
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label jesper_id = 7
.label jesper_name = 8
.label henriette_id = $a
.label henriette_name = $b
// [4] (byte) main::jesper_id#0 ← (byte) 4 -- vbuz1=vbuc1
lda #4
sta.z jesper_id
// [5] (byte[$10]) main::jesper_name#0 ← (const string) main::$4 -- pbuz1=pbuc1
lda #<_4
sta.z jesper_name
lda #>_4
sta.z jesper_name+1
// [6] call print_person
// [11] phi from main to print_person [phi:main->print_person]
print_person_from_main:
// [11] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#0] -- vbuz1=vbuc1
lda #0
sta.z idx_13
// [11] phi (struct Person*) print_person::person#2 = (struct Person*)&(byte) main::jesper_id#0 [phi:main->print_person#1] -- pssz1=pssc1
lda #<jesper_id
sta.z print_person.person
lda #>jesper_id
sta.z print_person.person+1
jsr print_person
jmp b1
// main::@1
b1:
// [7] (byte) main::henriette_id#0 ← (byte) 7 -- vbuz1=vbuc1
lda #7
sta.z henriette_id
// [8] (byte[$10]) main::henriette_name#0 ← (const string) main::$5 -- pbuz1=pbuc1
lda #<_5
sta.z henriette_name
lda #>_5
sta.z henriette_name+1
// [9] call print_person
// [11] phi from main::@1 to print_person [phi:main::@1->print_person]
print_person_from_b1:
// [11] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#0] -- register_copy
// [11] phi (struct Person*) print_person::person#2 = (struct Person*)&(byte) main::henriette_id#0 [phi:main::@1->print_person#1] -- pssz1=pssc1
lda #<henriette_id
sta.z print_person.person
lda #>henriette_id
sta.z print_person.person+1
jsr print_person
jmp breturn
// main::@return
breturn:
// [10] return
rts
_4: .text "jesper"
.byte 0
_5: .text "henriette"
.byte 0
}
// print_person
// print_person(struct Person* zeropage(2) person)
print_person: {
.label i = 5
.label person = 2
// [12] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_(_deref_pbuz2)
ldx.z idx_13
ldy #0
lda (person),y
tay
lda DIGIT,y
sta SCREEN,x
// [13] (byte) idx#4 ← ++ (byte) idx#13 -- vbuz1=_inc_vbuz2
ldy.z idx_13
iny
sty.z idx
// [14] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
lda #' '
ldy.z idx
sta SCREEN,y
// [15] (byte) idx#5 ← ++ (byte) idx#4 -- vbuz1=_inc_vbuz2
ldy.z idx
iny
sty.z idx_5
// [16] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
b1_from_print_person:
// [16] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
// [16] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuz1=vbuc1
lda #0
sta.z i
jmp b1
// print_person::@1
b1:
// [17] if((byte) 0!=*(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_(pptz1_derefidx_vbuc2)_derefidx_vbuz2_then_la1
ldy #OFFSET_STRUCT_PERSON_NAME
lda (person),y
sta.z $fe
iny
lda (person),y
sta.z $ff
ldy.z i
lda ($fe),y
cmp #0
bne b2
jmp b3
// print_person::@3
b3:
// [18] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuz1=vbuc2
lda #' '
ldy.z idx_14
sta SCREEN,y
// [19] (byte) idx#16 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz2
ldy.z idx_14
iny
sty.z idx_16
jmp breturn
// print_person::@return
breturn:
// [20] return
rts
// print_person::@2
b2:
// [21] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) -- pbuc1_derefidx_vbuz1=(pptz2_derefidx_vbuc2)_derefidx_vbuz3
ldx.z idx_14
ldy #OFFSET_STRUCT_PERSON_NAME
lda (person),y
sta.z $fe
iny
lda (person),y
sta.z $ff
ldy.z i
lda ($fe),y
sta SCREEN,x
// [22] (byte) idx#6 ← ++ (byte) idx#14 -- vbuz1=_inc_vbuz1
inc.z idx_6
// [23] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [16] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
b1_from_b2:
// [16] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
// [16] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
jmp b1
}
// File Data
DIGIT: .text "0123456789"
.byte 0
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] (byte) main::jesper_id#0 ← (byte) 4 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] (byte[$10]) main::jesper_name#0 ← (const string) main::$4 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] (byte) main::henriette_id#0 ← (byte) 7 [ idx#16 ] ( main:2 [ idx#16 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:4 [ idx#13 idx#16 ]
Statement [8] (byte[$10]) main::henriette_name#0 ← (const string) main::$5 [ idx#16 ] ( main:2 [ idx#16 ] ) always clobbers reg byte a
Statement [12] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) [ print_person::person#2 idx#13 ] ( main:2::print_person:6 [ print_person::person#2 idx#13 ] main:2::print_person:9 [ print_person::person#2 idx#13 ] ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:4 [ idx#13 idx#16 ]
Statement [14] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' [ print_person::person#2 idx#4 ] ( main:2::print_person:6 [ print_person::person#2 idx#4 ] main:2::print_person:9 [ print_person::person#2 idx#4 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:13 [ idx#4 ]
Statement [17] if((byte) 0!=*(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 [ print_person::person#2 print_person::i#2 idx#14 ] ( main:2::print_person:6 [ print_person::person#2 print_person::i#2 idx#14 ] main:2::print_person:9 [ print_person::person#2 print_person::i#2 idx#14 ] ) always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ]
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ]
Statement [18] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' [ idx#14 ] ( main:2::print_person:6 [ idx#14 ] main:2::print_person:9 [ idx#14 ] ) always clobbers reg byte a
Statement [21] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) [ print_person::person#2 print_person::i#2 idx#14 ] ( main:2::print_person:6 [ print_person::person#2 print_person::i#2 idx#14 ] main:2::print_person:9 [ print_person::person#2 print_person::i#2 idx#14 ] ) always clobbers reg byte a reg byte y
Statement [4] (byte) main::jesper_id#0 ← (byte) 4 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [5] (byte[$10]) main::jesper_name#0 ← (const string) main::$4 [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [7] (byte) main::henriette_id#0 ← (byte) 7 [ idx#16 ] ( main:2 [ idx#16 ] ) always clobbers reg byte a
Statement [8] (byte[$10]) main::henriette_name#0 ← (const string) main::$5 [ idx#16 ] ( main:2 [ idx#16 ] ) always clobbers reg byte a
Statement [12] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) [ print_person::person#2 idx#13 ] ( main:2::print_person:6 [ print_person::person#2 idx#13 ] main:2::print_person:9 [ print_person::person#2 idx#13 ] ) always clobbers reg byte a reg byte y
Statement [14] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' [ print_person::person#2 idx#4 ] ( main:2::print_person:6 [ print_person::person#2 idx#4 ] main:2::print_person:9 [ print_person::person#2 idx#4 ] ) always clobbers reg byte a
Statement [17] if((byte) 0!=*(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 [ print_person::person#2 print_person::i#2 idx#14 ] ( main:2::print_person:6 [ print_person::person#2 print_person::i#2 idx#14 ] main:2::print_person:9 [ print_person::person#2 print_person::i#2 idx#14 ] ) always clobbers reg byte a reg byte y
Statement [18] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' [ idx#14 ] ( main:2::print_person:6 [ idx#14 ] main:2::print_person:9 [ idx#14 ] ) always clobbers reg byte a
Statement [21] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) [ print_person::person#2 print_person::i#2 idx#14 ] ( main:2::print_person:6 [ print_person::person#2 print_person::i#2 idx#14 ] main:2::print_person:9 [ print_person::person#2 print_person::i#2 idx#14 ] ) always clobbers reg byte a reg byte y
Potential registers zp ZP_WORD:2 [ print_person::person#2 ] : zp ZP_WORD:2 ,
Potential registers zp ZP_BYTE:4 [ idx#13 idx#16 ] : zp ZP_BYTE:4 , reg byte x ,
Potential registers zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ] : zp ZP_BYTE:5 , reg byte x ,
Potential registers zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ] : zp ZP_BYTE:6 , reg byte x ,
Potential registers zp ZP_BYTE:7 [ main::jesper_id#0 ] : zp ZP_BYTE:7 ,
Potential registers zp ZP_WORD:8 [ main::jesper_name#0 ] : zp ZP_WORD:8 ,
Potential registers zp ZP_BYTE:10 [ main::henriette_id#0 ] : zp ZP_BYTE:10 ,
Potential registers zp ZP_WORD:11 [ main::henriette_name#0 ] : zp ZP_WORD:11 ,
Potential registers zp ZP_BYTE:13 [ idx#4 ] : zp ZP_BYTE:13 , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 20: zp ZP_BYTE:7 [ main::jesper_id#0 ] 20: zp ZP_WORD:8 [ main::jesper_name#0 ] 20: zp ZP_BYTE:10 [ main::henriette_id#0 ] 20: zp ZP_WORD:11 [ main::henriette_name#0 ]
Uplift Scope [print_person] 33: zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ] 0: zp ZP_WORD:2 [ print_person::person#2 ]
Uplift Scope [] 24.75: zp ZP_BYTE:6 [ idx#14 idx#5 idx#6 ] 3.8: zp ZP_BYTE:4 [ idx#13 idx#16 ] 3: zp ZP_BYTE:13 [ idx#4 ]
Uplift Scope [Person]
Uplifting [main] best 1121 combination zp ZP_BYTE:7 [ main::jesper_id#0 ] zp ZP_WORD:8 [ main::jesper_name#0 ] zp ZP_BYTE:10 [ main::henriette_id#0 ] zp ZP_WORD:11 [ main::henriette_name#0 ]
Uplifting [print_person] best 1121 combination zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ] zp ZP_WORD:2 [ print_person::person#2 ]
Uplifting [] best 1031 combination reg byte x [ idx#14 idx#5 idx#6 ] reg byte x [ idx#13 idx#16 ] reg byte x [ idx#4 ]
Uplifting [Person] best 1031 combination
Attempting to uplift remaining variables inzp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
Uplifting [print_person] best 1031 combination zp ZP_BYTE:5 [ print_person::i#2 print_person::i#1 ]
Attempting to uplift remaining variables inzp ZP_BYTE:7 [ main::jesper_id#0 ]
Uplifting [main] best 1031 combination zp ZP_BYTE:7 [ main::jesper_id#0 ]
Attempting to uplift remaining variables inzp ZP_BYTE:10 [ main::henriette_id#0 ]
Uplifting [main] best 1031 combination zp ZP_BYTE:10 [ main::henriette_id#0 ]
Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:4 [ print_person::i#2 print_person::i#1 ]
Allocated (was zp ZP_BYTE:7) zp ZP_BYTE:5 [ main::jesper_id#0 ]
Allocated (was zp ZP_WORD:8) zp ZP_WORD:6 [ main::jesper_name#0 ]
Allocated (was zp ZP_BYTE:10) zp ZP_BYTE:8 [ main::henriette_id#0 ]
Allocated (was zp ZP_WORD:11) zp ZP_WORD:9 [ main::henriette_name#0 ]
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Example of a struct containing an array
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
// https://gitlab.com/camelot/kickc/issues/312
// Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_PERSON_NAME = 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
jsr main
// [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
// @end
bend:
// main
main: {
.label jesper_id = 5
.label jesper_name = 6
.label henriette_id = 8
.label henriette_name = 9
// [4] (byte) main::jesper_id#0 ← (byte) 4 -- vbuz1=vbuc1
lda #4
sta.z jesper_id
// [5] (byte[$10]) main::jesper_name#0 ← (const string) main::$4 -- pbuz1=pbuc1
lda #<_4
sta.z jesper_name
lda #>_4
sta.z jesper_name+1
// [6] call print_person
// [11] phi from main to print_person [phi:main->print_person]
print_person_from_main:
// [11] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#0] -- vbuxx=vbuc1
ldx #0
// [11] phi (struct Person*) print_person::person#2 = (struct Person*)&(byte) main::jesper_id#0 [phi:main->print_person#1] -- pssz1=pssc1
lda #<jesper_id
sta.z print_person.person
lda #>jesper_id
sta.z print_person.person+1
jsr print_person
jmp b1
// main::@1
b1:
// [7] (byte) main::henriette_id#0 ← (byte) 7 -- vbuz1=vbuc1
lda #7
sta.z henriette_id
// [8] (byte[$10]) main::henriette_name#0 ← (const string) main::$5 -- pbuz1=pbuc1
lda #<_5
sta.z henriette_name
lda #>_5
sta.z henriette_name+1
// [9] call print_person
// [11] phi from main::@1 to print_person [phi:main::@1->print_person]
print_person_from_b1:
// [11] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#0] -- register_copy
// [11] phi (struct Person*) print_person::person#2 = (struct Person*)&(byte) main::henriette_id#0 [phi:main::@1->print_person#1] -- pssz1=pssc1
lda #<henriette_id
sta.z print_person.person
lda #>henriette_id
sta.z print_person.person+1
jsr print_person
jmp breturn
// main::@return
breturn:
// [10] return
rts
_4: .text "jesper"
.byte 0
_5: .text "henriette"
.byte 0
}
// print_person
// print_person(struct Person* zeropage(2) person)
print_person: {
.label i = 4
.label person = 2
// [12] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_(_deref_pbuz1)
ldy #0
lda (person),y
tay
lda DIGIT,y
sta SCREEN,x
// [13] (byte) idx#4 ← ++ (byte) idx#13 -- vbuxx=_inc_vbuxx
inx
// [14] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
lda #' '
sta SCREEN,x
// [15] (byte) idx#5 ← ++ (byte) idx#4 -- vbuxx=_inc_vbuxx
inx
// [16] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
b1_from_print_person:
// [16] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
// [16] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuz1=vbuc1
lda #0
sta.z i
jmp b1
// print_person::@1
b1:
// [17] if((byte) 0!=*(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_(pptz1_derefidx_vbuc2)_derefidx_vbuz2_then_la1
ldy #OFFSET_STRUCT_PERSON_NAME
lda (person),y
sta.z $fe
iny
lda (person),y
sta.z $ff
ldy.z i
lda ($fe),y
cmp #0
bne b2
jmp b3
// print_person::@3
b3:
// [18] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
lda #' '
sta SCREEN,x
// [19] (byte) idx#16 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
inx
jmp breturn
// print_person::@return
breturn:
// [20] return
rts
// print_person::@2
b2:
// [21] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) -- pbuc1_derefidx_vbuxx=(pptz1_derefidx_vbuc2)_derefidx_vbuz2
ldy #OFFSET_STRUCT_PERSON_NAME
lda (person),y
sta.z $fe
iny
lda (person),y
sta.z $ff
ldy.z i
lda ($fe),y
sta SCREEN,x
// [22] (byte) idx#6 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
inx
// [23] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [16] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
b1_from_b2:
// [16] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
// [16] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
jmp b1
}
// File Data
DIGIT: .text "0123456789"
.byte 0
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Removing instruction jmp b1
Removing instruction jmp b3
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction print_person_from_main:
Removing instruction b1:
Removing instruction print_person_from_b1:
Removing instruction breturn:
Removing instruction b1_from_print_person:
Removing instruction b3:
Removing instruction breturn:
Removing instruction b1_from_b2:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(byte[]) DIGIT
(const byte[]) DIGIT#0 DIGIT = (string) "0123456789"
(const byte) OFFSET_STRUCT_PERSON_NAME OFFSET_STRUCT_PERSON_NAME = (byte) 1
(byte) Person::id
(byte[$10]) Person::name
(byte*) SCREEN
(const byte*) SCREEN#0 SCREEN = (byte*) 1024
(byte) idx
(byte) idx#13 reg byte x 3.0
(byte) idx#14 reg byte x 9.75
(byte) idx#16 reg byte x 0.8
(byte) idx#4 reg byte x 3.0
(byte) idx#5 reg byte x 4.0
(byte) idx#6 reg byte x 11.0
(void()) main()
(const string) main::$4 $4 = (string) "jesper"
(const string) main::$5 $5 = (string) "henriette"
(label) main::@1
(label) main::@return
(struct Person) main::henriette
(byte) main::henriette_id
(byte) main::henriette_id#0 henriette_id zp ZP_BYTE:8 20.0
(byte[$10]) main::henriette_name
(byte[$10]) main::henriette_name#0 henriette_name zp ZP_WORD:9 20.0
(struct Person) main::jesper
(byte) main::jesper_id
(byte) main::jesper_id#0 jesper_id zp ZP_BYTE:5 20.0
(byte[$10]) main::jesper_name
(byte[$10]) main::jesper_name#0 jesper_name zp ZP_WORD:6 20.0
(void()) print_person((struct Person*) print_person::person)
(label) print_person::@1
(label) print_person::@2
(label) print_person::@3
(label) print_person::@return
(byte) print_person::i
(byte) print_person::i#1 i zp ZP_BYTE:4 22.0
(byte) print_person::i#2 i zp ZP_BYTE:4 11.0
(struct Person*) print_person::person
(struct Person*) print_person::person#2 person zp ZP_WORD:2
zp ZP_WORD:2 [ print_person::person#2 ]
reg byte x [ idx#13 idx#16 ]
zp ZP_BYTE:4 [ print_person::i#2 print_person::i#1 ]
reg byte x [ idx#14 idx#5 idx#6 ]
zp ZP_BYTE:5 [ main::jesper_id#0 ]
zp ZP_WORD:6 [ main::jesper_name#0 ]
zp ZP_BYTE:8 [ main::henriette_id#0 ]
zp ZP_WORD:9 [ main::henriette_name#0 ]
reg byte x [ idx#4 ]
FINAL ASSEMBLER
Score: 950
// File Comments
// Example of a struct containing an array
// It works on the surface - but illustrates the problem with structs containing arrays treating them like pointers.
// https://gitlab.com/camelot/kickc/issues/312
// Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// Global Constants & labels
.const OFFSET_STRUCT_PERSON_NAME = 1
.label SCREEN = $400
// @begin
// [1] phi from @begin to @1 [phi:@begin->@1]
// @1
// [2] call main
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label jesper_id = 5
.label jesper_name = 6
.label henriette_id = 8
.label henriette_name = 9
// jesper = { 4, "jesper" }
// [4] (byte) main::jesper_id#0 ← (byte) 4 -- vbuz1=vbuc1
lda #4
sta.z jesper_id
// [5] (byte[$10]) main::jesper_name#0 ← (const string) main::$4 -- pbuz1=pbuc1
lda #<_4
sta.z jesper_name
lda #>_4
sta.z jesper_name+1
// print_person(&jesper)
// [6] call print_person
// [11] phi from main to print_person [phi:main->print_person]
// [11] phi (byte) idx#13 = (byte) 0 [phi:main->print_person#0] -- vbuxx=vbuc1
ldx #0
// [11] phi (struct Person*) print_person::person#2 = (struct Person*)&(byte) main::jesper_id#0 [phi:main->print_person#1] -- pssz1=pssc1
lda #<jesper_id
sta.z print_person.person
lda #>jesper_id
sta.z print_person.person+1
jsr print_person
// main::@1
// henriette = { 7, "henriette" }
// [7] (byte) main::henriette_id#0 ← (byte) 7 -- vbuz1=vbuc1
lda #7
sta.z henriette_id
// [8] (byte[$10]) main::henriette_name#0 ← (const string) main::$5 -- pbuz1=pbuc1
lda #<_5
sta.z henriette_name
lda #>_5
sta.z henriette_name+1
// print_person(&henriette)
// [9] call print_person
// [11] phi from main::@1 to print_person [phi:main::@1->print_person]
// [11] phi (byte) idx#13 = (byte) idx#16 [phi:main::@1->print_person#0] -- register_copy
// [11] phi (struct Person*) print_person::person#2 = (struct Person*)&(byte) main::henriette_id#0 [phi:main::@1->print_person#1] -- pssz1=pssc1
lda #<henriette_id
sta.z print_person.person
lda #>henriette_id
sta.z print_person.person+1
jsr print_person
// main::@return
// }
// [10] return
rts
_4: .text "jesper"
.byte 0
_5: .text "henriette"
.byte 0
}
// print_person
// print_person(struct Person* zeropage(2) person)
print_person: {
.label i = 4
.label person = 2
// SCREEN[idx++] = DIGIT[person->id]
// [12] *((const byte*) SCREEN#0 + (byte) idx#13) ← *((const byte[]) DIGIT#0 + *((byte*)(struct Person*) print_person::person#2)) -- pbuc1_derefidx_vbuxx=pbuc2_derefidx_(_deref_pbuz1)
ldy #0
lda (person),y
tay
lda DIGIT,y
sta SCREEN,x
// SCREEN[idx++] = DIGIT[person->id];
// [13] (byte) idx#4 ← ++ (byte) idx#13 -- vbuxx=_inc_vbuxx
inx
// SCREEN[idx++] = ' '
// [14] *((const byte*) SCREEN#0 + (byte) idx#4) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
lda #' '
sta SCREEN,x
// SCREEN[idx++] = ' ';
// [15] (byte) idx#5 ← ++ (byte) idx#4 -- vbuxx=_inc_vbuxx
inx
// [16] phi from print_person to print_person::@1 [phi:print_person->print_person::@1]
// [16] phi (byte) idx#14 = (byte) idx#5 [phi:print_person->print_person::@1#0] -- register_copy
// [16] phi (byte) print_person::i#2 = (byte) 0 [phi:print_person->print_person::@1#1] -- vbuz1=vbuc1
lda #0
sta.z i
// print_person::@1
b1:
// for(byte i=0; person->name[i]; i++)
// [17] if((byte) 0!=*(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2)) goto print_person::@2 -- vbuc1_neq_(pptz1_derefidx_vbuc2)_derefidx_vbuz2_then_la1
ldy #OFFSET_STRUCT_PERSON_NAME
lda (person),y
sta.z $fe
iny
lda (person),y
sta.z $ff
ldy.z i
lda ($fe),y
cmp #0
bne b2
// print_person::@3
// SCREEN[idx++] = ' '
// [18] *((const byte*) SCREEN#0 + (byte) idx#14) ← (byte) ' ' -- pbuc1_derefidx_vbuxx=vbuc2
lda #' '
sta SCREEN,x
// SCREEN[idx++] = ' ';
// [19] (byte) idx#16 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
inx
// print_person::@return
// }
// [20] return
rts
// print_person::@2
b2:
// SCREEN[idx++] = person->name[i]
// [21] *((const byte*) SCREEN#0 + (byte) idx#14) ← *(*((byte[$10]*)(struct Person*) print_person::person#2 + (const byte) OFFSET_STRUCT_PERSON_NAME) + (byte) print_person::i#2) -- pbuc1_derefidx_vbuxx=(pptz1_derefidx_vbuc2)_derefidx_vbuz2
ldy #OFFSET_STRUCT_PERSON_NAME
lda (person),y
sta.z $fe
iny
lda (person),y
sta.z $ff
ldy.z i
lda ($fe),y
sta SCREEN,x
// SCREEN[idx++] = person->name[i];
// [22] (byte) idx#6 ← ++ (byte) idx#14 -- vbuxx=_inc_vbuxx
inx
// for(byte i=0; person->name[i]; i++)
// [23] (byte) print_person::i#1 ← ++ (byte) print_person::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [16] phi from print_person::@2 to print_person::@1 [phi:print_person::@2->print_person::@1]
// [16] phi (byte) idx#14 = (byte) idx#6 [phi:print_person::@2->print_person::@1#0] -- register_copy
// [16] phi (byte) print_person::i#2 = (byte) print_person::i#1 [phi:print_person::@2->print_person::@1#1] -- register_copy
jmp b1
}
// File Data
DIGIT: .text "0123456789"
.byte 0