From 67a9880b947a989de16a79f330b4b4a465c05b4c Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Wed, 21 Aug 2019 07:06:11 +0200 Subject: [PATCH] Added example of Using function as error does not give an error - instead silently throws away the statement. #276 --- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/function-as-array.kc | 14 + src/test/ref/function-as-array.asm | 14 + src/test/ref/function-as-array.cfg | 22 ++ src/test/ref/function-as-array.log | 307 ++++++++++++++++++ src/test/ref/function-as-array.sym | 11 + 6 files changed, 373 insertions(+) create mode 100644 src/test/kc/function-as-array.kc create mode 100644 src/test/ref/function-as-array.asm create mode 100644 src/test/ref/function-as-array.cfg create mode 100644 src/test/ref/function-as-array.log create mode 100644 src/test/ref/function-as-array.sym diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 3d97d336b..0d3dbfdad 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -36,6 +36,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testFunctionAsArray() throws IOException, URISyntaxException { + compileAndCompare("function-as-array"); + } + @Test public void testCodeAfterReturn1() throws IOException, URISyntaxException { compileAndCompare("code-after-return-1"); diff --git a/src/test/kc/function-as-array.kc b/src/test/kc/function-as-array.kc new file mode 100644 index 000000000..58295b3bc --- /dev/null +++ b/src/test/kc/function-as-array.kc @@ -0,0 +1,14 @@ +// Tests treating a function like an array +// Should produce an error + +void main() { + // Add a ball + new_ball(0); + new_ball[4]; +} + +const char[$10] BALLS; + +void new_ball(char i) { + BALLS[i]++; +} \ No newline at end of file diff --git a/src/test/ref/function-as-array.asm b/src/test/ref/function-as-array.asm new file mode 100644 index 000000000..53c49e7cc --- /dev/null +++ b/src/test/ref/function-as-array.asm @@ -0,0 +1,14 @@ +// Tests treating a function like an array +// Should produce an error +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + jsr new_ball + rts +} +new_ball: { + inc BALLS + rts +} + BALLS: .fill $10, 0 diff --git a/src/test/ref/function-as-array.cfg b/src/test/ref/function-as-array.cfg new file mode 100644 index 000000000..6009b8f9b --- /dev/null +++ b/src/test/ref/function-as-array.cfg @@ -0,0 +1,22 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() +main: scope:[main] from @1 + [4] phi() + [5] call new_ball + to:main::@return +main::@return: scope:[main] from main + [6] return + to:@return +new_ball: scope:[new_ball] from main + [7] *((const byte[$10]) BALLS#0) ← ++ *((const byte[$10]) BALLS#0) + to:new_ball::@return +new_ball::@return: scope:[new_ball] from new_ball + [8] return + to:@return diff --git a/src/test/ref/function-as-array.log b/src/test/ref/function-as-array.log new file mode 100644 index 000000000..1aef7a84e --- /dev/null +++ b/src/test/ref/function-as-array.log @@ -0,0 +1,307 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 +main: scope:[main] from @2 + (byte) new_ball::i#0 ← (number) 0 + call new_ball + to:main::@1 +main::@1: scope:[main] from main + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return +@1: scope:[] from @begin + (byte[$10]) BALLS#0 ← { fill( $10, 0) } + to:@2 +new_ball: scope:[new_ball] from main + (byte) new_ball::i#1 ← phi( main/(byte) new_ball::i#0 ) + *((byte[$10]) BALLS#0 + (byte) new_ball::i#1) ← ++ *((byte[$10]) BALLS#0 + (byte) new_ball::i#1) + to:new_ball::@return +new_ball::@return: scope:[new_ball] from new_ball + return + to:@return +@2: scope:[] from @1 + call main + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @3 +(label) @begin +(label) @end +(byte[$10]) BALLS +(byte[$10]) BALLS#0 +(void()) main() +(label) main::@1 +(label) main::@return +(void()) new_ball((byte) new_ball::i) +(label) new_ball::@return +(byte) new_ball::i +(byte) new_ball::i#0 +(byte) new_ball::i#1 + +Adding number conversion cast (unumber) 0 in (byte) new_ball::i#0 ← (number) 0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (byte) new_ball::i#0 ← (unumber)(number) 0 +Successful SSA optimization Pass2InlineCast +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Identical Phi Values (byte) new_ball::i#1 (byte) new_ball::i#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant right-side identified [3] (byte[$10]) BALLS#0 ← { fill( $10, 0) } +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) new_ball::i#0 = 0 +Constant (const byte[$10]) BALLS#0 = { fill( $10, 0) } +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero BALLS#0 in [5] *((const byte[$10]) BALLS#0 + (const byte) new_ball::i#0) ← ++ *((const byte[$10]) BALLS#0 + (const byte) new_ball::i#0) +Simplifying expression containing zero BALLS#0 in [5] *((const byte[$10]) BALLS#0 + (const byte) new_ball::i#0) ← ++ *((const byte[$10]) BALLS#0) +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused constant (const byte) new_ball::i#0 +Successful SSA optimization PassNEliminateUnusedVars +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 +Adding NOP phi() at start of main::@1 +CALL GRAPH +Calls in [] to main:3 +Calls in [main] to new_ball:7 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @1 +Culled Empty Block (label) @3 +Culled Empty Block (label) main::@1 +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 +Adding NOP phi() at start of main + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() +main: scope:[main] from @1 + [4] phi() + [5] call new_ball + to:main::@return +main::@return: scope:[main] from main + [6] return + to:@return +new_ball: scope:[new_ball] from main + [7] *((const byte[$10]) BALLS#0) ← ++ *((const byte[$10]) BALLS#0) + to:new_ball::@return +new_ball::@return: scope:[new_ball] from new_ball + [8] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte[$10]) BALLS +(void()) main() +(void()) new_ball((byte) new_ball::i) +(byte) new_ball::i + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +Target platform is c64basic + // File Comments +// Tests treating a function like an array +// Should produce an error + // Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + // Global Constants & labels + // @begin +bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 + // @1 +b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + // [5] call new_ball + jsr new_ball + jmp breturn + // main::@return + breturn: + // [6] return + rts +} + // new_ball +new_ball: { + // [7] *((const byte[$10]) BALLS#0) ← ++ *((const byte[$10]) BALLS#0) -- _deref_pbuc1=_inc__deref_pbuc1 + inc BALLS + jmp breturn + // new_ball::@return + breturn: + // [8] return + rts +} + // File Data + BALLS: .fill $10, 0 + +REGISTER UPLIFT POTENTIAL REGISTERS + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [new_ball] +Uplift Scope [] + +Uplifting [main] best 42 combination +Uplifting [new_ball] best 42 combination +Uplifting [] best 42 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Tests treating a function like an array +// Should produce an error + // Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + // Global Constants & labels + // @begin +bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 + // @1 +b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + // [5] call new_ball + jsr new_ball + jmp breturn + // main::@return + breturn: + // [6] return + rts +} + // new_ball +new_ball: { + // [7] *((const byte[$10]) BALLS#0) ← ++ *((const byte[$10]) BALLS#0) -- _deref_pbuc1=_inc__deref_pbuc1 + inc BALLS + jmp breturn + // new_ball::@return + breturn: + // [8] return + rts +} + // File Data + BALLS: .fill $10, 0 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp breturn +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +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 +(byte[$10]) BALLS +(const byte[$10]) BALLS#0 BALLS = { fill( $10, 0) } +(void()) main() +(label) main::@return +(void()) new_ball((byte) new_ball::i) +(label) new_ball::@return +(byte) new_ball::i + + + +FINAL ASSEMBLER +Score: 24 + + // File Comments +// Tests treating a function like an array +// Should produce an error + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + // @begin + // [1] phi from @begin to @1 [phi:@begin->@1] + // @1 + // [2] call main + // [4] phi from @1 to main [phi:@1->main] + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + // new_ball(0) + // [5] call new_ball + jsr new_ball + // main::@return + // } + // [6] return + rts +} + // new_ball +new_ball: { + // BALLS[i]++; + // [7] *((const byte[$10]) BALLS#0) ← ++ *((const byte[$10]) BALLS#0) -- _deref_pbuc1=_inc__deref_pbuc1 + inc BALLS + // new_ball::@return + // } + // [8] return + rts +} + // File Data + BALLS: .fill $10, 0 + diff --git a/src/test/ref/function-as-array.sym b/src/test/ref/function-as-array.sym new file mode 100644 index 000000000..076b59bdc --- /dev/null +++ b/src/test/ref/function-as-array.sym @@ -0,0 +1,11 @@ +(label) @1 +(label) @begin +(label) @end +(byte[$10]) BALLS +(const byte[$10]) BALLS#0 BALLS = { fill( $10, 0) } +(void()) main() +(label) main::@return +(void()) new_ball((byte) new_ball::i) +(label) new_ball::@return +(byte) new_ball::i +