diff --git a/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.asm b/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.asm new file mode 100644 index 000000000..121388002 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.asm @@ -0,0 +1,10 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + jsr main +main: { + .label screen = $400 + lda #'*' + sta screen+0 + rts +} diff --git a/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.cfg b/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.cfg new file mode 100644 index 000000000..28fef650a --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.cfg @@ -0,0 +1,18 @@ +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@1 +@1: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @1 + [3] phi() [ ] ( ) +main: scope:[main] from @1 + [4] phi() [ ] ( main:2 [ ] ) + to:main::@1 +main::@1: scope:[main] from main + [5] *((const byte*) main::screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '*' [ ] ( main:2 [ ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [6] return [ ] ( main:2 [ ] ) + to:@return diff --git a/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.log b/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.log new file mode 100644 index 000000000..0bf67d000 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.log @@ -0,0 +1,343 @@ +PARSING src/test/java/dk/camelot64/kickc/test/kc/const-pointer.kc +//Test that constant pointers are detected correctly + +void main() { + byte* screen = $400; + byte* NULL = $0; + byte* rem = $ff; + + if(rem!=NULL) { + screen[0] = '*'; + } else { + screen[0] = '.'; + } +} +SYMBOLS +(label) @1 +(label) @begin +(label) @end +(void()) main() +(boolean~) main::$0 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@return +(byte*) main::NULL +(byte*) main::rem +(byte*) main::screen + +Promoting word/signed word/dword/signed dword to byte* in main::screen ← ((byte*)) 1024 +Promoting byte/signed byte/word/signed word/dword/signed dword to byte* in main::NULL ← ((byte*)) 0 +Promoting byte/word/signed word/dword/signed dword to byte* in main::rem ← ((byte*)) 255 +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from + (byte*) main::screen ← ((byte*)) (word/signed word/dword/signed dword) 1024 + (byte*) main::NULL ← ((byte*)) (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte*) main::rem ← ((byte*)) (byte/word/signed word/dword/signed dword) 255 + (boolean~) main::$0 ← (byte*) main::rem != (byte*) main::NULL + if((boolean~) main::$0) goto main::@1 + to:main::@3 +main::@1: scope:[main] from main main::@4 + *((byte*) main::screen + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '*' + to:main::@2 +main::@3: scope:[main] from main + *((byte*) main::screen + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '.' + to:main::@2 +main::@2: scope:[main] from main::@1 main::@3 + to:main::@return +main::@4: scope:[main] from + to:main::@1 +main::@return: scope:[main] from main::@2 + return + to:@return +@1: scope:[] from @begin + call main + to:@end +@end: scope:[] from @1 + +Removing empty block main::@2 +Removing empty block main::@4 +PROCEDURE MODIFY VARIABLE ANALYSIS + +Completing Phi functions... + +CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + (byte*) main::screen#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024 + (byte*) main::NULL#0 ← ((byte*)) (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte*) main::rem#0 ← ((byte*)) (byte/word/signed word/dword/signed dword) 255 + (boolean~) main::$0 ← (byte*) main::rem#0 != (byte*) main::NULL#0 + if((boolean~) main::$0) goto main::@1 + to:main::@3 +main::@1: scope:[main] from main + (byte*) main::screen#1 ← phi( main/(byte*) main::screen#0 ) + *((byte*) main::screen#1 + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '*' + to:main::@return +main::@3: scope:[main] from main + (byte*) main::screen#2 ← phi( main/(byte*) main::screen#0 ) + *((byte*) main::screen#2 + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '.' + to:main::@return +main::@return: scope:[main] from main::@1 main::@3 + return + to:@return +@1: scope:[] from @begin + call main param-assignment + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(void()) main() +(boolean~) main::$0 +(label) main::@1 +(label) main::@3 +(label) main::@return +(byte*) main::NULL +(byte*) main::NULL#0 +(byte*) main::rem +(byte*) main::rem#0 +(byte*) main::screen +(byte*) main::screen#0 +(byte*) main::screen#1 +(byte*) main::screen#2 + +OPTIMIZING CONTROL FLOW GRAPH +Culled Empty Block (label) @2 +Succesful SSA optimization Pass2CullEmptyBlocks +Alias (byte*) main::screen#0 = (byte*) main::screen#1 (byte*) main::screen#2 +Succesful SSA optimization Pass2AliasElimination +Simple Condition (boolean~) main::$0 if((byte*) main::rem#0!=(byte*) main::NULL#0) goto main::@1 +Succesful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte*) main::screen#0 = ((byte*))1024 +Constant (const byte*) main::NULL#0 = ((byte*))0 +Constant (const byte*) main::rem#0 = ((byte*))255 +Succesful SSA optimization Pass2ConstantIdentification +Consolidated array index constant in *(main::screen#0+0) +Consolidated array index constant in *(main::screen#0+0) +Succesful SSA optimization Pass2ConstantAdditionElimination +if() condition always true - replacing block destination if((const byte*) main::rem#0!=(const byte*) main::NULL#0) goto main::@1 +Succesful SSA optimization Pass2ConstantIfs +Eliminating unused constant (const byte*) main::NULL#0 +Eliminating unused constant (const byte*) main::rem#0 +Succesful SSA optimization PassNEliminateUnusedVars +Removing unused block main::@3 +Succesful SSA optimization Pass2EliminateUnusedBlocks +OPTIMIZING CONTROL FLOW GRAPH +Block Sequence Planned @begin @1 @end main main::@1 main::@return +Block Sequence Planned @begin @1 @end main main::@1 main::@return +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to main:2 + +Propagating live ranges... +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Block Sequence Planned @begin @1 @end main main::@1 main::@return +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Propagating live ranges... + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@1 +@1: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @1 + [3] phi() [ ] ( ) +main: scope:[main] from @1 + [4] phi() [ ] ( main:2 [ ] ) + to:main::@1 +main::@1: scope:[main] from main + [5] *((const byte*) main::screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '*' [ ] ( main:2 [ ] ) + to:main::@return +main::@return: scope:[main] from main::@1 + [6] return [ ] ( main:2 [ ] ) + to:@return + +DOMINATORS +@begin dominated by @begin +@1 dominated by @1 @begin +@end dominated by @1 @begin @end +main dominated by @1 @begin main +main::@1 dominated by @1 @begin main::@1 main +main::@return dominated by main::@return @1 @begin main::@1 main + +NATURAL LOOPS + +NATURAL LOOPS WITH DEPTH +Found 0 loops in scope [] +Found 0 loops in scope [main] + + +VARIABLE REGISTER WEIGHTS +(void()) main() +(byte*) main::NULL +(byte*) main::rem +(byte*) main::screen + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG4 @1 +b1: +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + .label screen = $400 + jmp b1 + //SEG10 main::@1 + b1: + //SEG11 [5] *((const byte*) main::screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '*' [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2 + lda #'*' + sta screen+0 + jmp breturn + //SEG12 main::@return + breturn: + //SEG13 [6] return [ ] ( main:2 [ ] ) + rts +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [5] *((const byte*) main::screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '*' [ ] ( main:2 [ ] ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [] + +Uplifting [main] best 57 combination +Uplifting [] best 57 combination + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG4 @1 +b1: +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + .label screen = $400 + jmp b1 + //SEG10 main::@1 + b1: + //SEG11 [5] *((const byte*) main::screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '*' [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2 + lda #'*' + sta screen+0 + jmp breturn + //SEG12 main::@return + breturn: + //SEG13 [6] return [ ] ( main:2 [ ] ) + rts +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction bbegin: +Removing instruction b1_from_bbegin: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction b1: +Removing instruction bend: +Removing instruction b1: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(byte*) main::NULL +(byte*) main::rem +(byte*) main::screen +(const byte*) main::screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024 + + + +FINAL ASSEMBLER +Score: 18 + +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +//SEG3 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG4 @1 +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @1 to main [phi:@1->main] + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +//SEG8 @end +//SEG9 main +main: { + .label screen = $400 + //SEG10 main::@1 + //SEG11 [5] *((const byte*) main::screen#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) '*' [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuc2 + lda #'*' + sta screen+0 + //SEG12 main::@return + //SEG13 [6] return [ ] ( main:2 [ ] ) + rts +} + diff --git a/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.sym b/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.sym new file mode 100644 index 000000000..2a79604cd --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/const-pointer.sym @@ -0,0 +1,11 @@ +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@return +(byte*) main::NULL +(byte*) main::rem +(byte*) main::screen +(const byte*) main::screen#0 screen = ((byte*))(word/signed word/dword/signed dword) 1024 +