From f696f8db18324a54ea219172318ea0cee1d6c95b Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Tue, 24 Sep 2019 08:55:06 +0200 Subject: [PATCH] Added test declaring a memory-variables. #328 --- .../camelot64/kickc/model/symbols/Scope.java | 4 +- .../Pass0GenerateStatementSequence.java | 4 +- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/declared-memory-var-0.kc | 13 + src/test/ref/declared-memory-var-0.asm | 18 + src/test/ref/declared-memory-var-0.cfg | 25 ++ src/test/ref/declared-memory-var-0.log | 408 ++++++++++++++++++ src/test/ref/declared-memory-var-0.sym | 17 + 8 files changed, 491 insertions(+), 3 deletions(-) create mode 100644 src/test/kc/declared-memory-var-0.kc create mode 100644 src/test/ref/declared-memory-var-0.asm create mode 100644 src/test/ref/declared-memory-var-0.cfg create mode 100644 src/test/ref/declared-memory-var-0.log create mode 100644 src/test/ref/declared-memory-var-0.sym diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java index c3d74bdaf..923735e0a 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java @@ -347,7 +347,9 @@ public abstract class Scope implements Symbol, Serializable { if(asmName != null) { res.append(" " + asmName); } - + if(symVar.getStorageStrategy().equals(SymbolVariable.StorageStrategy.MEMORY)) { + res.append(" memory"); + } Registers.Register declRegister = symVar.getDeclaredRegister(); if(declRegister != null) { res.append(" !" + declRegister); diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 3648dd7b8..e86eafdf3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -837,12 +837,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor@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: { + .label i = 3 + // [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z i + // [5] phi (byte) idx#5 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta.z idx + jmp b1 + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) idx#5 = (byte) idx#2 [phi:main::@1->main::@1#1] -- register_copy + jmp b1 + // main::@1 + b1: + // [6] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte) idx#5 -- pbuc1_derefidx_vbuz1=vbuz2 + lda.z idx + ldy.z i + sta SCREEN,y + // [7] (byte) idx#2 ← (byte) idx#5 + (byte) main::i#2 -- vbuz1=vbuz1_plus_vbuz2 + lda.z idx + clc + adc.z i + sta.z idx + // [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1 + inc.z i + // [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #6 + cmp.z i + bne b1_from_b1 + jmp breturn + // main::@return + breturn: + // [10] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [7] (byte) idx#2 ← (byte) idx#5 + (byte) main::i#2 [ main::i#2 idx#2 ] ( main:2 [ main::i#2 idx#2 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ main::i#2 main::i#1 ] +Statement [7] (byte) idx#2 ← (byte) idx#5 + (byte) main::i#2 [ main::i#2 idx#2 ] ( main:2 [ main::i#2 idx#2 ] ) always clobbers reg byte a +Potential registers zp ZP_BYTE:2 [ idx#5 idx#2 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_BYTE:3 [ main::i#2 main::i#1 ] : zp ZP_BYTE:3 , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 31.17: zp ZP_BYTE:3 [ main::i#2 main::i#1 ] +Uplift Scope [] 23.83: zp ZP_BYTE:2 [ idx#5 idx#2 ] + +Uplifting [main] best 423 combination reg byte x [ main::i#2 main::i#1 ] +Uplifting [] best 343 combination reg byte a [ idx#5 idx#2 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store) + // Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @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] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + // [5] phi (byte) idx#5 = (byte) 0 [phi:main->main::@1#1] -- vbuaa=vbuc1 + lda #0 + jmp b1 + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + b1_from_b1: + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) idx#5 = (byte) idx#2 [phi:main::@1->main::@1#1] -- register_copy + jmp b1 + // main::@1 + b1: + // [6] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte) idx#5 -- pbuc1_derefidx_vbuxx=vbuaa + sta SCREEN,x + // [7] (byte) idx#2 ← (byte) idx#5 + (byte) main::i#2 -- vbuaa=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + // [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + inx + // [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #6 + bne b1_from_b1 + jmp breturn + // main::@return + breturn: + // [10] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing instruction lda #0 with TXA +Replacing label b1_from_b1 with b1 +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Removing instruction b1_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp b1 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = (byte*) 1024 +(byte) idx memory +(byte) idx#2 memory reg byte a 7.333333333333333 +(byte) idx#5 memory reg byte a 16.5 +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 14.666666666666666 + +reg byte a [ idx#5 idx#2 ] +reg byte x [ main::i#2 main::i#1 ] + + +FINAL ASSEMBLER +Score: 241 + + // File Comments +// Test declaring a variable as "memory", meaning it will be stored in memory and accessed through an implicit pointer (using load/store) + // Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + // @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: { + // [5] phi from main to main::@1 [phi:main->main::@1] + // [5] phi (byte) main::i#2 = (byte) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1 + ldx #0 + // [5] phi (byte) idx#5 = (byte) 0 [phi:main->main::@1#1] -- vbuaa=vbuc1 + txa + // [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + // [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy + // [5] phi (byte) idx#5 = (byte) idx#2 [phi:main::@1->main::@1#1] -- register_copy + // main::@1 + b1: + // SCREEN[i] = idx + // [6] *((const byte*) SCREEN#0 + (byte) main::i#2) ← (byte) idx#5 -- pbuc1_derefidx_vbuxx=vbuaa + sta SCREEN,x + // idx +=i + // [7] (byte) idx#2 ← (byte) idx#5 + (byte) main::i#2 -- vbuaa=vbuaa_plus_vbuxx + stx.z $ff + clc + adc.z $ff + // for( char i: 0..5 ) + // [8] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx + inx + // [9] if((byte) main::i#1!=(byte) 6) goto main::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #6 + bne b1 + // main::@return + // } + // [10] return + rts +} + // File Data + diff --git a/src/test/ref/declared-memory-var-0.sym b/src/test/ref/declared-memory-var-0.sym new file mode 100644 index 000000000..47d9a716f --- /dev/null +++ b/src/test/ref/declared-memory-var-0.sym @@ -0,0 +1,17 @@ +(label) @1 +(label) @begin +(label) @end +(byte*) SCREEN +(const byte*) SCREEN#0 SCREEN = (byte*) 1024 +(byte) idx memory +(byte) idx#2 memory reg byte a 7.333333333333333 +(byte) idx#5 memory reg byte a 16.5 +(void()) main() +(label) main::@1 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 14.666666666666666 + +reg byte a [ idx#5 idx#2 ] +reg byte x [ main::i#2 main::i#1 ]