From 7a4d3fff47955bc501f8f8c468b7276cbecf9e2d Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Mon, 3 Jun 2019 01:51:25 +0200 Subject: [PATCH] New type system fixed loHhi-operator on constant values. Closes #95 --- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/operator-lohi-problem-1.kc | 13 + src/test/ref/operator-lohi-problem-1.asm | 17 + src/test/ref/operator-lohi-problem-1.cfg | 16 + src/test/ref/operator-lohi-problem-1.log | 313 ++++++++++++++++++ src/test/ref/operator-lohi-problem-1.sym | 1 + 6 files changed, 365 insertions(+) create mode 100644 src/test/kc/operator-lohi-problem-1.kc create mode 100644 src/test/ref/operator-lohi-problem-1.asm create mode 100644 src/test/ref/operator-lohi-problem-1.cfg create mode 100644 src/test/ref/operator-lohi-problem-1.log create mode 100644 src/test/ref/operator-lohi-problem-1.sym diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 2daed0349..dc84fee0a 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -1407,6 +1407,11 @@ public class TestPrograms { compileAndCompare("loop-problem2"); } + @Test + public void testOperatorLoHiProblem1() throws IOException, URISyntaxException { + compileAndCompare("operator-lohi-problem-1"); + } + @Test public void testOperatorLoHiProblem() throws IOException, URISyntaxException { compileAndCompare("operator-lohi-problem"); diff --git a/src/test/kc/operator-lohi-problem-1.kc b/src/test/kc/operator-lohi-problem-1.kc new file mode 100644 index 000000000..b38a21a4d --- /dev/null +++ b/src/test/kc/operator-lohi-problem-1.kc @@ -0,0 +1,13 @@ +// Illustrates problem with constant evaluation of lo/hi-operator +// $20000 /$400 results in a byte value - confusing the lo/hi-evaluation +// which currently relies on getting the type from the literal value. +// A fix could be adding support for "declared" types for constant literal values +// - enabling the lo/hi to know that their operand is a word (from the cast). + +const dword DVAL = $20000; +const byte* SCREEN = $400; + +void main() { + SCREEN[0] = <(word)(DVAL/$400); + SCREEN[1] = >(word)(DVAL/$400); +} \ No newline at end of file diff --git a/src/test/ref/operator-lohi-problem-1.asm b/src/test/ref/operator-lohi-problem-1.asm new file mode 100644 index 000000000..02ecea630 --- /dev/null +++ b/src/test/ref/operator-lohi-problem-1.asm @@ -0,0 +1,17 @@ +// Illustrates problem with constant evaluation of lo/hi-operator +// $20000 /$400 results in a byte value - confusing the lo/hi-evaluation +// which currently relies on getting the type from the literal value. +// A fix could be adding support for "declared" types for constant literal values +// - enabling the lo/hi to know that their operand is a word (from the cast). +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const DVAL = $20000 + .label SCREEN = $400 +main: { + lda # (word~) main::$4 + *((byte*) SCREEN#0 + (number) 1) ← (byte~) main::$5 + to:main::@return +main::@return: scope:[main] from main + return + to:@return +@1: scope:[] from @begin + call main + to:@2 +@2: scope:[] from @1 + to:@end +@end: scope:[] from @2 + +SYMBOL TABLE SSA +(label) @1 +(label) @2 +(label) @begin +(label) @end +(dword) DVAL +(dword) DVAL#0 +(byte*) SCREEN +(byte*) SCREEN#0 +(void()) main() +(number~) main::$0 +(word~) main::$1 +(byte~) main::$2 +(number~) main::$3 +(word~) main::$4 +(byte~) main::$5 +(label) main::@return + +Adding number conversion cast (unumber) $20000 in (dword) DVAL#0 ← (number) $20000 +Adding number conversion cast (unumber) $400 in (number~) main::$0 ← (dword) DVAL#0 / (number) $400 +Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← (dword) DVAL#0 / (unumber)(number) $400 +Adding number conversion cast (unumber) 0 in *((byte*) SCREEN#0 + (number) 0) ← (byte~) main::$2 +Adding number conversion cast (unumber) $400 in (number~) main::$3 ← (dword) DVAL#0 / (number) $400 +Adding number conversion cast (unumber) main::$3 in (number~) main::$3 ← (dword) DVAL#0 / (unumber)(number) $400 +Adding number conversion cast (unumber) 1 in *((byte*) SCREEN#0 + (number) 1) ← (byte~) main::$5 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (dword) DVAL#0 ← (unumber)(number) $20000 +Inlining cast (byte*) SCREEN#0 ← (byte*)(number) $400 +Inlining cast (word~) main::$1 ← (word)(unumber~) main::$0 +Inlining cast (word~) main::$4 ← (word)(unumber~) main::$3 +Successful SSA optimization Pass2InlineCast +Simplifying constant integer cast $20000 +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast $400 +Simplifying constant integer cast 0 +Simplifying constant integer cast $400 +Simplifying constant integer cast 1 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (dword) $20000 +Finalized unsigned number type (word) $400 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (word) $400 +Finalized unsigned number type (byte) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to dword in (unumber~) main::$0 ← (dword) DVAL#0 / (word) $400 +Inferred type updated to dword in (unumber~) main::$3 ← (dword) DVAL#0 / (word) $400 +Identified duplicate assignment right side [6] (dword~) main::$3 ← (dword) DVAL#0 / (word) $400 +Successful SSA optimization Pass2DuplicateRValueIdentification +Constant (const dword) DVAL#0 = $20000 +Constant (const byte*) SCREEN#0 = (byte*) 1024 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN#0 in [5] *((const byte*) SCREEN#0 + (byte) 0) ← (byte~) main::$2 +Successful SSA optimization PassNSimplifyExpressionWithZero +Alias (dword~) main::$3 = (dword~) main::$0 +Successful SSA optimization Pass2AliasElimination +Constant right-side identified [0] (dword~) main::$3 ← (const dword) DVAL#0 / (word) $400 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const dword) main::$3 = DVAL#0/$400 +Successful SSA optimization Pass2ConstantIdentification +Constant value identified (word)main::$3 in [1] (word~) main::$1 ← (word)(const dword) main::$3 +Constant value identified (word)main::$3 in [5] (word~) main::$4 ← (word)(const dword) main::$3 +Successful SSA optimization Pass2ConstantValues +Constant (const word) main::$1 = (word)main::$3 +Constant (const word) main::$4 = (word)main::$3 +Successful SSA optimization Pass2ConstantIdentification +Constant right-side identified [0] (byte~) main::$2 ← < (const word) main::$1 +Constant right-side identified [2] (byte~) main::$5 ← > (const word) main::$4 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) main::$2 = main::$4 +Successful SSA optimization Pass2ConstantIdentification +Simplifying constant evaluating to zero >(const word) main::$4 in +Successful SSA optimization PassNSimplifyConstantZero +Eliminating unused constant (const word) main::$4 +Successful SSA optimization PassNEliminateUnusedVars +Constant inlined main::$5 = (byte) 0 +Constant inlined main::$3 = (const dword) DVAL#0/(word) $400 +Constant inlined main::$1 = (word)(const dword) DVAL#0/(word) $400 +Constant inlined main::$2 = <(word)(const dword) DVAL#0/(word) $400 +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN#0+1) +Successful SSA optimization Pass2ConstantAdditionElimination +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 @end +CALL GRAPH +Calls in [] to main:2 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @2 +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] *((const byte*) SCREEN#0) ← <(word)(const dword) DVAL#0/(word) $400 + [5] *((const byte*) SCREEN#0+(byte) 1) ← (byte) 0 + to:main::@return +main::@return: scope:[main] from main + [6] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(dword) DVAL +(byte*) SCREEN +(void()) main() + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +//SEG0 File Comments +// Illustrates problem with constant evaluation of lo/hi-operator +// $20000 /$400 results in a byte value - confusing the lo/hi-evaluation +// which currently relies on getting the type from the literal value. +// A fix could be adding support for "declared" types for constant literal values +// - enabling the lo/hi to know that their operand is a word (from the cast). +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const DVAL = $20000 + .label SCREEN = $400 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + //SEG10 [4] *((const byte*) SCREEN#0) ← <(word)(const dword) DVAL#0/(word) $400 -- _deref_pbuc1=vbuc2 + lda #@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main + jsr main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + //SEG10 [4] *((const byte*) SCREEN#0) ← <(word)(const dword) DVAL#0/(word) $400 -- _deref_pbuc1=vbuc2 + lda #@1] +//SEG5 @1 +//SEG6 [2] call main +//SEG7 [3] phi from @1 to @end [phi:@1->@end] +//SEG8 @end +//SEG9 main +main: { + //SEG10 [4] *((const byte*) SCREEN#0) ← <(word)(const dword) DVAL#0/(word) $400 -- _deref_pbuc1=vbuc2 + lda #