CONTROL FLOW GRAPH SSA void main() main: scope:[main] from __start main::screen#0 = (char *)$400 main::txt#0 = Text main::i#0 = 0 to:main::@1 main::@1: scope:[main] from main main::@5 main::screen#7 = phi( main/main::screen#0, main::@5/main::screen#2 ) main::txt#4 = phi( main/main::txt#0, main::@5/main::txt#1 ) main::i#2 = phi( main/main::i#0, main::@5/main::i#1 ) main::$0 = sizeof Text main::$1 = main::$0 / SIZEOF_STRUCT_$0 main::$2 = main::i#2 < main::$1 if(main::$2) goto main::@2 to:main::@return main::@2: scope:[main] from main::@1 main::i#5 = phi( main::@1/main::i#2 ) main::screen#6 = phi( main::@1/main::screen#7 ) main::txt#2 = phi( main::@1/main::txt#4 ) main::$4 = (char **)main::txt#2 main::$3 = main::$4 + OFFSET_STRUCT_$0_MSG main::msg#0 = *main::$3 to:main::@3 main::@3: scope:[main] from main::@2 main::@4 main::txt#5 = phi( main::@2/main::txt#2, main::@4/main::txt#6 ) main::i#4 = phi( main::@2/main::i#5, main::@4/main::i#6 ) main::screen#5 = phi( main::@2/main::screen#6, main::@4/main::screen#1 ) main::msg#2 = phi( main::@2/main::msg#0, main::@4/main::msg#1 ) main::$5 = 0 != *main::msg#2 if(main::$5) goto main::@4 to:main::@5 main::@4: scope:[main] from main::@3 main::txt#6 = phi( main::@3/main::txt#5 ) main::i#6 = phi( main::@3/main::i#4 ) main::screen#3 = phi( main::@3/main::screen#5 ) main::msg#3 = phi( main::@3/main::msg#2 ) *main::screen#3 = *main::msg#3 main::screen#1 = ++ main::screen#3 main::msg#1 = ++ main::msg#3 to:main::@3 main::@5: scope:[main] from main::@3 main::txt#3 = phi( main::@3/main::txt#5 ) main::i#3 = phi( main::@3/main::i#4 ) main::screen#4 = phi( main::@3/main::screen#5 ) *main::screen#4 = ' ' main::screen#2 = ++ main::screen#4 main::i#1 = ++ main::i#3 main::txt#1 = main::txt#3 + SIZEOF_STRUCT_$0 to:main::@1 main::@return: scope:[main] from main::@1 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 __constant char $0_msg[$18] = "Wolfgang Amadeus Mozart" __constant char $0_msg1[$19] = ""Eine kleine Nachtmusik"" __constant char $0_msg10[$16] = "Ullrich von Bassewitz" __constant char $0_msg11[$19] = "Press any key to quit..." __constant char $0_msg2[9] = "(KV 525)" __constant char $0_msg3[$1d] = "Ported to the SID in 1987 by" __constant char $0_msg4[$16] = "Joachim von Bassewitz" __constant char $0_msg5[$1b] = "(joachim@von-bassewitz.de)" __constant char $0_msg6[4] = "and" __constant char $0_msg7[$16] = "Ullrich von Bassewitz" __constant char $0_msg8[$1b] = "(ullrich@von-bassewitz.de)" __constant char $0_msg9[$14] = "C Implementation by" __constant char OFFSET_STRUCT_$0_MSG = 1 __constant char SIZEOF_STRUCT_$0 = 3 __constant struct $0 Text[] = { { Y: 2, Msg: $0_msg }, { Y: 4, Msg: $0_msg1 }, { Y: 5, Msg: $0_msg2 }, { Y: 9, Msg: $0_msg3 }, { Y: $b, Msg: $0_msg4 }, { Y: $c, Msg: $0_msg5 }, { Y: $d, Msg: $0_msg6 }, { Y: $e, Msg: $0_msg7 }, { Y: $f, Msg: $0_msg8 }, { Y: $12, Msg: $0_msg9 }, { Y: $13, Msg: $0_msg10 }, { Y: $17, Msg: $0_msg11 } } void __start() void main() unsigned int main::$0 unsigned int main::$1 bool main::$2 char **main::$3 char **main::$4 bool main::$5 char main::i char main::i#0 char main::i#1 char main::i#2 char main::i#3 char main::i#4 char main::i#5 char main::i#6 char *main::msg char *main::msg#0 char *main::msg#1 char *main::msg#2 char *main::msg#3 char *main::screen char *main::screen#0 char *main::screen#1 char *main::screen#2 char *main::screen#3 char *main::screen#4 char *main::screen#5 char *main::screen#6 char *main::screen#7 struct $0 *main::txt struct $0 *main::txt#0 struct $0 *main::txt#1 struct $0 *main::txt#2 struct $0 *main::txt#3 struct $0 *main::txt#4 struct $0 *main::txt#5 struct $0 *main::txt#6 Adding number conversion cast (unumber) 0 in main::$5 = 0 != *main::msg#2 Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (char *) 1024 Simplifying constant integer cast 0 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (char) 0 Successful SSA optimization PassNFinalizeNumberTypeConversions Alias main::txt#2 = main::txt#4 Alias main::screen#6 = main::screen#7 Alias main::i#2 = main::i#5 Alias main::msg#2 = main::msg#3 Alias main::screen#3 = main::screen#5 main::screen#4 Alias main::i#3 = main::i#6 main::i#4 Alias main::txt#3 = main::txt#6 main::txt#5 Successful SSA optimization Pass2AliasElimination Identical Phi Values main::i#3 main::i#2 Identical Phi Values main::txt#3 main::txt#2 Successful SSA optimization Pass2IdenticalPhiElimination Simple Condition main::$2 [7] if(main::i#2main::@1] __b1_from_main: // [1] phi main::screen#6 = (char *) 1024 [phi:main->main::@1#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 // [1] phi main::txt#2 = Text [phi:main->main::@1#1] -- pssz1=pssc1 lda #Text sta.z txt+1 // [1] phi main::i#2 = 0 [phi:main->main::@1#2] -- vbuxx=vbuc1 ldx #0 jmp __b1 // main::@1 __b1: // [2] if(main::i#2<$c*3/3) goto main::@2 -- vbuxx_lt_vbuc1_then_la1 cpx #$c*3/3 bcc __b2 jmp __breturn // main::@return __breturn: // [3] return rts // main::@2 __b2: // [4] main::msg#0 = ((char **)main::txt#2)[1] -- pbuz1=qbuz2_derefidx_vbuc1 ldy #1 lda (txt),y sta.z msg iny lda (txt),y sta.z msg+1 // [5] phi from main::@2 main::@4 to main::@3 [phi:main::@2/main::@4->main::@3] __b3_from___b2: __b3_from___b4: // [5] phi main::screen#3 = main::screen#6 [phi:main::@2/main::@4->main::@3#0] -- register_copy // [5] phi main::msg#2 = main::msg#0 [phi:main::@2/main::@4->main::@3#1] -- register_copy jmp __b3 // main::@3 __b3: // [6] if(0!=*main::msg#2) goto main::@4 -- 0_neq__deref_pbuz1_then_la1 ldy #0 lda (msg),y cmp #0 bne __b4 jmp __b5 // main::@5 __b5: // [7] *main::screen#3 = ' ' -- _deref_pbuz1=vbuc1 lda #' ' ldy #0 sta (screen),y // [8] main::screen#2 = ++ main::screen#3 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: // [9] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx inx // [10] main::txt#1 = main::txt#2 + 3 -- pssz1=pssz1_plus_vbuc1 lda #3 clc adc.z txt sta.z txt bcc !+ inc.z txt+1 !: // [1] phi from main::@5 to main::@1 [phi:main::@5->main::@1] __b1_from___b5: // [1] phi main::screen#6 = main::screen#2 [phi:main::@5->main::@1#0] -- register_copy // [1] phi main::txt#2 = main::txt#1 [phi:main::@5->main::@1#1] -- register_copy // [1] phi main::i#2 = main::i#1 [phi:main::@5->main::@1#2] -- register_copy jmp __b1 // main::@4 __b4: // [11] *main::screen#3 = *main::msg#2 -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (msg),y ldy #0 sta (screen),y // [12] main::screen#1 = ++ main::screen#3 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: // [13] main::msg#1 = ++ main::msg#2 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: jmp __b3_from___b4 } // File Data .segment Data Text: .byte 2 .word __0_msg .byte 4 .word __0_msg1 .byte 5 .word __0_msg2 .byte 9 .word __0_msg3 .byte $b .word __0_msg4 .byte $c .word __0_msg5 .byte $d .word __0_msg6 .byte $e .word __0_msg10 .byte $f .word __0_msg8 .byte $12 .word __0_msg9 .byte $13 .word __0_msg10 .byte $17 .word __0_msg11 __0_msg: .text "Wolfgang Amadeus Mozart" .byte 0 __0_msg1: .text @"\"Eine kleine Nachtmusik\"" .byte 0 __0_msg2: .text "(KV 525)" .byte 0 __0_msg3: .text "Ported to the SID in 1987 by" .byte 0 __0_msg4: .text "Joachim von Bassewitz" .byte 0 __0_msg5: .text "(joachim@von-bassewitz.de)" .byte 0 __0_msg6: .text "and" .byte 0 __0_msg8: .text "(ullrich@von-bassewitz.de)" .byte 0 __0_msg9: .text "C Implementation by" .byte 0 __0_msg10: .text "Ullrich von Bassewitz" .byte 0 __0_msg11: .text "Press any key to quit..." .byte 0 ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __b3 Removing instruction jmp __b5 Succesful ASM optimization Pass5NextJumpElimination Removing instruction ldy #0 Succesful ASM optimization Pass5UnnecesaryLoadElimination Replacing label __b3_from___b4 with __b3 Removing instruction __b3_from___b2: Removing instruction __b3_from___b4: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction __b1_from_main: Removing instruction __breturn: Removing instruction __b5: Removing instruction __b1_from___b5: Succesful ASM optimization Pass5UnusedLabelElimination Removing instruction ldy #0 Succesful ASM optimization Pass5UnnecesaryLoadElimination FINAL SYMBOL TABLE __constant char $0_msg[$18] = "Wolfgang Amadeus Mozart" __constant char $0_msg1[$19] = ""Eine kleine Nachtmusik"" __constant char $0_msg10[$16] = "Ullrich von Bassewitz" __constant char $0_msg11[$19] = "Press any key to quit..." __constant char $0_msg2[9] = "(KV 525)" __constant char $0_msg3[$1d] = "Ported to the SID in 1987 by" __constant char $0_msg4[$16] = "Joachim von Bassewitz" __constant char $0_msg5[$1b] = "(joachim@von-bassewitz.de)" __constant char $0_msg6[4] = "and" __constant char $0_msg8[$1b] = "(ullrich@von-bassewitz.de)" __constant char $0_msg9[$14] = "C Implementation by" __constant struct $0 Text[] = { { Y: 2, Msg: $0_msg }, { Y: 4, Msg: $0_msg1 }, { Y: 5, Msg: $0_msg2 }, { Y: 9, Msg: $0_msg3 }, { Y: $b, Msg: $0_msg4 }, { Y: $c, Msg: $0_msg5 }, { Y: $d, Msg: $0_msg6 }, { Y: $e, Msg: $0_msg10 }, { Y: $f, Msg: $0_msg8 }, { Y: $12, Msg: $0_msg9 }, { Y: $13, Msg: $0_msg10 }, { Y: $17, Msg: $0_msg11 } } void main() char main::i char main::i#1 // reg byte x 11.0 char main::i#2 // reg byte x 3.3000000000000003 char *main::msg char *main::msg#0 // msg zp[2]:4 22.0 char *main::msg#1 // msg zp[2]:4 202.0 char *main::msg#2 // msg zp[2]:4 103.75 char *main::screen char *main::screen#1 // screen zp[2]:6 101.0 char *main::screen#2 // screen zp[2]:6 7.333333333333333 char *main::screen#3 // screen zp[2]:6 84.0 char *main::screen#6 // screen zp[2]:6 7.333333333333333 struct $0 *main::txt struct $0 *main::txt#1 // txt zp[2]:2 22.0 struct $0 *main::txt#2 // txt zp[2]:2 2.0 reg byte x [ main::i#2 main::i#1 ] zp[2]:2 [ main::txt#2 main::txt#1 ] zp[2]:4 [ main::msg#2 main::msg#0 main::msg#1 ] zp[2]:6 [ main::screen#3 main::screen#6 main::screen#2 main::screen#1 ] FINAL ASSEMBLER Score: 6261 // File Comments // Structs with char* pointer members // https://gitlab.com/camelot/kickc/-/issues/397 // Upstart // Commodore 64 PRG executable file .file [name="struct-49.prg", type="prg", segments="Program"] .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$80d] .segmentdef Data [startAfter="Code"] .segment Basic :BasicUpstart(main) // Global Constants & labels .segment Code // main main: { .label msg = 4 .label screen = 6 .label txt = 2 // [1] phi from main to main::@1 [phi:main->main::@1] // [1] phi main::screen#6 = (char *) 1024 [phi:main->main::@1#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 // [1] phi main::txt#2 = Text [phi:main->main::@1#1] -- pssz1=pssc1 lda #Text sta.z txt+1 // [1] phi main::i#2 = 0 [phi:main->main::@1#2] -- vbuxx=vbuc1 ldx #0 // main::@1 __b1: // for(char i=0;iMsg // [4] main::msg#0 = ((char **)main::txt#2)[1] -- pbuz1=qbuz2_derefidx_vbuc1 ldy #1 lda (txt),y sta.z msg iny lda (txt),y sta.z msg+1 // [5] phi from main::@2 main::@4 to main::@3 [phi:main::@2/main::@4->main::@3] // [5] phi main::screen#3 = main::screen#6 [phi:main::@2/main::@4->main::@3#0] -- register_copy // [5] phi main::msg#2 = main::msg#0 [phi:main::@2/main::@4->main::@3#1] -- register_copy // main::@3 __b3: // for(char* msg = txt->Msg; *msg; msg++) // [6] if(0!=*main::msg#2) goto main::@4 -- 0_neq__deref_pbuz1_then_la1 ldy #0 lda (msg),y cmp #0 bne __b4 // main::@5 // *(screen++) = ' ' // [7] *main::screen#3 = ' ' -- _deref_pbuz1=vbuc1 lda #' ' sta (screen),y // *(screen++) = ' '; // [8] main::screen#2 = ++ main::screen#3 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: // for(char i=0;imain::@1] // [1] phi main::screen#6 = main::screen#2 [phi:main::@5->main::@1#0] -- register_copy // [1] phi main::txt#2 = main::txt#1 [phi:main::@5->main::@1#1] -- register_copy // [1] phi main::i#2 = main::i#1 [phi:main::@5->main::@1#2] -- register_copy jmp __b1 // main::@4 __b4: // *(screen++) = *msg // [11] *main::screen#3 = *main::msg#2 -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (msg),y sta (screen),y // *(screen++) = *msg; // [12] main::screen#1 = ++ main::screen#3 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: // for(char* msg = txt->Msg; *msg; msg++) // [13] main::msg#1 = ++ main::msg#2 -- pbuz1=_inc_pbuz1 inc.z msg bne !+ inc.z msg+1 !: jmp __b3 } // File Data .segment Data Text: .byte 2 .word __0_msg .byte 4 .word __0_msg1 .byte 5 .word __0_msg2 .byte 9 .word __0_msg3 .byte $b .word __0_msg4 .byte $c .word __0_msg5 .byte $d .word __0_msg6 .byte $e .word __0_msg10 .byte $f .word __0_msg8 .byte $12 .word __0_msg9 .byte $13 .word __0_msg10 .byte $17 .word __0_msg11 __0_msg: .text "Wolfgang Amadeus Mozart" .byte 0 __0_msg1: .text @"\"Eine kleine Nachtmusik\"" .byte 0 __0_msg2: .text "(KV 525)" .byte 0 __0_msg3: .text "Ported to the SID in 1987 by" .byte 0 __0_msg4: .text "Joachim von Bassewitz" .byte 0 __0_msg5: .text "(joachim@von-bassewitz.de)" .byte 0 __0_msg6: .text "and" .byte 0 __0_msg8: .text "(ullrich@von-bassewitz.de)" .byte 0 __0_msg9: .text "C Implementation by" .byte 0 __0_msg10: .text "Ullrich von Bassewitz" .byte 0 __0_msg11: .text "Press any key to quit..." .byte 0