From 899058ce42249e1ad6d381a269cca0347c56bc2f Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Wed, 4 Sep 2019 23:09:27 +0200 Subject: [PATCH] Added fragment for Paul Nelsen. --- .../vwuz1=(_deref_pptc1)_derefidx_vbuyy.asm | 9 + .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/struct-ptr-26.kc | 18 + src/test/ref/struct-ptr-26.asm | 69 ++ src/test/ref/struct-ptr-26.cfg | 53 + src/test/ref/struct-ptr-26.log | 1057 +++++++++++++++++ src/test/ref/struct-ptr-26.sym | 52 + 7 files changed, 1263 insertions(+) create mode 100644 src/main/fragment/vwuz1=(_deref_pptc1)_derefidx_vbuyy.asm create mode 100644 src/test/kc/struct-ptr-26.kc create mode 100644 src/test/ref/struct-ptr-26.asm create mode 100644 src/test/ref/struct-ptr-26.cfg create mode 100644 src/test/ref/struct-ptr-26.log create mode 100644 src/test/ref/struct-ptr-26.sym diff --git a/src/main/fragment/vwuz1=(_deref_pptc1)_derefidx_vbuyy.asm b/src/main/fragment/vwuz1=(_deref_pptc1)_derefidx_vbuyy.asm new file mode 100644 index 000000000..48b1355e4 --- /dev/null +++ b/src/main/fragment/vwuz1=(_deref_pptc1)_derefidx_vbuyy.asm @@ -0,0 +1,9 @@ +ldx {c1} +stx $fe +ldx {c1}+1 +stx $ff +lda ($fe),y +sta {z1} +iny +lda ($fe),y +sta {z1}+1 diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 66bc634fb..499fd59e3 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -638,6 +638,11 @@ public class TestPrograms { } */ + @Test + public void testStructPtr26() throws IOException, URISyntaxException { + compileAndCompare("struct-ptr-26"); + } + @Test public void testStructPtr25() throws IOException, URISyntaxException { compileAndCompare("struct-ptr-25"); diff --git a/src/test/kc/struct-ptr-26.kc b/src/test/kc/struct-ptr-26.kc new file mode 100644 index 000000000..d9aa8c5b4 --- /dev/null +++ b/src/test/kc/struct-ptr-26.kc @@ -0,0 +1,18 @@ +import "print" +typedef unsigned char BYTE; +typedef unsigned short WORD; +struct fileentry { + BYTE *bufEdit; + BYTE bFlag; + BYTE bError; +}; +typedef struct fileentry ENTRY; +void main(){ + ENTRY *file; + WORD uSize; + file = 0x4000; + file->bufEdit = 4; + word* ptrw = (WORD *)(file->bufEdit + 30); + uSize = *ptrw; + print_word(uSize); +} \ No newline at end of file diff --git a/src/test/ref/struct-ptr-26.asm b/src/test/ref/struct-ptr-26.asm new file mode 100644 index 000000000..f7ce23bae --- /dev/null +++ b/src/test/ref/struct-ptr-26.asm @@ -0,0 +1,69 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label print_char_cursor = 2 +main: { + .label file = $4000 + .label uSize = 4 + lda #<4 + sta file + lda #>4 + sta file+1 + ldy #$1e + ldx file + stx.z $fe + tax + stx.z $ff + lda ($fe),y + sta.z uSize + iny + lda ($fe),y + sta.z uSize+1 + jsr print_word + rts +} +// Print a word as HEX +// print_word(word zeropage(4) w) +print_word: { + .label w = 4 + lda.z w+1 + tax + lda #<$400 + sta.z print_char_cursor + lda #>$400 + sta.z print_char_cursor+1 + jsr print_byte + lda.z w + tax + jsr print_byte + rts +} +// Print a byte as HEX +// print_byte(byte register(X) b) +print_byte: { + txa + lsr + lsr + lsr + lsr + tay + lda print_hextab,y + jsr print_char + lda #$f + axs #0 + lda print_hextab,x + jsr print_char + rts +} +// Print a single char +// print_char(byte register(A) ch) +print_char: { + ldy #0 + sta (print_char_cursor),y + inc.z print_char_cursor + bne !+ + inc.z print_char_cursor+1 + !: + rts +} + print_hextab: .text "0123456789abcdef" diff --git a/src/test/ref/struct-ptr-26.cfg b/src/test/ref/struct-ptr-26.cfg new file mode 100644 index 000000000..2fc971fe4 --- /dev/null +++ b/src/test/ref/struct-ptr-26.cfg @@ -0,0 +1,53 @@ +@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**)(const struct fileentry*) main::file#1) ← (byte*) 4 + [5] (word) main::uSize#1 ← *((word*)*((byte**)(const struct fileentry*) main::file#1) + (byte) $1e) + [6] (word) print_word::w#0 ← (word) main::uSize#1 + [7] call print_word + to:main::@return +main::@return: scope:[main] from main + [8] return + to:@return +print_word: scope:[print_word] from main + [9] (byte) print_byte::b#0 ← > (word) print_word::w#0 + [10] call print_byte + to:print_word::@1 +print_word::@1: scope:[print_word] from print_word + [11] (byte) print_byte::b#1 ← < (word) print_word::w#0 + [12] call print_byte + to:print_word::@return +print_word::@return: scope:[print_word] from print_word::@1 + [13] return + to:@return +print_byte: scope:[print_byte] from print_word print_word::@1 + [14] (byte*) print_char_cursor#24 ← phi( print_word/(byte*) 1024 print_word::@1/(byte*) print_char_cursor#19 ) + [14] (byte) print_byte::b#2 ← phi( print_word/(byte) print_byte::b#0 print_word::@1/(byte) print_byte::b#1 ) + [15] (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte) 4 + [16] (byte) print_char::ch#0 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$0) + [17] call print_char + to:print_byte::@1 +print_byte::@1: scope:[print_byte] from print_byte + [18] (byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte) $f + [19] (byte) print_char::ch#1 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$2) + [20] call print_char + to:print_byte::@return +print_byte::@return: scope:[print_byte] from print_byte::@1 + [21] return + to:@return +print_char: scope:[print_char] from print_byte print_byte::@1 + [22] (byte*) print_char_cursor#18 ← phi( print_byte/(byte*) print_char_cursor#24 print_byte::@1/(byte*) print_char_cursor#19 ) + [22] (byte) print_char::ch#2 ← phi( print_byte/(byte) print_char::ch#0 print_byte::@1/(byte) print_char::ch#1 ) + [23] *((byte*) print_char_cursor#18) ← (byte) print_char::ch#2 + [24] (byte*) print_char_cursor#19 ← ++ (byte*) print_char_cursor#18 + to:print_char::@return +print_char::@return: scope:[print_char] from print_char + [25] return + to:@return diff --git a/src/test/ref/struct-ptr-26.log b/src/test/ref/struct-ptr-26.log new file mode 100644 index 000000000..a4b243158 --- /dev/null +++ b/src/test/ref/struct-ptr-26.log @@ -0,0 +1,1057 @@ +Fixing pointer addition (word*~) bsearch16u::$7 ← (word*) bsearch16u::items + (byte~) bsearch16u::$6 +Fixing pointer addition (word*~) bsearch16u::$15 ← (word*) bsearch16u::pivot + (number) 1 +Fixing pointer addition (word*~) bsearch16u::$1 ← (word*) bsearch16u::items - (number) 1 +Fixing pointer array-indexing *((word*) utoa::digit_values + (byte) utoa::digit) +Fixing pointer array-indexing *((dword*) ultoa::digit_values + (byte) ultoa::digit) +Rewriting struct pointer member access *((struct fileentry*) main::file).bufEdit +Rewriting struct pointer member access *((struct fileentry*) main::file).bufEdit +Warning! Adding boolean cast to non-boolean condition *((byte*) strcpy::src) +Warning! Adding boolean cast to non-boolean condition *((byte*) print_str_lines::str) +Warning! Adding boolean cast to non-boolean condition (byte) print_str_lines::ch +Warning! Adding boolean cast to non-boolean condition *((byte*) print_str::str) +Warning! Adding boolean cast to non-boolean condition *((byte*) print_str_at::str) +Warning! Adding boolean cast to non-boolean sub-expression (byte) print_str_lines::ch +Identified constant variable (byte*) HEAP_TOP +Culled Empty Block (label) @1 +Culled Empty Block (label) @2 +Culled Empty Block (label) @3 +Culled Empty Block (label) @4 +Culled Empty Block (label) @5 +Culled Empty Block (label) @6 +Culled Empty Block (label) @7 +Culled Empty Block (label) @8 +Culled Empty Block (label) @9 +Culled Empty Block (label) @10 +Culled Empty Block (label) @11 +Culled Empty Block (label) @13 +Culled Empty Block (label) @14 +Culled Empty Block (label) @15 +Culled Empty Block (label) @16 +Culled Empty Block (label) @17 +Culled Empty Block (label) @18 +Culled Empty Block (label) @19 +Culled Empty Block (label) @20 +Culled Empty Block (label) @21 +Culled Empty Block (label) @22 +Culled Empty Block (label) @23 +Culled Empty Block (label) @24 +Culled Empty Block (label) @25 +Culled Empty Block (label) @26 +Culled Empty Block (label) @27 +Culled Empty Block (label) @28 +Culled Empty Block (label) @30 +Culled Empty Block (label) @31 +Culled Empty Block (label) @32 +Culled Empty Block (label) @33 +Culled Empty Block (label) @34 +Culled Empty Block (label) @35 +Culled Empty Block (label) @36 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@12 +@12: scope:[] from @begin + (byte*) print_screen#0 ← ((byte*)) (number) $400 + (byte*) print_line_cursor#0 ← (byte*) print_screen#0 + (byte*) print_char_cursor#0 ← (byte*) print_line_cursor#0 + to:@29 +print_word: scope:[print_word] from main + (byte*) print_char_cursor#23 ← phi( main/(byte*) print_char_cursor#25 ) + (word) print_word::w#1 ← phi( main/(word) print_word::w#0 ) + (byte~) print_word::$0 ← > (word) print_word::w#1 + (byte) print_byte::b#0 ← (byte~) print_word::$0 + call print_byte + to:print_word::@1 +print_word::@1: scope:[print_word] from print_word + (word) print_word::w#2 ← phi( print_word/(word) print_word::w#1 ) + (byte*) print_char_cursor#12 ← phi( print_word/(byte*) print_char_cursor#6 ) + (byte*) print_char_cursor#1 ← (byte*) print_char_cursor#12 + (byte~) print_word::$2 ← < (word) print_word::w#2 + (byte) print_byte::b#1 ← (byte~) print_word::$2 + call print_byte + to:print_word::@2 +print_word::@2: scope:[print_word] from print_word::@1 + (byte*) print_char_cursor#13 ← phi( print_word::@1/(byte*) print_char_cursor#6 ) + (byte*) print_char_cursor#2 ← (byte*) print_char_cursor#13 + to:print_word::@return +print_word::@return: scope:[print_word] from print_word::@2 + (byte*) print_char_cursor#14 ← phi( print_word::@2/(byte*) print_char_cursor#2 ) + (byte*) print_char_cursor#3 ← (byte*) print_char_cursor#14 + return + to:@return +@29: scope:[] from @12 + (byte*) print_char_cursor#27 ← phi( @12/(byte*) print_char_cursor#0 ) + (byte[]) print_hextab#0 ← (const string) $0 + to:@37 +print_byte: scope:[print_byte] from print_word print_word::@1 + (byte*) print_char_cursor#24 ← phi( print_word/(byte*) print_char_cursor#23 print_word::@1/(byte*) print_char_cursor#1 ) + (byte) print_byte::b#2 ← phi( print_word/(byte) print_byte::b#0 print_word::@1/(byte) print_byte::b#1 ) + (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (number) 4 + (byte) print_char::ch#0 ← *((byte[]) print_hextab#0 + (byte~) print_byte::$0) + call print_char + to:print_byte::@1 +print_byte::@1: scope:[print_byte] from print_byte + (byte) print_byte::b#3 ← phi( print_byte/(byte) print_byte::b#2 ) + (byte*) print_char_cursor#15 ← phi( print_byte/(byte*) print_char_cursor#8 ) + (byte*) print_char_cursor#4 ← (byte*) print_char_cursor#15 + (number~) print_byte::$2 ← (byte) print_byte::b#3 & (number) $f + (byte) print_char::ch#1 ← *((byte[]) print_hextab#0 + (number~) print_byte::$2) + call print_char + to:print_byte::@2 +print_byte::@2: scope:[print_byte] from print_byte::@1 + (byte*) print_char_cursor#16 ← phi( print_byte::@1/(byte*) print_char_cursor#8 ) + (byte*) print_char_cursor#5 ← (byte*) print_char_cursor#16 + to:print_byte::@return +print_byte::@return: scope:[print_byte] from print_byte::@2 + (byte*) print_char_cursor#17 ← phi( print_byte::@2/(byte*) print_char_cursor#5 ) + (byte*) print_char_cursor#6 ← (byte*) print_char_cursor#17 + return + to:@return +print_char: scope:[print_char] from print_byte print_byte::@1 + (byte*) print_char_cursor#18 ← phi( print_byte/(byte*) print_char_cursor#24 print_byte::@1/(byte*) print_char_cursor#4 ) + (byte) print_char::ch#2 ← phi( print_byte/(byte) print_char::ch#0 print_byte::@1/(byte) print_char::ch#1 ) + *((byte*) print_char_cursor#18) ← (byte) print_char::ch#2 + (byte*) print_char_cursor#7 ← ++ (byte*) print_char_cursor#18 + to:print_char::@return +print_char::@return: scope:[print_char] from print_char + (byte*) print_char_cursor#19 ← phi( print_char/(byte*) print_char_cursor#7 ) + (byte*) print_char_cursor#8 ← (byte*) print_char_cursor#19 + return + to:@return +main: scope:[main] from @37 + (byte*) print_char_cursor#25 ← phi( @37/(byte*) print_char_cursor#26 ) + (struct fileentry*) main::file#0 ← (struct fileentry*) 0 + (word) main::uSize#0 ← (word) 0 + (struct fileentry*) main::file#1 ← ((struct fileentry*)) (number) $4000 + (byte**) main::$3 ← (byte**)(struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT + *((byte**) main::$3) ← ((byte*)) (number) 4 + (byte**) main::$4 ← (byte**)(struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT + (byte*~) main::$0 ← *((byte**) main::$4) + (number) $1e + (word*~) main::$1 ← ((word*)) (byte*~) main::$0 + (word*) main::ptrw#0 ← (word*~) main::$1 + (word) main::uSize#1 ← *((word*) main::ptrw#0) + (word) print_word::w#0 ← (word) main::uSize#1 + call print_word + to:main::@1 +main::@1: scope:[main] from main + (byte*) print_char_cursor#20 ← phi( main/(byte*) print_char_cursor#3 ) + (byte*) print_char_cursor#9 ← (byte*) print_char_cursor#20 + to:main::@return +main::@return: scope:[main] from main::@1 + (byte*) print_char_cursor#21 ← phi( main::@1/(byte*) print_char_cursor#9 ) + (byte*) print_char_cursor#10 ← (byte*) print_char_cursor#21 + return + to:@return +@37: scope:[] from @29 + (byte*) print_char_cursor#26 ← phi( @29/(byte*) print_char_cursor#27 ) + call main + to:@38 +@38: scope:[] from @37 + (byte*) print_char_cursor#22 ← phi( @37/(byte*) print_char_cursor#10 ) + (byte*) print_char_cursor#11 ← (byte*) print_char_cursor#22 + to:@end +@end: scope:[] from @38 + +SYMBOL TABLE SSA +(const string) $0 = (string) "0123456789abcdef"z +(label) @12 +(label) @29 +(label) @37 +(label) @38 +(label) @begin +(label) @end +(const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT = (byte) 0 +(const byte) RADIX::BINARY = (number) 2 +(const byte) RADIX::DECIMAL = (number) $a +(const byte) RADIX::HEXADECIMAL = (number) $10 +(const byte) RADIX::OCTAL = (number) 8 +(byte) fileentry::bError +(byte) fileentry::bFlag +(byte*) fileentry::bufEdit +(void()) main() +(byte*~) main::$0 +(word*~) main::$1 +(byte**) main::$3 +(byte**) main::$4 +(label) main::@1 +(label) main::@return +(struct fileentry*) main::file +(struct fileentry*) main::file#0 +(struct fileentry*) main::file#1 +(word*) main::ptrw +(word*) main::ptrw#0 +(word) main::uSize +(word) main::uSize#0 +(word) main::uSize#1 +(void()) print_byte((byte) print_byte::b) +(byte~) print_byte::$0 +(number~) print_byte::$2 +(label) print_byte::@1 +(label) print_byte::@2 +(label) print_byte::@return +(byte) print_byte::b +(byte) print_byte::b#0 +(byte) print_byte::b#1 +(byte) print_byte::b#2 +(byte) print_byte::b#3 +(void()) print_char((byte) print_char::ch) +(label) print_char::@return +(byte) print_char::ch +(byte) print_char::ch#0 +(byte) print_char::ch#1 +(byte) print_char::ch#2 +(byte*) print_char_cursor +(byte*) print_char_cursor#0 +(byte*) print_char_cursor#1 +(byte*) print_char_cursor#10 +(byte*) print_char_cursor#11 +(byte*) print_char_cursor#12 +(byte*) print_char_cursor#13 +(byte*) print_char_cursor#14 +(byte*) print_char_cursor#15 +(byte*) print_char_cursor#16 +(byte*) print_char_cursor#17 +(byte*) print_char_cursor#18 +(byte*) print_char_cursor#19 +(byte*) print_char_cursor#2 +(byte*) print_char_cursor#20 +(byte*) print_char_cursor#21 +(byte*) print_char_cursor#22 +(byte*) print_char_cursor#23 +(byte*) print_char_cursor#24 +(byte*) print_char_cursor#25 +(byte*) print_char_cursor#26 +(byte*) print_char_cursor#27 +(byte*) print_char_cursor#3 +(byte*) print_char_cursor#4 +(byte*) print_char_cursor#5 +(byte*) print_char_cursor#6 +(byte*) print_char_cursor#7 +(byte*) print_char_cursor#8 +(byte*) print_char_cursor#9 +(byte[]) print_hextab +(byte[]) print_hextab#0 +(byte*) print_line_cursor +(byte*) print_line_cursor#0 +(byte*) print_screen +(byte*) print_screen#0 +(void()) print_word((word) print_word::w) +(byte~) print_word::$0 +(byte~) print_word::$2 +(label) print_word::@1 +(label) print_word::@2 +(label) print_word::@return +(word) print_word::w +(word) print_word::w#0 +(word) print_word::w#1 +(word) print_word::w#2 + +Adding number conversion cast (unumber) 4 in (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (number) 4 +Adding number conversion cast (unumber) $f in (number~) print_byte::$2 ← (byte) print_byte::b#3 & (number) $f +Adding number conversion cast (unumber) print_byte::$2 in (number~) print_byte::$2 ← (byte) print_byte::b#3 & (unumber)(number) $f +Adding number conversion cast (unumber) $1e in (byte*~) main::$0 ← *((byte**) main::$4) + (number) $1e +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (byte*) print_screen#0 ← (byte*)(number) $400 +Inlining cast (struct fileentry*) main::file#1 ← (struct fileentry*)(number) $4000 +Inlining cast *((byte**) main::$3) ← (byte*)(number) 4 +Inlining cast (word*~) main::$1 ← (word*)(byte*~) main::$0 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast 4 +Simplifying constant integer cast $f +Simplifying constant pointer cast (struct fileentry*) 16384 +Simplifying constant pointer cast (byte*) 4 +Simplifying constant integer cast $1e +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 4 +Finalized unsigned number type (byte) $f +Finalized unsigned number type (byte) $1e +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to byte in (unumber~) print_byte::$2 ← (byte) print_byte::b#3 & (byte) $f +Alias (byte*) print_char_cursor#0 = (byte*) print_line_cursor#0 (byte*) print_screen#0 (byte*) print_char_cursor#27 (byte*) print_char_cursor#26 +Alias (byte) print_byte::b#0 = (byte~) print_word::$0 +Alias (word) print_word::w#1 = (word) print_word::w#2 +Alias (byte*) print_char_cursor#1 = (byte*) print_char_cursor#12 +Alias (byte) print_byte::b#1 = (byte~) print_word::$2 +Alias (byte*) print_char_cursor#13 = (byte*) print_char_cursor#2 (byte*) print_char_cursor#14 (byte*) print_char_cursor#3 +Alias (byte) print_byte::b#2 = (byte) print_byte::b#3 +Alias (byte*) print_char_cursor#15 = (byte*) print_char_cursor#4 +Alias (byte*) print_char_cursor#16 = (byte*) print_char_cursor#5 (byte*) print_char_cursor#17 (byte*) print_char_cursor#6 +Alias (byte*) print_char_cursor#19 = (byte*) print_char_cursor#7 (byte*) print_char_cursor#8 +Alias (word*) main::ptrw#0 = (word*~) main::$1 +Alias (byte*) print_char_cursor#10 = (byte*) print_char_cursor#9 (byte*) print_char_cursor#20 (byte*) print_char_cursor#21 +Alias (byte*) print_char_cursor#11 = (byte*) print_char_cursor#22 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values (word) print_word::w#1 (word) print_word::w#0 +Identical Phi Values (byte*) print_char_cursor#23 (byte*) print_char_cursor#25 +Identical Phi Values (byte*) print_char_cursor#1 (byte*) print_char_cursor#16 +Identical Phi Values (byte*) print_char_cursor#13 (byte*) print_char_cursor#16 +Identical Phi Values (byte*) print_char_cursor#15 (byte*) print_char_cursor#19 +Identical Phi Values (byte*) print_char_cursor#16 (byte*) print_char_cursor#19 +Identical Phi Values (byte*) print_char_cursor#25 (byte*) print_char_cursor#0 +Identical Phi Values (byte*) print_char_cursor#10 (byte*) print_char_cursor#13 +Identical Phi Values (byte*) print_char_cursor#11 (byte*) print_char_cursor#10 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant (const byte*) print_char_cursor#0 = (byte*) 1024 +Constant (const byte[]) print_hextab#0 = $0 +Constant (const struct fileentry*) main::file#0 = (struct fileentry*) 0 +Constant (const word) main::uSize#0 = 0 +Constant (const struct fileentry*) main::file#1 = (struct fileentry*) 16384 +Successful SSA optimization Pass2ConstantIdentification +Constant value identified (byte**)main::file#1 in [43] (byte**) main::$3 ← (byte**)(const struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT +Constant value identified (byte**)main::file#1 in [45] (byte**) main::$4 ← (byte**)(const struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT +Successful SSA optimization Pass2ConstantValues +Converting *(pointer+n) to pointer[n] [44] *((byte**) main::$3) ← (byte*) 4 -- *((byte**)main::file#1 + OFFSET_STRUCT_FILEENTRY_BUFEDIT) +Converting *(pointer+n) to pointer[n] [46] (byte*~) main::$0 ← *((byte**) main::$4) + (byte) $1e -- *((byte**)main::file#1 + OFFSET_STRUCT_FILEENTRY_BUFEDIT) +Converting *(pointer+n) to pointer[n] [49] (word) main::uSize#1 ← *((word*) main::ptrw#0) -- *((word*)*((byte**)main::file#1 + OFFSET_STRUCT_FILEENTRY_BUFEDIT) + $1e) +Successful SSA optimization Pass2InlineDerefIdx +Simplifying expression containing zero (byte**)main::file#1 in [43] (byte**) main::$3 ← (byte**)(const struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT +Simplifying expression containing zero (byte**)main::file#1 in [44] *((byte**)(const struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT) ← (byte*) 4 +Simplifying expression containing zero (byte**)main::file#1 in [45] (byte**) main::$4 ← (byte**)(const struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT +Simplifying expression containing zero (byte**)main::file#1 in [46] (byte*~) main::$0 ← *((byte**)(const struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT) + (byte) $1e +Simplifying expression containing zero (byte**)main::file#1 in [49] (word) main::uSize#1 ← *((word*)*((byte**)(const struct fileentry*) main::file#1 + (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT) + (byte) $1e) +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused variable (byte**) main::$3 and assignment [17] (byte**) main::$3 ← (byte**)(const struct fileentry*) main::file#1 +Eliminating unused variable (byte**) main::$4 and assignment [19] (byte**) main::$4 ← (byte**)(const struct fileentry*) main::file#1 +Eliminating unused variable (word*) main::ptrw#0 and assignment [21] (word*) main::ptrw#0 ← (word*)(byte*~) main::$0 +Eliminating unused constant (const struct fileentry*) main::file#0 +Eliminating unused constant (const word) main::uSize#0 +Eliminating unused constant (const byte) OFFSET_STRUCT_FILEENTRY_BUFEDIT +Successful SSA optimization PassNEliminateUnusedVars +Eliminating unused variable (byte*~) main::$0 and assignment [18] (byte*~) main::$0 ← *((byte**)(const struct fileentry*) main::file#1) + (byte) $1e +Successful SSA optimization PassNEliminateUnusedVars +Inlining constant with var siblings (const byte*) print_char_cursor#0 +Constant inlined $0 = (const byte[]) print_hextab#0 +Constant inlined print_char_cursor#0 = (byte*) 1024 +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @12 +Adding NOP phi() at start of @29 +Adding NOP phi() at start of @37 +Adding NOP phi() at start of @38 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main::@1 +Adding NOP phi() at start of print_word::@2 +Adding NOP phi() at start of print_byte::@2 +CALL GRAPH +Calls in [] to main:4 +Calls in [main] to print_word:10 +Calls in [print_word] to print_byte:15 print_byte:19 +Calls in [print_byte] to print_char:27 print_char:32 + +Created 4 initial phi equivalence classes +Coalesced [14] print_byte::b#4 ← print_byte::b#0 +Coalesced [17] print_byte::b#5 ← print_byte::b#1 +Coalesced [18] print_char_cursor#28 ← print_char_cursor#19 +Coalesced [25] print_char::ch#3 ← print_char::ch#0 +Coalesced [26] print_char_cursor#29 ← print_char_cursor#24 +Coalesced [30] print_char::ch#4 ← print_char::ch#1 +Coalesced (already) [31] print_char_cursor#30 ← print_char_cursor#19 +Coalesced down to 3 phi equivalence classes +Culled Empty Block (label) @12 +Culled Empty Block (label) @29 +Culled Empty Block (label) @38 +Culled Empty Block (label) main::@1 +Culled Empty Block (label) print_word::@2 +Culled Empty Block (label) print_byte::@2 +Renumbering block @37 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**)(const struct fileentry*) main::file#1) ← (byte*) 4 + [5] (word) main::uSize#1 ← *((word*)*((byte**)(const struct fileentry*) main::file#1) + (byte) $1e) + [6] (word) print_word::w#0 ← (word) main::uSize#1 + [7] call print_word + to:main::@return +main::@return: scope:[main] from main + [8] return + to:@return +print_word: scope:[print_word] from main + [9] (byte) print_byte::b#0 ← > (word) print_word::w#0 + [10] call print_byte + to:print_word::@1 +print_word::@1: scope:[print_word] from print_word + [11] (byte) print_byte::b#1 ← < (word) print_word::w#0 + [12] call print_byte + to:print_word::@return +print_word::@return: scope:[print_word] from print_word::@1 + [13] return + to:@return +print_byte: scope:[print_byte] from print_word print_word::@1 + [14] (byte*) print_char_cursor#24 ← phi( print_word/(byte*) 1024 print_word::@1/(byte*) print_char_cursor#19 ) + [14] (byte) print_byte::b#2 ← phi( print_word/(byte) print_byte::b#0 print_word::@1/(byte) print_byte::b#1 ) + [15] (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte) 4 + [16] (byte) print_char::ch#0 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$0) + [17] call print_char + to:print_byte::@1 +print_byte::@1: scope:[print_byte] from print_byte + [18] (byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte) $f + [19] (byte) print_char::ch#1 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$2) + [20] call print_char + to:print_byte::@return +print_byte::@return: scope:[print_byte] from print_byte::@1 + [21] return + to:@return +print_char: scope:[print_char] from print_byte print_byte::@1 + [22] (byte*) print_char_cursor#18 ← phi( print_byte/(byte*) print_char_cursor#24 print_byte::@1/(byte*) print_char_cursor#19 ) + [22] (byte) print_char::ch#2 ← phi( print_byte/(byte) print_char::ch#0 print_byte::@1/(byte) print_char::ch#1 ) + [23] *((byte*) print_char_cursor#18) ← (byte) print_char::ch#2 + [24] (byte*) print_char_cursor#19 ← ++ (byte*) print_char_cursor#18 + to:print_char::@return +print_char::@return: scope:[print_char] from print_char + [25] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) fileentry::bError +(byte) fileentry::bFlag +(byte*) fileentry::bufEdit +(void()) main() +(struct fileentry*) main::file +(word*) main::ptrw +(word) main::uSize +(word) main::uSize#1 4.0 +(void()) print_byte((byte) print_byte::b) +(byte~) print_byte::$0 4.0 +(byte~) print_byte::$2 4.0 +(byte) print_byte::b +(byte) print_byte::b#0 4.0 +(byte) print_byte::b#1 4.0 +(byte) print_byte::b#2 2.0 +(void()) print_char((byte) print_char::ch) +(byte) print_char::ch +(byte) print_char::ch#0 4.0 +(byte) print_char::ch#1 4.0 +(byte) print_char::ch#2 6.0 +(byte*) print_char_cursor +(byte*) print_char_cursor#18 4.0 +(byte*) print_char_cursor#19 0.6666666666666666 +(byte*) print_char_cursor#24 1.3333333333333333 +(byte[]) print_hextab +(byte*) print_line_cursor +(byte*) print_screen +(void()) print_word((word) print_word::w) +(word) print_word::w +(word) print_word::w#0 2.0 + +Initial phi equivalence classes +[ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] +[ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] +[ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] +Added variable main::uSize#1 to zero page equivalence class [ main::uSize#1 ] +Added variable print_word::w#0 to zero page equivalence class [ print_word::w#0 ] +Added variable print_byte::$0 to zero page equivalence class [ print_byte::$0 ] +Added variable print_byte::$2 to zero page equivalence class [ print_byte::$2 ] +Complete equivalence classes +[ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] +[ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] +[ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] +[ main::uSize#1 ] +[ print_word::w#0 ] +[ print_byte::$0 ] +[ print_byte::$2 ] +Allocated zp ZP_BYTE:2 [ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] +Allocated zp ZP_BYTE:3 [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] +Allocated zp ZP_WORD:4 [ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] +Allocated zp ZP_WORD:6 [ main::uSize#1 ] +Allocated zp ZP_WORD:8 [ print_word::w#0 ] +Allocated zp ZP_BYTE:10 [ print_byte::$0 ] +Allocated zp ZP_BYTE:11 [ print_byte::$2 ] + +INITIAL ASM +Target platform is c64basic + // File Comments + // Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label print_char_cursor = 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 file = $4000 + .label uSize = 6 + // [4] *((byte**)(const struct fileentry*) main::file#1) ← (byte*) 4 -- _deref_pptc1=pbuc2 + lda #<4 + sta file + lda #>4 + sta file+1 + // [5] (word) main::uSize#1 ← *((word*)*((byte**)(const struct fileentry*) main::file#1) + (byte) $1e) -- vwuz1=(_deref_pptc1)_derefidx_vbuc2 + ldy #$1e + ldx file + stx.z $fe + ldx file+1 + stx.z $ff + lda ($fe),y + sta.z uSize + iny + lda ($fe),y + sta.z uSize+1 + // [6] (word) print_word::w#0 ← (word) main::uSize#1 -- vwuz1=vwuz2 + lda.z uSize + sta.z print_word.w + lda.z uSize+1 + sta.z print_word.w+1 + // [7] call print_word + jsr print_word + jmp breturn + // main::@return + breturn: + // [8] return + rts +} + // print_word +// Print a word as HEX +// print_word(word zeropage(8) w) +print_word: { + .label w = 8 + // [9] (byte) print_byte::b#0 ← > (word) print_word::w#0 -- vbuz1=_hi_vwuz2 + lda.z w+1 + sta.z print_byte.b + // [10] call print_byte + // [14] phi from print_word to print_byte [phi:print_word->print_byte] + print_byte_from_print_word: + // [14] phi (byte*) print_char_cursor#24 = (byte*) 1024 [phi:print_word->print_byte#0] -- pbuz1=pbuc1 + lda #<$400 + sta.z print_char_cursor + lda #>$400 + sta.z print_char_cursor+1 + // [14] phi (byte) print_byte::b#2 = (byte) print_byte::b#0 [phi:print_word->print_byte#1] -- register_copy + jsr print_byte + jmp b1 + // print_word::@1 + b1: + // [11] (byte) print_byte::b#1 ← < (word) print_word::w#0 -- vbuz1=_lo_vwuz2 + lda.z w + sta.z print_byte.b + // [12] call print_byte + // [14] phi from print_word::@1 to print_byte [phi:print_word::@1->print_byte] + print_byte_from_b1: + // [14] phi (byte*) print_char_cursor#24 = (byte*) print_char_cursor#19 [phi:print_word::@1->print_byte#0] -- register_copy + // [14] phi (byte) print_byte::b#2 = (byte) print_byte::b#1 [phi:print_word::@1->print_byte#1] -- register_copy + jsr print_byte + jmp breturn + // print_word::@return + breturn: + // [13] return + rts +} + // print_byte +// Print a byte as HEX +// print_byte(byte zeropage(2) b) +print_byte: { + .label _0 = $a + .label _2 = $b + .label b = 2 + // [15] (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte) 4 -- vbuz1=vbuz2_ror_4 + lda.z b + lsr + lsr + lsr + lsr + sta.z _0 + // [16] (byte) print_char::ch#0 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$0) -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z _0 + lda print_hextab,y + sta.z print_char.ch + // [17] call print_char + // [22] phi from print_byte to print_char [phi:print_byte->print_char] + print_char_from_print_byte: + // [22] phi (byte*) print_char_cursor#18 = (byte*) print_char_cursor#24 [phi:print_byte->print_char#0] -- register_copy + // [22] phi (byte) print_char::ch#2 = (byte) print_char::ch#0 [phi:print_byte->print_char#1] -- register_copy + jsr print_char + jmp b1 + // print_byte::@1 + b1: + // [18] (byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte) $f -- vbuz1=vbuz2_band_vbuc1 + lda #$f + and.z b + sta.z _2 + // [19] (byte) print_char::ch#1 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$2) -- vbuz1=pbuc1_derefidx_vbuz2 + ldy.z _2 + lda print_hextab,y + sta.z print_char.ch + // [20] call print_char + // [22] phi from print_byte::@1 to print_char [phi:print_byte::@1->print_char] + print_char_from_b1: + // [22] phi (byte*) print_char_cursor#18 = (byte*) print_char_cursor#19 [phi:print_byte::@1->print_char#0] -- register_copy + // [22] phi (byte) print_char::ch#2 = (byte) print_char::ch#1 [phi:print_byte::@1->print_char#1] -- register_copy + jsr print_char + jmp breturn + // print_byte::@return + breturn: + // [21] return + rts +} + // print_char +// Print a single char +// print_char(byte zeropage(3) ch) +print_char: { + .label ch = 3 + // [23] *((byte*) print_char_cursor#18) ← (byte) print_char::ch#2 -- _deref_pbuz1=vbuz2 + lda.z ch + ldy #0 + sta (print_char_cursor),y + // [24] (byte*) print_char_cursor#19 ← ++ (byte*) print_char_cursor#18 -- pbuz1=_inc_pbuz1 + inc.z print_char_cursor + bne !+ + inc.z print_char_cursor+1 + !: + jmp breturn + // print_char::@return + breturn: + // [25] return + rts +} + // File Data + print_hextab: .text "0123456789abcdef" + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [4] *((byte**)(const struct fileentry*) main::file#1) ← (byte*) 4 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [5] (word) main::uSize#1 ← *((word*)*((byte**)(const struct fileentry*) main::file#1) + (byte) $1e) [ main::uSize#1 ] ( main:2 [ main::uSize#1 ] ) always clobbers reg byte a reg byte x reg byte y +Statement [6] (word) print_word::w#0 ← (word) main::uSize#1 [ print_word::w#0 ] ( main:2 [ print_word::w#0 ] ) always clobbers reg byte a +Statement [9] (byte) print_byte::b#0 ← > (word) print_word::w#0 [ print_word::w#0 print_byte::b#0 ] ( main:2::print_word:7 [ print_word::w#0 print_byte::b#0 ] ) always clobbers reg byte a +Statement [11] (byte) print_byte::b#1 ← < (word) print_word::w#0 [ print_byte::b#1 print_char_cursor#19 ] ( main:2::print_word:7 [ print_byte::b#1 print_char_cursor#19 ] ) always clobbers reg byte a +Statement [15] (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte) 4 [ print_byte::b#2 print_char_cursor#24 print_byte::$0 ] ( main:2::print_word:7::print_byte:10 [ print_word::w#0 print_byte::b#2 print_char_cursor#24 print_byte::$0 ] main:2::print_word:7::print_byte:12 [ print_byte::b#2 print_char_cursor#24 print_byte::$0 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] +Statement [18] (byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte) $f [ print_char_cursor#19 print_byte::$2 ] ( main:2::print_word:7::print_byte:10 [ print_word::w#0 print_char_cursor#19 print_byte::$2 ] main:2::print_word:7::print_byte:12 [ print_char_cursor#19 print_byte::$2 ] ) always clobbers reg byte a +Statement [23] *((byte*) print_char_cursor#18) ← (byte) print_char::ch#2 [ print_char_cursor#18 ] ( main:2::print_word:7::print_byte:10::print_char:17 [ print_word::w#0 print_byte::b#2 print_char_cursor#18 ] main:2::print_word:7::print_byte:12::print_char:17 [ print_byte::b#2 print_char_cursor#18 ] main:2::print_word:7::print_byte:10::print_char:20 [ print_word::w#0 print_char_cursor#18 ] main:2::print_word:7::print_byte:12::print_char:20 [ print_char_cursor#18 ] ) always clobbers reg byte y +Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] +Statement [4] *((byte**)(const struct fileentry*) main::file#1) ← (byte*) 4 [ ] ( main:2 [ ] ) always clobbers reg byte a +Statement [5] (word) main::uSize#1 ← *((word*)*((byte**)(const struct fileentry*) main::file#1) + (byte) $1e) [ main::uSize#1 ] ( main:2 [ main::uSize#1 ] ) always clobbers reg byte a reg byte x reg byte y +Statement [6] (word) print_word::w#0 ← (word) main::uSize#1 [ print_word::w#0 ] ( main:2 [ print_word::w#0 ] ) always clobbers reg byte a +Statement [9] (byte) print_byte::b#0 ← > (word) print_word::w#0 [ print_word::w#0 print_byte::b#0 ] ( main:2::print_word:7 [ print_word::w#0 print_byte::b#0 ] ) always clobbers reg byte a +Statement [11] (byte) print_byte::b#1 ← < (word) print_word::w#0 [ print_byte::b#1 print_char_cursor#19 ] ( main:2::print_word:7 [ print_byte::b#1 print_char_cursor#19 ] ) always clobbers reg byte a +Statement [15] (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte) 4 [ print_byte::b#2 print_char_cursor#24 print_byte::$0 ] ( main:2::print_word:7::print_byte:10 [ print_word::w#0 print_byte::b#2 print_char_cursor#24 print_byte::$0 ] main:2::print_word:7::print_byte:12 [ print_byte::b#2 print_char_cursor#24 print_byte::$0 ] ) always clobbers reg byte a +Statement [18] (byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte) $f [ print_char_cursor#19 print_byte::$2 ] ( main:2::print_word:7::print_byte:10 [ print_word::w#0 print_char_cursor#19 print_byte::$2 ] main:2::print_word:7::print_byte:12 [ print_char_cursor#19 print_byte::$2 ] ) always clobbers reg byte a +Statement [23] *((byte*) print_char_cursor#18) ← (byte) print_char::ch#2 [ print_char_cursor#18 ] ( main:2::print_word:7::print_byte:10::print_char:17 [ print_word::w#0 print_byte::b#2 print_char_cursor#18 ] main:2::print_word:7::print_byte:12::print_char:17 [ print_byte::b#2 print_char_cursor#18 ] main:2::print_word:7::print_byte:10::print_char:20 [ print_word::w#0 print_char_cursor#18 ] main:2::print_word:7::print_byte:12::print_char:20 [ print_char_cursor#18 ] ) always clobbers reg byte y +Potential registers zp ZP_BYTE:2 [ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] : zp ZP_BYTE:2 , reg byte x , +Potential registers zp ZP_BYTE:3 [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_WORD:4 [ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] : zp ZP_WORD:4 , +Potential registers zp ZP_WORD:6 [ main::uSize#1 ] : zp ZP_WORD:6 , +Potential registers zp ZP_WORD:8 [ print_word::w#0 ] : zp ZP_WORD:8 , +Potential registers zp ZP_BYTE:10 [ print_byte::$0 ] : zp ZP_BYTE:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:11 [ print_byte::$2 ] : zp ZP_BYTE:11 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [print_byte] 10: zp ZP_BYTE:2 [ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] 4: zp ZP_BYTE:10 [ print_byte::$0 ] 4: zp ZP_BYTE:11 [ print_byte::$2 ] +Uplift Scope [print_char] 14: zp ZP_BYTE:3 [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] +Uplift Scope [] 6: zp ZP_WORD:4 [ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] +Uplift Scope [main] 4: zp ZP_WORD:6 [ main::uSize#1 ] +Uplift Scope [print_word] 2: zp ZP_WORD:8 [ print_word::w#0 ] +Uplift Scope [RADIX] +Uplift Scope [fileentry] + +Uplifting [print_byte] best 216 combination reg byte x [ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] reg byte a [ print_byte::$0 ] reg byte x [ print_byte::$2 ] +Uplifting [print_char] best 207 combination reg byte a [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] +Uplifting [] best 207 combination zp ZP_WORD:4 [ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] +Uplifting [main] best 207 combination zp ZP_WORD:6 [ main::uSize#1 ] +Uplifting [print_word] best 207 combination zp ZP_WORD:8 [ print_word::w#0 ] +Uplifting [RADIX] best 207 combination +Uplifting [fileentry] best 207 combination +Coalescing zero page register [ zp ZP_WORD:6 [ main::uSize#1 ] ] with [ zp ZP_WORD:8 [ print_word::w#0 ] ] - score: 1 +Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] +Allocated (was zp ZP_WORD:6) zp ZP_WORD:4 [ main::uSize#1 print_word::w#0 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments + // Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label print_char_cursor = 2 + // @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 file = $4000 + .label uSize = 4 + // [4] *((byte**)(const struct fileentry*) main::file#1) ← (byte*) 4 -- _deref_pptc1=pbuc2 + lda #<4 + sta file + lda #>4 + sta file+1 + // [5] (word) main::uSize#1 ← *((word*)*((byte**)(const struct fileentry*) main::file#1) + (byte) $1e) -- vwuz1=(_deref_pptc1)_derefidx_vbuc2 + ldy #$1e + ldx file + stx.z $fe + ldx file+1 + stx.z $ff + lda ($fe),y + sta.z uSize + iny + lda ($fe),y + sta.z uSize+1 + // [6] (word) print_word::w#0 ← (word) main::uSize#1 + // [7] call print_word + jsr print_word + jmp breturn + // main::@return + breturn: + // [8] return + rts +} + // print_word +// Print a word as HEX +// print_word(word zeropage(4) w) +print_word: { + .label w = 4 + // [9] (byte) print_byte::b#0 ← > (word) print_word::w#0 -- vbuxx=_hi_vwuz1 + lda.z w+1 + tax + // [10] call print_byte + // [14] phi from print_word to print_byte [phi:print_word->print_byte] + print_byte_from_print_word: + // [14] phi (byte*) print_char_cursor#24 = (byte*) 1024 [phi:print_word->print_byte#0] -- pbuz1=pbuc1 + lda #<$400 + sta.z print_char_cursor + lda #>$400 + sta.z print_char_cursor+1 + // [14] phi (byte) print_byte::b#2 = (byte) print_byte::b#0 [phi:print_word->print_byte#1] -- register_copy + jsr print_byte + jmp b1 + // print_word::@1 + b1: + // [11] (byte) print_byte::b#1 ← < (word) print_word::w#0 -- vbuxx=_lo_vwuz1 + lda.z w + tax + // [12] call print_byte + // [14] phi from print_word::@1 to print_byte [phi:print_word::@1->print_byte] + print_byte_from_b1: + // [14] phi (byte*) print_char_cursor#24 = (byte*) print_char_cursor#19 [phi:print_word::@1->print_byte#0] -- register_copy + // [14] phi (byte) print_byte::b#2 = (byte) print_byte::b#1 [phi:print_word::@1->print_byte#1] -- register_copy + jsr print_byte + jmp breturn + // print_word::@return + breturn: + // [13] return + rts +} + // print_byte +// Print a byte as HEX +// print_byte(byte register(X) b) +print_byte: { + // [15] (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte) 4 -- vbuaa=vbuxx_ror_4 + txa + lsr + lsr + lsr + lsr + // [16] (byte) print_char::ch#0 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$0) -- vbuaa=pbuc1_derefidx_vbuaa + tay + lda print_hextab,y + // [17] call print_char + // [22] phi from print_byte to print_char [phi:print_byte->print_char] + print_char_from_print_byte: + // [22] phi (byte*) print_char_cursor#18 = (byte*) print_char_cursor#24 [phi:print_byte->print_char#0] -- register_copy + // [22] phi (byte) print_char::ch#2 = (byte) print_char::ch#0 [phi:print_byte->print_char#1] -- register_copy + jsr print_char + jmp b1 + // print_byte::@1 + b1: + // [18] (byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte) $f -- vbuxx=vbuxx_band_vbuc1 + lda #$f + axs #0 + // [19] (byte) print_char::ch#1 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$2) -- vbuaa=pbuc1_derefidx_vbuxx + lda print_hextab,x + // [20] call print_char + // [22] phi from print_byte::@1 to print_char [phi:print_byte::@1->print_char] + print_char_from_b1: + // [22] phi (byte*) print_char_cursor#18 = (byte*) print_char_cursor#19 [phi:print_byte::@1->print_char#0] -- register_copy + // [22] phi (byte) print_char::ch#2 = (byte) print_char::ch#1 [phi:print_byte::@1->print_char#1] -- register_copy + jsr print_char + jmp breturn + // print_byte::@return + breturn: + // [21] return + rts +} + // print_char +// Print a single char +// print_char(byte register(A) ch) +print_char: { + // [23] *((byte*) print_char_cursor#18) ← (byte) print_char::ch#2 -- _deref_pbuz1=vbuaa + ldy #0 + sta (print_char_cursor),y + // [24] (byte*) print_char_cursor#19 ← ++ (byte*) print_char_cursor#18 -- pbuz1=_inc_pbuz1 + inc.z print_char_cursor + bne !+ + inc.z print_char_cursor+1 + !: + jmp breturn + // print_char::@return + breturn: + // [25] return + rts +} + // File Data + print_hextab: .text "0123456789abcdef" + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp breturn +Removing instruction jmp b1 +Removing instruction jmp breturn +Removing instruction jmp b1 +Removing instruction jmp breturn +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing instruction ldx file+1 with TAX +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction bend_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction breturn: +Removing instruction print_byte_from_print_word: +Removing instruction b1: +Removing instruction print_byte_from_b1: +Removing instruction breturn: +Removing instruction print_char_from_print_byte: +Removing instruction b1: +Removing instruction print_char_from_b1: +Removing instruction breturn: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const byte) RADIX::BINARY BINARY = (number) 2 +(const byte) RADIX::DECIMAL DECIMAL = (number) $a +(const byte) RADIX::HEXADECIMAL HEXADECIMAL = (number) $10 +(const byte) RADIX::OCTAL OCTAL = (number) 8 +(byte) fileentry::bError +(byte) fileentry::bFlag +(byte*) fileentry::bufEdit +(void()) main() +(label) main::@return +(struct fileentry*) main::file +(const struct fileentry*) main::file#1 file = (struct fileentry*) 16384 +(word*) main::ptrw +(word) main::uSize +(word) main::uSize#1 uSize zp ZP_WORD:4 4.0 +(void()) print_byte((byte) print_byte::b) +(byte~) print_byte::$0 reg byte a 4.0 +(byte~) print_byte::$2 reg byte x 4.0 +(label) print_byte::@1 +(label) print_byte::@return +(byte) print_byte::b +(byte) print_byte::b#0 reg byte x 4.0 +(byte) print_byte::b#1 reg byte x 4.0 +(byte) print_byte::b#2 reg byte x 2.0 +(void()) print_char((byte) print_char::ch) +(label) print_char::@return +(byte) print_char::ch +(byte) print_char::ch#0 reg byte a 4.0 +(byte) print_char::ch#1 reg byte a 4.0 +(byte) print_char::ch#2 reg byte a 6.0 +(byte*) print_char_cursor +(byte*) print_char_cursor#18 print_char_cursor zp ZP_WORD:2 4.0 +(byte*) print_char_cursor#19 print_char_cursor zp ZP_WORD:2 0.6666666666666666 +(byte*) print_char_cursor#24 print_char_cursor zp ZP_WORD:2 1.3333333333333333 +(byte[]) print_hextab +(const byte[]) print_hextab#0 print_hextab = (string) "0123456789abcdef"z +(byte*) print_line_cursor +(byte*) print_screen +(void()) print_word((word) print_word::w) +(label) print_word::@1 +(label) print_word::@return +(word) print_word::w +(word) print_word::w#0 w zp ZP_WORD:4 2.0 + +reg byte x [ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] +reg byte a [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] +zp ZP_WORD:2 [ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] +zp ZP_WORD:4 [ main::uSize#1 print_word::w#0 ] +reg byte a [ print_byte::$0 ] +reg byte x [ print_byte::$2 ] + + +FINAL ASSEMBLER +Score: 163 + + // File Comments + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label print_char_cursor = 2 + // @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 file = $4000 + .label uSize = 4 + // file->bufEdit = 4 + // [4] *((byte**)(const struct fileentry*) main::file#1) ← (byte*) 4 -- _deref_pptc1=pbuc2 + lda #<4 + sta file + lda #>4 + sta file+1 + // uSize = *ptrw + // [5] (word) main::uSize#1 ← *((word*)*((byte**)(const struct fileentry*) main::file#1) + (byte) $1e) -- vwuz1=(_deref_pptc1)_derefidx_vbuc2 + ldy #$1e + ldx file + stx.z $fe + tax + stx.z $ff + lda ($fe),y + sta.z uSize + iny + lda ($fe),y + sta.z uSize+1 + // print_word(uSize) + // [6] (word) print_word::w#0 ← (word) main::uSize#1 + // [7] call print_word + jsr print_word + // main::@return + // } + // [8] return + rts +} + // print_word +// Print a word as HEX +// print_word(word zeropage(4) w) +print_word: { + .label w = 4 + // print_byte(>w) + // [9] (byte) print_byte::b#0 ← > (word) print_word::w#0 -- vbuxx=_hi_vwuz1 + lda.z w+1 + tax + // [10] call print_byte + // [14] phi from print_word to print_byte [phi:print_word->print_byte] + // [14] phi (byte*) print_char_cursor#24 = (byte*) 1024 [phi:print_word->print_byte#0] -- pbuz1=pbuc1 + lda #<$400 + sta.z print_char_cursor + lda #>$400 + sta.z print_char_cursor+1 + // [14] phi (byte) print_byte::b#2 = (byte) print_byte::b#0 [phi:print_word->print_byte#1] -- register_copy + jsr print_byte + // print_word::@1 + // print_byte(print_byte] + // [14] phi (byte*) print_char_cursor#24 = (byte*) print_char_cursor#19 [phi:print_word::@1->print_byte#0] -- register_copy + // [14] phi (byte) print_byte::b#2 = (byte) print_byte::b#1 [phi:print_word::@1->print_byte#1] -- register_copy + jsr print_byte + // print_word::@return + // } + // [13] return + rts +} + // print_byte +// Print a byte as HEX +// print_byte(byte register(X) b) +print_byte: { + // b>>4 + // [15] (byte~) print_byte::$0 ← (byte) print_byte::b#2 >> (byte) 4 -- vbuaa=vbuxx_ror_4 + txa + lsr + lsr + lsr + lsr + // print_char(print_hextab[b>>4]) + // [16] (byte) print_char::ch#0 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$0) -- vbuaa=pbuc1_derefidx_vbuaa + tay + lda print_hextab,y + // [17] call print_char + // [22] phi from print_byte to print_char [phi:print_byte->print_char] + // [22] phi (byte*) print_char_cursor#18 = (byte*) print_char_cursor#24 [phi:print_byte->print_char#0] -- register_copy + // [22] phi (byte) print_char::ch#2 = (byte) print_char::ch#0 [phi:print_byte->print_char#1] -- register_copy + jsr print_char + // print_byte::@1 + // b&$f + // [18] (byte~) print_byte::$2 ← (byte) print_byte::b#2 & (byte) $f -- vbuxx=vbuxx_band_vbuc1 + lda #$f + axs #0 + // print_char(print_hextab[b&$f]) + // [19] (byte) print_char::ch#1 ← *((const byte[]) print_hextab#0 + (byte~) print_byte::$2) -- vbuaa=pbuc1_derefidx_vbuxx + lda print_hextab,x + // [20] call print_char + // [22] phi from print_byte::@1 to print_char [phi:print_byte::@1->print_char] + // [22] phi (byte*) print_char_cursor#18 = (byte*) print_char_cursor#19 [phi:print_byte::@1->print_char#0] -- register_copy + // [22] phi (byte) print_char::ch#2 = (byte) print_char::ch#1 [phi:print_byte::@1->print_char#1] -- register_copy + jsr print_char + // print_byte::@return + // } + // [21] return + rts +} + // print_char +// Print a single char +// print_char(byte register(A) ch) +print_char: { + // *(print_char_cursor++) = ch + // [23] *((byte*) print_char_cursor#18) ← (byte) print_char::ch#2 -- _deref_pbuz1=vbuaa + ldy #0 + sta (print_char_cursor),y + // *(print_char_cursor++) = ch; + // [24] (byte*) print_char_cursor#19 ← ++ (byte*) print_char_cursor#18 -- pbuz1=_inc_pbuz1 + inc.z print_char_cursor + bne !+ + inc.z print_char_cursor+1 + !: + // print_char::@return + // } + // [25] return + rts +} + // File Data + print_hextab: .text "0123456789abcdef" + diff --git a/src/test/ref/struct-ptr-26.sym b/src/test/ref/struct-ptr-26.sym new file mode 100644 index 000000000..157efda06 --- /dev/null +++ b/src/test/ref/struct-ptr-26.sym @@ -0,0 +1,52 @@ +(label) @1 +(label) @begin +(label) @end +(const byte) RADIX::BINARY BINARY = (number) 2 +(const byte) RADIX::DECIMAL DECIMAL = (number) $a +(const byte) RADIX::HEXADECIMAL HEXADECIMAL = (number) $10 +(const byte) RADIX::OCTAL OCTAL = (number) 8 +(byte) fileentry::bError +(byte) fileentry::bFlag +(byte*) fileentry::bufEdit +(void()) main() +(label) main::@return +(struct fileentry*) main::file +(const struct fileentry*) main::file#1 file = (struct fileentry*) 16384 +(word*) main::ptrw +(word) main::uSize +(word) main::uSize#1 uSize zp ZP_WORD:4 4.0 +(void()) print_byte((byte) print_byte::b) +(byte~) print_byte::$0 reg byte a 4.0 +(byte~) print_byte::$2 reg byte x 4.0 +(label) print_byte::@1 +(label) print_byte::@return +(byte) print_byte::b +(byte) print_byte::b#0 reg byte x 4.0 +(byte) print_byte::b#1 reg byte x 4.0 +(byte) print_byte::b#2 reg byte x 2.0 +(void()) print_char((byte) print_char::ch) +(label) print_char::@return +(byte) print_char::ch +(byte) print_char::ch#0 reg byte a 4.0 +(byte) print_char::ch#1 reg byte a 4.0 +(byte) print_char::ch#2 reg byte a 6.0 +(byte*) print_char_cursor +(byte*) print_char_cursor#18 print_char_cursor zp ZP_WORD:2 4.0 +(byte*) print_char_cursor#19 print_char_cursor zp ZP_WORD:2 0.6666666666666666 +(byte*) print_char_cursor#24 print_char_cursor zp ZP_WORD:2 1.3333333333333333 +(byte[]) print_hextab +(const byte[]) print_hextab#0 print_hextab = (string) "0123456789abcdef"z +(byte*) print_line_cursor +(byte*) print_screen +(void()) print_word((word) print_word::w) +(label) print_word::@1 +(label) print_word::@return +(word) print_word::w +(word) print_word::w#0 w zp ZP_WORD:4 2.0 + +reg byte x [ print_byte::b#2 print_byte::b#0 print_byte::b#1 ] +reg byte a [ print_char::ch#2 print_char::ch#0 print_char::ch#1 ] +zp ZP_WORD:2 [ print_char_cursor#18 print_char_cursor#24 print_char_cursor#19 ] +zp ZP_WORD:4 [ main::uSize#1 print_word::w#0 ] +reg byte a [ print_byte::$0 ] +reg byte x [ print_byte::$2 ]