From f67c2712d3a97f44e9d9972cdad3653cdfd80243 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Fri, 14 May 2021 00:01:58 +0200 Subject: [PATCH] Fixed support for address-of on arrays. Closes #662 --- .../kickc/passes/Pass1AddressOfHandling.java | 3 + .../kickc/test/TestProgramsFast.java | 5 + src/test/kc/npe-problem-0.c | 10 + src/test/ref/npe-problem-0.asm | 22 ++ src/test/ref/npe-problem-0.cfg | 9 + src/test/ref/npe-problem-0.log | 215 ++++++++++++++++++ src/test/ref/npe-problem-0.sym | 5 + 7 files changed, 269 insertions(+) create mode 100644 src/test/kc/npe-problem-0.c create mode 100644 src/test/ref/npe-problem-0.asm create mode 100644 src/test/ref/npe-problem-0.cfg create mode 100644 src/test/ref/npe-problem-0.log create mode 100644 src/test/ref/npe-problem-0.sym diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1AddressOfHandling.java b/src/main/java/dk/camelot64/kickc/passes/Pass1AddressOfHandling.java index a6f90d401..bd54b72d3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1AddressOfHandling.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1AddressOfHandling.java @@ -59,6 +59,9 @@ public class Pass1AddressOfHandling extends Pass2SsaOptimization { } private void updateAddressOfVariable(Variable variable, String stmtStr) { + if(variable.getArraySpec()!=null) + return; + if(variable.getType() instanceof SymbolTypeStruct) { variable.setKind(Variable.Kind.LOAD_STORE); SymbolType typeQualified = variable.getType().getQualified(true, variable.getType().isNomodify()); diff --git a/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java b/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java index efcf2231f..d2a48d2f9 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java +++ b/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java @@ -9,6 +9,11 @@ import java.io.IOException; */ public class TestProgramsFast extends TestPrograms { + @Test + public void testNpeProblem0() throws IOException { + compileAndCompare("npe-problem-0.c"); + } + @Test public void testProcedureDeclare11() throws IOException { compileAndCompare("procedure-declare-11.c"); diff --git a/src/test/kc/npe-problem-0.c b/src/test/kc/npe-problem-0.c new file mode 100644 index 000000000..d37cd6e54 --- /dev/null +++ b/src/test/kc/npe-problem-0.c @@ -0,0 +1,10 @@ + +unsigned char bram[100]; +unsigned char *bram_base = (unsigned char*)&bram; + +char * const SCREEN = (char*)0x0400; + +void main() { + SCREEN[0] = *bram_base++; + SCREEN[1] = *bram_base++; +} \ No newline at end of file diff --git a/src/test/ref/npe-problem-0.asm b/src/test/ref/npe-problem-0.asm new file mode 100644 index 000000000..75a0522ac --- /dev/null +++ b/src/test/ref/npe-problem-0.asm @@ -0,0 +1,22 @@ + // Commodore 64 PRG executable file +.file [name="npe-problem-0.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) + .label SCREEN = $400 +.segment Code +main: { + // SCREEN[0] = *bram_base++ + lda bram + sta SCREEN + // SCREEN[1] = *bram_base++ + lda bram+1 + sta SCREEN+1 + // } + rts +} +.segment Data + bram: .fill $64, 0 diff --git a/src/test/ref/npe-problem-0.cfg b/src/test/ref/npe-problem-0.cfg new file mode 100644 index 000000000..e7aacb373 --- /dev/null +++ b/src/test/ref/npe-problem-0.cfg @@ -0,0 +1,9 @@ + +void main() +main: scope:[main] from + [0] *SCREEN = *((byte*)&bram) + [1] *(SCREEN+1) = *(++(byte*)&bram) + to:main::@return +main::@return: scope:[main] from main + [2] return + to:@return diff --git a/src/test/ref/npe-problem-0.log b/src/test/ref/npe-problem-0.log new file mode 100644 index 000000000..812b6809c --- /dev/null +++ b/src/test/ref/npe-problem-0.log @@ -0,0 +1,215 @@ +Inlined call call __init + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start::@1 + bram_base#6 = phi( __start::@1/bram_base#10 ) + SCREEN[0] = *bram_base#6 + bram_base#0 = ++ bram_base#6 + SCREEN[1] = *bram_base#0 + bram_base#1 = ++ bram_base#0 + to:main::@return +main::@return: scope:[main] from main + bram_base#7 = phi( main/bram_base#1 ) + bram_base#2 = bram_base#7 + return + to:@return + +void __start() +__start: scope:[__start] from + to:__start::__init1 +__start::__init1: scope:[__start] from __start + bram_base#3 = (byte*)&bram + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + bram_base#10 = phi( __start::__init1/bram_base#3 ) + call main + to:__start::@2 +__start::@2: scope:[__start] from __start::@1 + bram_base#8 = phi( __start::@1/bram_base#2 ) + bram_base#4 = bram_base#8 + to:__start::@return +__start::@return: scope:[__start] from __start::@2 + bram_base#9 = phi( __start::@2/bram_base#4 ) + bram_base#5 = bram_base#9 + return + to:@return + +SYMBOL TABLE SSA +constant byte* const SCREEN = (byte*)$400 +void __start() +constant byte* bram[$64] = { fill( $64, 0) } +byte* bram_base +byte* bram_base#0 +byte* bram_base#1 +byte* bram_base#10 +byte* bram_base#2 +byte* bram_base#3 +byte* bram_base#4 +byte* bram_base#5 +byte* bram_base#6 +byte* bram_base#7 +byte* bram_base#8 +byte* bram_base#9 +void main() + +Adding number conversion cast (unumber) 0 in SCREEN[0] = *bram_base#6 +Adding number conversion cast (unumber) 1 in SCREEN[1] = *bram_base#0 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast 0 +Simplifying constant integer cast 1 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias bram_base#1 = bram_base#7 bram_base#2 +Alias bram_base#10 = bram_base#3 +Alias bram_base#4 = bram_base#8 bram_base#9 bram_base#5 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values bram_base#6 bram_base#10 +Identical Phi Values bram_base#4 bram_base#1 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant bram_base#10 = (byte*)&bram +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN in [1] SCREEN[0] = *bram_base#10 +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused variable bram_base#1 and assignment [3] bram_base#1 = ++ bram_base#0 +Successful SSA optimization PassNEliminateUnusedVars +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::__init1 +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@2 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Constant right-side identified [1] bram_base#0 = ++ bram_base#10 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant bram_base#0 = ++bram_base#10 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings bram_base#10 +Inlining constant with different constant siblings bram_base#0 +Constant inlined bram_base#10 = (byte*)&bram +Constant inlined bram_base#0 = ++(byte*)&bram +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(SCREEN+1) +Successful SSA optimization Pass2ConstantAdditionElimination +Finalized unsigned number type (byte) $64 +Finalized unsigned number type (byte) $64 +Successful SSA optimization PassNFinalizeNumberTypeConversions +CALL GRAPH + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes + +FINAL CONTROL FLOW GRAPH + +void main() +main: scope:[main] from + [0] *SCREEN = *((byte*)&bram) + [1] *(SCREEN+1) = *(++(byte*)&bram) + to:main::@return +main::@return: scope:[main] from main + [2] return + to:@return + + +VARIABLE REGISTER WEIGHTS +byte* bram_base +void main() + +Initial phi equivalence classes +Complete equivalence classes +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [0] *SCREEN = *((byte*)&bram) [ ] ( [ ] { } ) always clobbers reg byte a +Statement [1] *(SCREEN+1) = *(++(byte*)&bram) [ ] ( [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [] + +Uplifting [main] best 25 combination +Uplifting [] best 25 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments + // Upstart + // Commodore 64 PRG executable file +.file [name="npe-problem-0.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 + .label SCREEN = $400 +.segment Code + // main +main: { + // [0] *SCREEN = *((byte*)&bram) -- _deref_pbuc1=_deref_pbuc2 + lda bram + sta SCREEN + // [1] *(SCREEN+1) = *(++(byte*)&bram) -- _deref_pbuc1=_deref_pbuc2 + lda bram+1 + sta SCREEN+1 + jmp __breturn + // main::@return + __breturn: + // [2] return + rts +} + // File Data +.segment Data + bram: .fill $64, 0 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +constant byte* const SCREEN = (byte*) 1024 +constant byte* bram[$64] = { fill( $64, 0) } +byte* bram_base +void main() + + + +FINAL ASSEMBLER +Score: 22 + + // File Comments + // Upstart + // Commodore 64 PRG executable file +.file [name="npe-problem-0.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 + .label SCREEN = $400 +.segment Code + // main +main: { + // SCREEN[0] = *bram_base++ + // [0] *SCREEN = *((byte*)&bram) -- _deref_pbuc1=_deref_pbuc2 + lda bram + sta SCREEN + // SCREEN[1] = *bram_base++ + // [1] *(SCREEN+1) = *(++(byte*)&bram) -- _deref_pbuc1=_deref_pbuc2 + lda bram+1 + sta SCREEN+1 + // main::@return + // } + // [2] return + rts +} + // File Data +.segment Data + bram: .fill $64, 0 + diff --git a/src/test/ref/npe-problem-0.sym b/src/test/ref/npe-problem-0.sym new file mode 100644 index 000000000..f7c3fab46 --- /dev/null +++ b/src/test/ref/npe-problem-0.sym @@ -0,0 +1,5 @@ +constant byte* const SCREEN = (byte*) 1024 +constant byte* bram[$64] = { fill( $64, 0) } +byte* bram_base +void main() +