From 08d268f130edb564be2245c8f2835826051facfd Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Thu, 26 Dec 2019 00:57:19 +0100 Subject: [PATCH] Added some hardcoded address parameter tests. --- .../camelot64/kickc/model/symbols/Scope.java | 3 +- .../kickc/passes/Pass3AssertConstants.java | 23 +- .../kickc/passes/Pass4CodeGeneration.java | 5 +- .../dk/camelot64/kickc/test/TestPrograms.java | 15 + src/test/kc/address-5.kc | 21 + src/test/kc/address-6.kc | 21 + src/test/kc/register-0.kc | 22 + src/test/ref/address-5.asm | 33 ++ src/test/ref/address-5.cfg | 37 ++ src/test/ref/address-5.log | 421 ++++++++++++++++ src/test/ref/address-5.sym | 16 + src/test/ref/address-6.asm | 33 ++ src/test/ref/address-6.cfg | 37 ++ src/test/ref/address-6.log | 421 ++++++++++++++++ src/test/ref/address-6.sym | 16 + src/test/ref/register-0.asm | 30 ++ src/test/ref/register-0.cfg | 39 ++ src/test/ref/register-0.log | 474 ++++++++++++++++++ src/test/ref/register-0.sym | 17 + 19 files changed, 1678 insertions(+), 6 deletions(-) create mode 100644 src/test/kc/address-5.kc create mode 100644 src/test/kc/address-6.kc create mode 100644 src/test/kc/register-0.kc create mode 100644 src/test/ref/address-5.asm create mode 100644 src/test/ref/address-5.cfg create mode 100644 src/test/ref/address-5.log create mode 100644 src/test/ref/address-5.sym create mode 100644 src/test/ref/address-6.asm create mode 100644 src/test/ref/address-6.cfg create mode 100644 src/test/ref/address-6.log create mode 100644 src/test/ref/address-6.sym create mode 100644 src/test/ref/register-0.asm create mode 100644 src/test/ref/register-0.cfg create mode 100644 src/test/ref/register-0.log create mode 100644 src/test/ref/register-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 3b7533f17..6bb5eed90 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java @@ -169,7 +169,8 @@ public abstract class Scope implements Symbol, Serializable { public Variable getVariable(String name) { Variable symbol = (Variable) getSymbol(name); - if(symbol!=null && !symbol.isVariable()) throw new InternalError("Symbol is not a variable! "+symbol.toString()); + if(symbol!=null && !symbol.isVariable()) + throw new InternalError("Symbol is not a variable! "+symbol.toString()); return symbol; } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertConstants.java b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertConstants.java index 1faef40c6..347457bcb 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass3AssertConstants.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass3AssertConstants.java @@ -6,7 +6,13 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.Statement; import dk.camelot64.kickc.model.statements.StatementAsm; import dk.camelot64.kickc.model.statements.StatementKickAsm; -import dk.camelot64.kickc.model.values.*; +import dk.camelot64.kickc.model.symbols.Procedure; +import dk.camelot64.kickc.model.symbols.Symbol; +import dk.camelot64.kickc.model.symbols.Variable; +import dk.camelot64.kickc.model.values.ConstantRef; +import dk.camelot64.kickc.model.values.ConstantValue; +import dk.camelot64.kickc.model.values.RValue; +import dk.camelot64.kickc.model.values.SymbolRef; import java.util.List; import java.util.Map; @@ -39,7 +45,7 @@ public class Pass3AssertConstants extends Pass2SsaAssertion { throw new CompileError("Error! KickAssembler bytes is not constant " + bytes.toString(), statement); } RValue cycles = ((StatementKickAsm) statement).getCycles(); - if(cycles!= null && !(cycles instanceof ConstantValue)) { + if(cycles != null && !(cycles instanceof ConstantValue)) { throw new CompileError("Error! KickAssembler cycles is not constant " + cycles.toString(), statement); } } else if(statement instanceof StatementAsm) { @@ -47,9 +53,18 @@ public class Pass3AssertConstants extends Pass2SsaAssertion { Map referenced = statementAsm.getReferenced(); for(String label : referenced.keySet()) { SymbolRef symbolRef = referenced.get(label); - if(!(symbolRef instanceof ConstantRef) && !(symbolRef instanceof ProcedureRef)) { + Symbol symbol = getScope().getSymbol(symbolRef); + if(symbol instanceof Procedure) + // Referencing procedures are fine! + continue; + else if(symbol instanceof Variable && ((Variable) symbol).isKindConstant()) + // Referencing constants are fine! + continue; + else if(symbol instanceof Variable && ((Variable) symbol).isKindLoadStore()) + // Referencing load/store is fine! + continue; + else throw new CompileError("Error! Inline ASM reference is not constant " + label, statement); - } } } else if(statement instanceof StatementKickAsm) { StatementKickAsm statementAsm = (StatementKickAsm) statement; diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 7b0364747..2a9712759 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -276,7 +276,10 @@ public class Pass4CodeGeneration { signature.append(param.getType().getTypeName()).append(" "); if(allocation instanceof Registers.RegisterZpMem) { Registers.RegisterZpMem registerZp = (Registers.RegisterZpMem) allocation; - signature.append("zeropage(").append(AsmFormat.getAsmNumber(registerZp.getZp())).append(")"); + signature.append("zp(").append(AsmFormat.getAsmNumber(registerZp.getZp())).append(")"); + } else if(allocation instanceof Registers.RegisterMainMem) { + Registers.RegisterMainMem registerMainMem = (Registers.RegisterMainMem) allocation; + signature.append("mem(").append(AsmFormat.getAsmNumber(registerMainMem.getAddress())).append(")"); } else if(allocation instanceof Registers.RegisterAByte) { signature.append("register(A)"); } else if(allocation instanceof Registers.RegisterXByte) { diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 7db205b64..c1e348468 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -37,6 +37,21 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testRegister0() throws IOException, URISyntaxException { + compileAndCompare("register-0"); + } + + @Test + public void testAddress6() throws IOException, URISyntaxException { + compileAndCompare("address-6"); + } + + @Test + public void testAddress5() throws IOException, URISyntaxException { + compileAndCompare("address-5"); + } + @Test public void testAddress4() throws IOException, URISyntaxException { compileAndCompare("address-4"); diff --git a/src/test/kc/address-5.kc b/src/test/kc/address-5.kc new file mode 100644 index 000000000..91ca7cece --- /dev/null +++ b/src/test/kc/address-5.kc @@ -0,0 +1,21 @@ +// Test declaring a variable as at a hard-coded address +// zero-page hard-coded address parameter + +void main() { + print('c'); + print('m'); + print('l'); +} + +const char* SCREEN = 0x0400; + +volatile char __address(0x03) idx; + +void print(char __address(0x02) ch) { + asm { + ldx idx + lda ch + sta SCREEN,x + inc idx + } +} diff --git a/src/test/kc/address-6.kc b/src/test/kc/address-6.kc new file mode 100644 index 000000000..13bab1790 --- /dev/null +++ b/src/test/kc/address-6.kc @@ -0,0 +1,21 @@ +// Test declaring a variable as at a hard-coded address +// mainmem-page hard-coded address parameter + +void main() { + print('c'); + print('m'); + print('l'); +} + +const char* SCREEN = 0x0400; + +volatile char __address(0x3000) idx; + +void print(char __address(0x3001) ch) { + asm { + ldx idx + lda ch + sta SCREEN,x + inc idx + } +} diff --git a/src/test/kc/register-0.kc b/src/test/kc/register-0.kc new file mode 100644 index 000000000..f19e86883 --- /dev/null +++ b/src/test/kc/register-0.kc @@ -0,0 +1,22 @@ +// Test declaring a variable as at a hard-coded register +// hard-coded register parameter + +void main() { + print('c'); + print('m'); + print('l'); +} + +const char* SCREEN = 0x0400; + +volatile char __address(0x03) idx; + +void print(char register(A) ch) { + // Force usage of ch + kickasm(uses ch) {{ }} + asm { + ldx idx + sta SCREEN,x + inc idx + } +} diff --git a/src/test/ref/address-5.asm b/src/test/ref/address-5.asm new file mode 100644 index 000000000..3277a648b --- /dev/null +++ b/src/test/ref/address-5.asm @@ -0,0 +1,33 @@ +// Test declaring a variable as at a hard-coded address +// zero-page hard-coded address parameter +.pc = $801 "Basic" +:BasicUpstart(__b1) +.pc = $80d "Program" + .label SCREEN = $400 + .label idx = 3 +__b1: + lda #0 + sta.z idx + jsr main + rts +main: { + lda #'c' + sta.z print.ch + jsr print + lda #'m' + sta.z print.ch + jsr print + lda #'l' + sta.z print.ch + jsr print + rts +} +// print(byte zeropage(2) ch) +print: { + .label ch = 2 + ldx idx + lda ch + sta SCREEN,x + inc idx + rts +} diff --git a/src/test/ref/address-5.cfg b/src/test/ref/address-5.cfg new file mode 100644 index 000000000..bfd51f44a --- /dev/null +++ b/src/test/ref/address-5.cfg @@ -0,0 +1,37 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] (byte) idx ← (byte) 0 + to:@2 +@2: scope:[] from @1 + [2] phi() + [3] call main + to:@end +@end: scope:[] from @2 + [4] phi() + +(void()) main() +main: scope:[main] from @2 + [5] (byte) print::ch ← (byte) 'c' + [6] call print + to:main::@1 +main::@1: scope:[main] from main + [7] (byte) print::ch ← (byte) 'm' + [8] call print + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] (byte) print::ch ← (byte) 'l' + [10] call print + to:main::@return +main::@return: scope:[main] from main::@2 + [11] return + to:@return + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + asm { ldxidx ldach staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + [13] return + to:@return diff --git a/src/test/ref/address-5.log b/src/test/ref/address-5.log new file mode 100644 index 000000000..9588b4b7a --- /dev/null +++ b/src/test/ref/address-5.log @@ -0,0 +1,421 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @2 + (byte) print::ch ← (byte) 'c' + call print + to:main::@1 +main::@1: scope:[main] from main + (byte) print::ch ← (byte) 'm' + call print + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte) print::ch ← (byte) 'l' + call print + to:main::@3 +main::@3: scope:[main] from main::@2 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + (byte) idx ← (byte) 0 + to:@2 + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + asm { ldxidx ldach staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + 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 +(const byte*) SCREEN = (byte*)(number) $400 +(byte) idx loadstore !zp[-1]:3 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch loadstore !zp[-1]:2 + +Simplifying constant pointer cast (byte*) 1024 +Successful SSA optimization PassNCastSimplification +Adding NOP phi() at start of @begin +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::@3 +CALL GRAPH +Calls in [] to main:3 +Calls in [main] to print:7 print:9 print:11 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @3 +Culled Empty Block (label) main::@3 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] (byte) idx ← (byte) 0 + to:@2 +@2: scope:[] from @1 + [2] phi() + [3] call main + to:@end +@end: scope:[] from @2 + [4] phi() + +(void()) main() +main: scope:[main] from @2 + [5] (byte) print::ch ← (byte) 'c' + [6] call print + to:main::@1 +main::@1: scope:[main] from main + [7] (byte) print::ch ← (byte) 'm' + [8] call print + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] (byte) print::ch ← (byte) 'l' + [10] call print + to:main::@return +main::@return: scope:[main] from main::@2 + [11] return + to:@return + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + asm { ldxidx ldach staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + [13] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) idx loadstore !zp[-1]:3 0.2222222222222222 +(void()) main() +(void()) print((byte) print::ch) +(byte) print::ch loadstore !zp[-1]:2 2.0 + +Initial phi equivalence classes +Added variable idx to live range equivalence class [ idx ] +Added variable print::ch to live range equivalence class [ print::ch ] +Complete equivalence classes +[ idx ] +[ print::ch ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Test declaring a variable as at a hard-coded address +// zero-page hard-coded address parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = 3 + // @begin +__bbegin: + jmp __b1 + // @1 +__b1: + // [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [2] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [3] call main + jsr main + // [4] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: + jmp __bend + // @end +__bend: + // main +main: { + // [5] (byte) print::ch ← (byte) 'c' -- vbuz1=vbuc1 + lda #'c' + sta.z print.ch + // [6] call print + jsr print + jmp __b1 + // main::@1 + __b1: + // [7] (byte) print::ch ← (byte) 'm' -- vbuz1=vbuc1 + lda #'m' + sta.z print.ch + // [8] call print + jsr print + jmp __b2 + // main::@2 + __b2: + // [9] (byte) print::ch ← (byte) 'l' -- vbuz1=vbuc1 + lda #'l' + sta.z print.ch + // [10] call print + jsr print + jmp __breturn + // main::@return + __breturn: + // [11] return + rts +} + // print +// print(byte zeropage(2) ch) +print: { + .label ch = 2 + // asm { ldxidx ldach staSCREEN,x incidx } + ldx idx + lda ch + sta SCREEN,x + inc idx + jmp __breturn + // print::@return + __breturn: + // [13] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a +Statement [5] (byte) print::ch ← (byte) 'c' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a +Statement [7] (byte) print::ch ← (byte) 'm' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a +Statement [9] (byte) print::ch ← (byte) 'l' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a +Statement asm { ldxidx ldach staSCREEN,x incidx } always clobbers reg byte a reg byte x +Potential registers zp[1]:3 [ idx ] : zp[1]:3 , +Potential registers zp[1]:2 [ print::ch ] : zp[1]:2 , + +REGISTER UPLIFT SCOPES +Uplift Scope [print] 2: zp[1]:2 [ print::ch ] +Uplift Scope [] 0.22: zp[1]:3 [ idx ] +Uplift Scope [main] + +Uplifting [print] best 123 combination zp[1]:2 [ print::ch ] +Uplifting [] best 123 combination zp[1]:3 [ idx ] +Uplifting [main] best 123 combination +Attempting to uplift remaining variables inzp[1]:2 [ print::ch ] +Uplifting [print] best 123 combination zp[1]:2 [ print::ch ] +Attempting to uplift remaining variables inzp[1]:3 [ idx ] +Uplifting [] best 123 combination zp[1]:3 [ idx ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test declaring a variable as at a hard-coded address +// zero-page hard-coded address parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = 3 + // @begin +__bbegin: + jmp __b1 + // @1 +__b1: + // [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [2] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [3] call main + jsr main + // [4] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: + jmp __bend + // @end +__bend: + // main +main: { + // [5] (byte) print::ch ← (byte) 'c' -- vbuz1=vbuc1 + lda #'c' + sta.z print.ch + // [6] call print + jsr print + jmp __b1 + // main::@1 + __b1: + // [7] (byte) print::ch ← (byte) 'm' -- vbuz1=vbuc1 + lda #'m' + sta.z print.ch + // [8] call print + jsr print + jmp __b2 + // main::@2 + __b2: + // [9] (byte) print::ch ← (byte) 'l' -- vbuz1=vbuc1 + lda #'l' + sta.z print.ch + // [10] call print + jsr print + jmp __breturn + // main::@return + __breturn: + // [11] return + rts +} + // print +// print(byte zeropage(2) ch) +print: { + .label ch = 2 + // asm { ldxidx ldach staSCREEN,x incidx } + ldx idx + lda ch + sta SCREEN,x + inc idx + jmp __breturn + // print::@return + __breturn: + // [13] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 +Removing instruction __bbegin: +Removing instruction __b2_from___b1: +Removing instruction __bend_from___b2: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b2: +Removing instruction __bend: +Removing instruction __b1: +Removing instruction __b2: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Adding RTS to root block +Succesful ASM optimization Pass5AddMainRts + +FINAL SYMBOL TABLE +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte*) SCREEN = (byte*) 1024 +(byte) idx loadstore !zp[-1]:3 zp[1]:3 0.2222222222222222 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch loadstore !zp[-1]:2 zp[1]:2 2.0 + +zp[1]:3 [ idx ] +zp[1]:2 [ print::ch ] + + +FINAL ASSEMBLER +Score: 81 + + // File Comments +// Test declaring a variable as at a hard-coded address +// zero-page hard-coded address parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__b1) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = 3 + // @begin + // @1 +__b1: + // idx + // [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [2] phi from @1 to @2 [phi:@1->@2] + // @2 + // [3] call main + jsr main + rts + // [4] phi from @2 to @end [phi:@2->@end] + // @end + // main +main: { + // print('c') + // [5] (byte) print::ch ← (byte) 'c' -- vbuz1=vbuc1 + lda #'c' + sta.z print.ch + // [6] call print + jsr print + // main::@1 + // print('m') + // [7] (byte) print::ch ← (byte) 'm' -- vbuz1=vbuc1 + lda #'m' + sta.z print.ch + // [8] call print + jsr print + // main::@2 + // print('l') + // [9] (byte) print::ch ← (byte) 'l' -- vbuz1=vbuc1 + lda #'l' + sta.z print.ch + // [10] call print + jsr print + // main::@return + // } + // [11] return + rts +} + // print +// print(byte zeropage(2) ch) +print: { + .label ch = 2 + // asm + // asm { ldxidx ldach staSCREEN,x incidx } + ldx idx + lda ch + sta SCREEN,x + inc idx + // print::@return + // } + // [13] return + rts +} + // File Data + diff --git a/src/test/ref/address-5.sym b/src/test/ref/address-5.sym new file mode 100644 index 000000000..d22044338 --- /dev/null +++ b/src/test/ref/address-5.sym @@ -0,0 +1,16 @@ +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte*) SCREEN = (byte*) 1024 +(byte) idx loadstore !zp[-1]:3 zp[1]:3 0.2222222222222222 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch loadstore !zp[-1]:2 zp[1]:2 2.0 + +zp[1]:3 [ idx ] +zp[1]:2 [ print::ch ] diff --git a/src/test/ref/address-6.asm b/src/test/ref/address-6.asm new file mode 100644 index 000000000..213bcf965 --- /dev/null +++ b/src/test/ref/address-6.asm @@ -0,0 +1,33 @@ +// Test declaring a variable as at a hard-coded address +// mainmem-page hard-coded address parameter +.pc = $801 "Basic" +:BasicUpstart(__b1) +.pc = $80d "Program" + .label SCREEN = $400 + .label idx = $3000 +__b1: + lda #0 + sta idx + jsr main + rts +main: { + lda #'c' + sta print.ch + jsr print + lda #'m' + sta print.ch + jsr print + lda #'l' + sta print.ch + jsr print + rts +} +// print(byte mem($3001) ch) +print: { + .label ch = $3001 + ldx idx + lda ch + sta SCREEN,x + inc idx + rts +} diff --git a/src/test/ref/address-6.cfg b/src/test/ref/address-6.cfg new file mode 100644 index 000000000..bfd51f44a --- /dev/null +++ b/src/test/ref/address-6.cfg @@ -0,0 +1,37 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] (byte) idx ← (byte) 0 + to:@2 +@2: scope:[] from @1 + [2] phi() + [3] call main + to:@end +@end: scope:[] from @2 + [4] phi() + +(void()) main() +main: scope:[main] from @2 + [5] (byte) print::ch ← (byte) 'c' + [6] call print + to:main::@1 +main::@1: scope:[main] from main + [7] (byte) print::ch ← (byte) 'm' + [8] call print + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] (byte) print::ch ← (byte) 'l' + [10] call print + to:main::@return +main::@return: scope:[main] from main::@2 + [11] return + to:@return + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + asm { ldxidx ldach staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + [13] return + to:@return diff --git a/src/test/ref/address-6.log b/src/test/ref/address-6.log new file mode 100644 index 000000000..134be8ae5 --- /dev/null +++ b/src/test/ref/address-6.log @@ -0,0 +1,421 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @2 + (byte) print::ch ← (byte) 'c' + call print + to:main::@1 +main::@1: scope:[main] from main + (byte) print::ch ← (byte) 'm' + call print + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte) print::ch ← (byte) 'l' + call print + to:main::@3 +main::@3: scope:[main] from main::@2 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + (byte) idx ← (byte) 0 + to:@2 + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + asm { ldxidx ldach staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + 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 +(const byte*) SCREEN = (byte*)(number) $400 +(byte) idx loadstore !mem[-1]:12288 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch loadstore !mem[-1]:12289 + +Simplifying constant pointer cast (byte*) 1024 +Successful SSA optimization PassNCastSimplification +Adding NOP phi() at start of @begin +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::@3 +CALL GRAPH +Calls in [] to main:3 +Calls in [main] to print:7 print:9 print:11 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Culled Empty Block (label) @3 +Culled Empty Block (label) main::@3 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] (byte) idx ← (byte) 0 + to:@2 +@2: scope:[] from @1 + [2] phi() + [3] call main + to:@end +@end: scope:[] from @2 + [4] phi() + +(void()) main() +main: scope:[main] from @2 + [5] (byte) print::ch ← (byte) 'c' + [6] call print + to:main::@1 +main::@1: scope:[main] from main + [7] (byte) print::ch ← (byte) 'm' + [8] call print + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] (byte) print::ch ← (byte) 'l' + [10] call print + to:main::@return +main::@return: scope:[main] from main::@2 + [11] return + to:@return + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + asm { ldxidx ldach staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + [13] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) idx loadstore !mem[-1]:12288 0.2222222222222222 +(void()) main() +(void()) print((byte) print::ch) +(byte) print::ch loadstore !mem[-1]:12289 2.0 + +Initial phi equivalence classes +Added variable idx to live range equivalence class [ idx ] +Added variable print::ch to live range equivalence class [ print::ch ] +Complete equivalence classes +[ idx ] +[ print::ch ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Test declaring a variable as at a hard-coded address +// mainmem-page hard-coded address parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = $3000 + // @begin +__bbegin: + jmp __b1 + // @1 +__b1: + // [1] (byte) idx ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta idx + // [2] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [3] call main + jsr main + // [4] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: + jmp __bend + // @end +__bend: + // main +main: { + // [5] (byte) print::ch ← (byte) 'c' -- vbum1=vbuc1 + lda #'c' + sta print.ch + // [6] call print + jsr print + jmp __b1 + // main::@1 + __b1: + // [7] (byte) print::ch ← (byte) 'm' -- vbum1=vbuc1 + lda #'m' + sta print.ch + // [8] call print + jsr print + jmp __b2 + // main::@2 + __b2: + // [9] (byte) print::ch ← (byte) 'l' -- vbum1=vbuc1 + lda #'l' + sta print.ch + // [10] call print + jsr print + jmp __breturn + // main::@return + __breturn: + // [11] return + rts +} + // print +// print(byte mem($3001) ch) +print: { + .label ch = $3001 + // asm { ldxidx ldach staSCREEN,x incidx } + ldx idx + lda ch + sta SCREEN,x + inc idx + jmp __breturn + // print::@return + __breturn: + // [13] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a +Statement [5] (byte) print::ch ← (byte) 'c' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a +Statement [7] (byte) print::ch ← (byte) 'm' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a +Statement [9] (byte) print::ch ← (byte) 'l' [ idx print::ch ] ( main:3 [ idx print::ch ] ) always clobbers reg byte a +Statement asm { ldxidx ldach staSCREEN,x incidx } always clobbers reg byte a reg byte x +Potential registers mem[1]:12288 [ idx ] : mem[1]:12288 , +Potential registers mem[1]:12289 [ print::ch ] : mem[1]:12289 , + +REGISTER UPLIFT SCOPES +Uplift Scope [print] 2: mem[1]:12289 [ print::ch ] +Uplift Scope [] 0.22: mem[1]:12288 [ idx ] +Uplift Scope [main] + +Uplifting [print] best 127 combination mem[1]:12289 [ print::ch ] +Uplifting [] best 127 combination mem[1]:12288 [ idx ] +Uplifting [main] best 127 combination +Attempting to uplift remaining variables inmem[1]:12289 [ print::ch ] +Uplifting [print] best 127 combination mem[1]:12289 [ print::ch ] +Attempting to uplift remaining variables inmem[1]:12288 [ idx ] +Uplifting [] best 127 combination mem[1]:12288 [ idx ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test declaring a variable as at a hard-coded address +// mainmem-page hard-coded address parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = $3000 + // @begin +__bbegin: + jmp __b1 + // @1 +__b1: + // [1] (byte) idx ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta idx + // [2] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [3] call main + jsr main + // [4] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: + jmp __bend + // @end +__bend: + // main +main: { + // [5] (byte) print::ch ← (byte) 'c' -- vbum1=vbuc1 + lda #'c' + sta print.ch + // [6] call print + jsr print + jmp __b1 + // main::@1 + __b1: + // [7] (byte) print::ch ← (byte) 'm' -- vbum1=vbuc1 + lda #'m' + sta print.ch + // [8] call print + jsr print + jmp __b2 + // main::@2 + __b2: + // [9] (byte) print::ch ← (byte) 'l' -- vbum1=vbuc1 + lda #'l' + sta print.ch + // [10] call print + jsr print + jmp __breturn + // main::@return + __breturn: + // [11] return + rts +} + // print +// print(byte mem($3001) ch) +print: { + .label ch = $3001 + // asm { ldxidx ldach staSCREEN,x incidx } + ldx idx + lda ch + sta SCREEN,x + inc idx + jmp __breturn + // print::@return + __breturn: + // [13] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 +Removing instruction __bbegin: +Removing instruction __b2_from___b1: +Removing instruction __bend_from___b2: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b2: +Removing instruction __bend: +Removing instruction __b1: +Removing instruction __b2: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Adding RTS to root block +Succesful ASM optimization Pass5AddMainRts + +FINAL SYMBOL TABLE +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte*) SCREEN = (byte*) 1024 +(byte) idx loadstore !mem[-1]:12288 mem[1]:12288 0.2222222222222222 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch loadstore !mem[-1]:12289 mem[1]:12289 2.0 + +mem[1]:12288 [ idx ] +mem[1]:12289 [ print::ch ] + + +FINAL ASSEMBLER +Score: 85 + + // File Comments +// Test declaring a variable as at a hard-coded address +// mainmem-page hard-coded address parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__b1) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = $3000 + // @begin + // @1 +__b1: + // idx + // [1] (byte) idx ← (byte) 0 -- vbum1=vbuc1 + lda #0 + sta idx + // [2] phi from @1 to @2 [phi:@1->@2] + // @2 + // [3] call main + jsr main + rts + // [4] phi from @2 to @end [phi:@2->@end] + // @end + // main +main: { + // print('c') + // [5] (byte) print::ch ← (byte) 'c' -- vbum1=vbuc1 + lda #'c' + sta print.ch + // [6] call print + jsr print + // main::@1 + // print('m') + // [7] (byte) print::ch ← (byte) 'm' -- vbum1=vbuc1 + lda #'m' + sta print.ch + // [8] call print + jsr print + // main::@2 + // print('l') + // [9] (byte) print::ch ← (byte) 'l' -- vbum1=vbuc1 + lda #'l' + sta print.ch + // [10] call print + jsr print + // main::@return + // } + // [11] return + rts +} + // print +// print(byte mem($3001) ch) +print: { + .label ch = $3001 + // asm + // asm { ldxidx ldach staSCREEN,x incidx } + ldx idx + lda ch + sta SCREEN,x + inc idx + // print::@return + // } + // [13] return + rts +} + // File Data + diff --git a/src/test/ref/address-6.sym b/src/test/ref/address-6.sym new file mode 100644 index 000000000..97e2daeb9 --- /dev/null +++ b/src/test/ref/address-6.sym @@ -0,0 +1,16 @@ +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte*) SCREEN = (byte*) 1024 +(byte) idx loadstore !mem[-1]:12288 mem[1]:12288 0.2222222222222222 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch loadstore !mem[-1]:12289 mem[1]:12289 2.0 + +mem[1]:12288 [ idx ] +mem[1]:12289 [ print::ch ] diff --git a/src/test/ref/register-0.asm b/src/test/ref/register-0.asm new file mode 100644 index 000000000..1c2f799df --- /dev/null +++ b/src/test/ref/register-0.asm @@ -0,0 +1,30 @@ +// Test declaring a variable as at a hard-coded register +// hard-coded register parameter +.pc = $801 "Basic" +:BasicUpstart(__b1) +.pc = $80d "Program" + .label SCREEN = $400 + .label idx = 3 +__b1: + lda #0 + sta.z idx + jsr main + rts +main: { + lda #'c' + jsr print + lda #'m' + jsr print + lda #'l' + jsr print + rts +} +// print(byte register(A) ch) +print: { + // Force usage of ch + + ldx idx + sta SCREEN,x + inc idx + rts +} diff --git a/src/test/ref/register-0.cfg b/src/test/ref/register-0.cfg new file mode 100644 index 000000000..dc24ff2b9 --- /dev/null +++ b/src/test/ref/register-0.cfg @@ -0,0 +1,39 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] (byte) idx ← (byte) 0 + to:@2 +@2: scope:[] from @1 + [2] phi() + [3] call main + to:@end +@end: scope:[] from @2 + [4] phi() + +(void()) main() +main: scope:[main] from @2 + [5] phi() + [6] call print + to:main::@1 +main::@1: scope:[main] from main + [7] phi() + [8] call print + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] phi() + [10] call print + to:main::@return +main::@return: scope:[main] from main::@2 + [11] return + to:@return + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + [12] (byte) print::ch#3 ← phi( main/(byte) 'c' main::@1/(byte) 'm' main::@2/(byte) 'l' ) + kickasm( uses print::ch#3) {{ }} + asm { ldxidx staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + [15] return + to:@return diff --git a/src/test/ref/register-0.log b/src/test/ref/register-0.log new file mode 100644 index 000000000..786473398 --- /dev/null +++ b/src/test/ref/register-0.log @@ -0,0 +1,474 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 + +(void()) main() +main: scope:[main] from @2 + (byte) print::ch#0 ← (byte) 'c' + call print + to:main::@1 +main::@1: scope:[main] from main + (byte) print::ch#1 ← (byte) 'm' + call print + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte) print::ch#2 ← (byte) 'l' + call print + to:main::@3 +main::@3: scope:[main] from main::@2 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + (byte) idx ← (byte) 0 + to:@2 + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + (byte) print::ch#3 ← phi( main/(byte) print::ch#0 main::@1/(byte) print::ch#1 main::@2/(byte) print::ch#2 ) + kickasm( uses print::ch#3) {{ }} + asm { ldxidx staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + 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 +(const byte*) SCREEN = (byte*)(number) $400 +(byte) idx loadstore !zp[-1]:3 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch !reg byte a +(byte) print::ch#0 !reg byte a +(byte) print::ch#1 !reg byte a +(byte) print::ch#2 !reg byte a +(byte) print::ch#3 !reg byte a + +Simplifying constant pointer cast (byte*) 1024 +Successful SSA optimization PassNCastSimplification +Constant (const byte) print::ch#0 = 'c' +Constant (const byte) print::ch#1 = 'm' +Constant (const byte) print::ch#2 = 'l' +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with var siblings (const byte) print::ch#0 +Inlining constant with var siblings (const byte) print::ch#1 +Inlining constant with var siblings (const byte) print::ch#2 +Constant inlined print::ch#2 = (byte) 'l' +Constant inlined print::ch#1 = (byte) 'm' +Constant inlined print::ch#0 = (byte) 'c' +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of @begin +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 +Adding NOP phi() at start of main::@2 +Adding NOP phi() at start of main::@3 +CALL GRAPH +Calls in [] to main:3 +Calls in [main] to print:7 print:9 print:11 + +Created 1 initial phi equivalence classes +Coalesced down to 1 phi equivalence classes +Culled Empty Block (label) @3 +Culled Empty Block (label) main::@3 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@1 +Adding NOP phi() at start of main::@2 + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] (byte) idx ← (byte) 0 + to:@2 +@2: scope:[] from @1 + [2] phi() + [3] call main + to:@end +@end: scope:[] from @2 + [4] phi() + +(void()) main() +main: scope:[main] from @2 + [5] phi() + [6] call print + to:main::@1 +main::@1: scope:[main] from main + [7] phi() + [8] call print + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] phi() + [10] call print + to:main::@return +main::@return: scope:[main] from main::@2 + [11] return + to:@return + +(void()) print((byte) print::ch) +print: scope:[print] from main main::@1 main::@2 + [12] (byte) print::ch#3 ← phi( main/(byte) 'c' main::@1/(byte) 'm' main::@2/(byte) 'l' ) + kickasm( uses print::ch#3) {{ }} + asm { ldxidx staSCREEN,x incidx } + to:print::@return +print::@return: scope:[print] from print + [15] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(byte) idx loadstore !zp[-1]:3 0.18181818181818182 +(void()) main() +(void()) print((byte) print::ch) +(byte) print::ch !reg byte a +(byte) print::ch#3 !reg byte a + +Initial phi equivalence classes +[ print::ch#3 ] +Added variable idx to live range equivalence class [ idx ] +Complete equivalence classes +[ print::ch#3 ] +[ idx ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Test declaring a variable as at a hard-coded register +// hard-coded register parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = 3 + // @begin +__bbegin: + jmp __b1 + // @1 +__b1: + // [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [2] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [3] call main + // [5] phi from @2 to main [phi:@2->main] +main_from___b2: + jsr main + // [4] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: + jmp __bend + // @end +__bend: + // main +main: { + // [6] call print + // [12] phi from main to print [phi:main->print] + print_from_main: + // [12] phi (byte) print::ch#3 = (byte) 'c' [phi:main->print#0] -- vbuaa=vbuc1 + lda #'c' + jsr print + // [7] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + jmp __b1 + // main::@1 + __b1: + // [8] call print + // [12] phi from main::@1 to print [phi:main::@1->print] + print_from___b1: + // [12] phi (byte) print::ch#3 = (byte) 'm' [phi:main::@1->print#0] -- vbuaa=vbuc1 + lda #'m' + jsr print + // [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + __b2_from___b1: + jmp __b2 + // main::@2 + __b2: + // [10] call print + // [12] phi from main::@2 to print [phi:main::@2->print] + print_from___b2: + // [12] phi (byte) print::ch#3 = (byte) 'l' [phi:main::@2->print#0] -- vbuaa=vbuc1 + lda #'l' + jsr print + jmp __breturn + // main::@return + __breturn: + // [11] return + rts +} + // print +// print(byte register(A) ch) +print: { + // kickasm( uses print::ch#3) {{ }} + // Force usage of ch + + // asm { ldxidx staSCREEN,x incidx } + ldx idx + sta SCREEN,x + inc idx + jmp __breturn + // print::@return + __breturn: + // [15] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] (byte) idx ← (byte) 0 [ idx ] ( [ idx ] ) always clobbers reg byte a +Statement asm { ldxidx staSCREEN,x incidx } always clobbers reg byte x +Potential registers reg byte a [ print::ch#3 ] : reg byte a , +Potential registers zp[1]:3 [ idx ] : zp[1]:3 , + +REGISTER UPLIFT SCOPES +Uplift Scope [] 0.18: zp[1]:3 [ idx ] +Uplift Scope [main] +Uplift Scope [print] 0: reg byte a [ print::ch#3 ] + +Uplifting [] best 366 combination zp[1]:3 [ idx ] +Uplifting [main] best 366 combination +Uplifting [print] best 366 combination reg byte a [ print::ch#3 ] +Attempting to uplift remaining variables inzp[1]:3 [ idx ] +Uplifting [] best 366 combination zp[1]:3 [ idx ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test declaring a variable as at a hard-coded register +// hard-coded register parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = 3 + // @begin +__bbegin: + jmp __b1 + // @1 +__b1: + // [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [2] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [3] call main + // [5] phi from @2 to main [phi:@2->main] +main_from___b2: + jsr main + // [4] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: + jmp __bend + // @end +__bend: + // main +main: { + // [6] call print + // [12] phi from main to print [phi:main->print] + print_from_main: + // [12] phi (byte) print::ch#3 = (byte) 'c' [phi:main->print#0] -- vbuaa=vbuc1 + lda #'c' + jsr print + // [7] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + jmp __b1 + // main::@1 + __b1: + // [8] call print + // [12] phi from main::@1 to print [phi:main::@1->print] + print_from___b1: + // [12] phi (byte) print::ch#3 = (byte) 'm' [phi:main::@1->print#0] -- vbuaa=vbuc1 + lda #'m' + jsr print + // [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + __b2_from___b1: + jmp __b2 + // main::@2 + __b2: + // [10] call print + // [12] phi from main::@2 to print [phi:main::@2->print] + print_from___b2: + // [12] phi (byte) print::ch#3 = (byte) 'l' [phi:main::@2->print#0] -- vbuaa=vbuc1 + lda #'l' + jsr print + jmp __breturn + // main::@return + __breturn: + // [11] return + rts +} + // print +// print(byte register(A) ch) +print: { + // kickasm( uses print::ch#3) {{ }} + // Force usage of ch + + // asm { ldxidx staSCREEN,x incidx } + ldx idx + sta SCREEN,x + inc idx + jmp __breturn + // print::@return + __breturn: + // [15] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __bend +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __bbegin with __b1 +Removing instruction __bbegin: +Removing instruction __b2_from___b1: +Removing instruction main_from___b2: +Removing instruction __bend_from___b2: +Removing instruction __b1_from_main: +Removing instruction print_from___b1: +Removing instruction __b2_from___b1: +Removing instruction print_from___b2: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b2: +Removing instruction __bend: +Removing instruction print_from_main: +Removing instruction __b1: +Removing instruction __b2: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Adding RTS to root block +Succesful ASM optimization Pass5AddMainRts + +FINAL SYMBOL TABLE +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte*) SCREEN = (byte*) 1024 +(byte) idx loadstore !zp[-1]:3 zp[1]:3 0.18181818181818182 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch !reg byte a +(byte) print::ch#3 !reg byte a + +reg byte a [ print::ch#3 ] +zp[1]:3 [ idx ] + + +FINAL ASSEMBLER +Score: 324 + + // File Comments +// Test declaring a variable as at a hard-coded register +// hard-coded register parameter + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__b1) +.pc = $80d "Program" + // Global Constants & labels + .label SCREEN = $400 + .label idx = 3 + // @begin + // @1 +__b1: + // idx + // [1] (byte) idx ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [2] phi from @1 to @2 [phi:@1->@2] + // @2 + // [3] call main + // [5] phi from @2 to main [phi:@2->main] + jsr main + rts + // [4] phi from @2 to @end [phi:@2->@end] + // @end + // main +main: { + // print('c') + // [6] call print + // [12] phi from main to print [phi:main->print] + // [12] phi (byte) print::ch#3 = (byte) 'c' [phi:main->print#0] -- vbuaa=vbuc1 + lda #'c' + jsr print + // [7] phi from main to main::@1 [phi:main->main::@1] + // main::@1 + // print('m') + // [8] call print + // [12] phi from main::@1 to print [phi:main::@1->print] + // [12] phi (byte) print::ch#3 = (byte) 'm' [phi:main::@1->print#0] -- vbuaa=vbuc1 + lda #'m' + jsr print + // [9] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + // main::@2 + // print('l') + // [10] call print + // [12] phi from main::@2 to print [phi:main::@2->print] + // [12] phi (byte) print::ch#3 = (byte) 'l' [phi:main::@2->print#0] -- vbuaa=vbuc1 + lda #'l' + jsr print + // main::@return + // } + // [11] return + rts +} + // print +// print(byte register(A) ch) +print: { + // kickasm + // kickasm( uses print::ch#3) {{ }} + // Force usage of ch + + // asm + // asm { ldxidx staSCREEN,x incidx } + ldx idx + sta SCREEN,x + inc idx + // print::@return + // } + // [15] return + rts +} + // File Data + diff --git a/src/test/ref/register-0.sym b/src/test/ref/register-0.sym new file mode 100644 index 000000000..8bc4b1852 --- /dev/null +++ b/src/test/ref/register-0.sym @@ -0,0 +1,17 @@ +(label) @1 +(label) @2 +(label) @begin +(label) @end +(const byte*) SCREEN = (byte*) 1024 +(byte) idx loadstore !zp[-1]:3 zp[1]:3 0.18181818181818182 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(void()) print((byte) print::ch) +(label) print::@return +(byte) print::ch !reg byte a +(byte) print::ch#3 !reg byte a + +reg byte a [ print::ch#3 ] +zp[1]:3 [ idx ]