From 9b113b4bcd15dc5589d568c9a48cd1427cf89c11 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Mon, 2 Sep 2019 23:35:15 +0200 Subject: [PATCH] Fixed problem with inline ASM culling JMP. Closes #302 --- src/main/java/dk/camelot64/kickc/KickC.java | 2 +- .../passes/Pass5NextJumpElimination.java | 2 + .../dk/camelot64/kickc/test/TestPrograms.java | 7 +- src/test/kc/asm-culling-jmp.kc | 12 + src/test/ref/asm-culling-jmp.asm | 14 ++ src/test/ref/asm-culling-jmp.cfg | 16 ++ src/test/ref/asm-culling-jmp.log | 232 ++++++++++++++++++ src/test/ref/asm-culling-jmp.sym | 6 + 8 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 src/test/kc/asm-culling-jmp.kc create mode 100644 src/test/ref/asm-culling-jmp.asm create mode 100644 src/test/ref/asm-culling-jmp.cfg create mode 100644 src/test/ref/asm-culling-jmp.log create mode 100644 src/test/ref/asm-culling-jmp.sym diff --git a/src/main/java/dk/camelot64/kickc/KickC.java b/src/main/java/dk/camelot64/kickc/KickC.java index 900834021..294bd757b 100644 --- a/src/main/java/dk/camelot64/kickc/KickC.java +++ b/src/main/java/dk/camelot64/kickc/KickC.java @@ -273,7 +273,7 @@ public class KickC implements Callable { ByteArrayOutputStream kasmLogOutputStream = new ByteArrayOutputStream(); String[] assembleCommand = {asmPath.toString(), "-log", kasmLogPath.toString(), "-o", prgPath.toString(), "-vicesymbols", "-showmem", "-debugdump"}; if(verbose) { - System.out.print("Assembling command: java -jar kickassembler-5.7.jar "); + System.out.print("Assembling command: java -jar kickassembler-5.9.jar "); for(String cmd : assembleCommand) { System.out.print(cmd + " "); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass5NextJumpElimination.java b/src/main/java/dk/camelot64/kickc/passes/Pass5NextJumpElimination.java index f73c4e792..f8f80fb19 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass5NextJumpElimination.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass5NextJumpElimination.java @@ -36,6 +36,8 @@ public class Pass5NextJumpElimination extends Pass5AsmOptimization { if(instruction.getType().isJump() && !instruction.getType().getMnemnonic().equals("jsr")) { candidate = instruction; } + } else if(line instanceof AsmDataString || line instanceof AsmDataNumeric || line instanceof AsmDataFill || line instanceof AsmInlineKickAsm ) { + candidate = null; } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 8fa953c03..c81fc15d8 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -44,9 +44,14 @@ public class TestPrograms { } */ + @Test + public void testAsmCullingJmp() throws IOException, URISyntaxException { + compileAndCompare("asm-culling-jmp"); + } + @Test public void testZeropageDetectAdvanced() throws IOException, URISyntaxException { - compileAndCompare("zeropage-detect-advanced", log()); + compileAndCompare("zeropage-detect-advanced"); } @Test diff --git a/src/test/kc/asm-culling-jmp.kc b/src/test/kc/asm-culling-jmp.kc new file mode 100644 index 000000000..53ea452c3 --- /dev/null +++ b/src/test/kc/asm-culling-jmp.kc @@ -0,0 +1,12 @@ +// Example of inline ASM where a JMP is erronously culled during compilation +// https://gitlab.com/camelot/kickc/issues/302 + +void main() { + asm { + jmp qwe + .byte 0,25,51,76,102,128,153,179,204,230 + qwe: lda #50 + } + *((char*)0x0400) = 'c'; + +} \ No newline at end of file diff --git a/src/test/ref/asm-culling-jmp.asm b/src/test/ref/asm-culling-jmp.asm new file mode 100644 index 000000000..0ab70306c --- /dev/null +++ b/src/test/ref/asm-culling-jmp.asm @@ -0,0 +1,14 @@ +// Example of inline ASM where a JMP is erronously culled during compilation +// https://gitlab.com/camelot/kickc/issues/302 +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +main: { + jmp qwe + .byte 0, 25, 51, 76, 102, 128, 153, 179, 204, 230 + qwe: + lda #$32 + lda #'c' + sta $400 + rts +} diff --git a/src/test/ref/asm-culling-jmp.cfg b/src/test/ref/asm-culling-jmp.cfg new file mode 100644 index 000000000..4762e874b --- /dev/null +++ b/src/test/ref/asm-culling-jmp.cfg @@ -0,0 +1,16 @@ +@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 + asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } + [5] *((byte*) 1024) ← (byte) 'c' + to:main::@return +main::@return: scope:[main] from main + [6] return + to:@return diff --git a/src/test/ref/asm-culling-jmp.log b/src/test/ref/asm-culling-jmp.log new file mode 100644 index 000000000..c37abb906 --- /dev/null +++ b/src/test/ref/asm-culling-jmp.log @@ -0,0 +1,232 @@ + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@1 +main: scope:[main] from @1 + asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } + (byte*~) main::$0 ← ((byte*)) (number) $400 + *((byte*~) main::$0) ← (byte) 'c' + 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 +(void()) main() +(byte*~) main::$0 +(label) main::@return + +Inlining cast (byte*~) main::$0 ← (byte*)(number) $400 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (byte*) 1024 +Successful SSA optimization PassNCastSimplification +Constant (const byte*) main::$0 = (byte*) 1024 +Successful SSA optimization Pass2ConstantIdentification +Constant inlined main::$0 = (byte*) 1024 +Successful SSA optimization Pass2ConstantInlining +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 + asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } + [5] *((byte*) 1024) ← (byte) 'c' + to:main::@return +main::@return: scope:[main] from main + [6] return + to:@return + + +VARIABLE REGISTER WEIGHTS +(void()) main() + +Initial phi equivalence classes +Complete equivalence classes + +INITIAL ASM +Target platform is c64basic + // File Comments +// Example of inline ASM where a JMP is erronously culled during compilation +// https://gitlab.com/camelot/kickc/issues/302 + // 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 + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + // asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } + jmp qwe + .byte 0, 25, 51, 76, 102, 128, 153, 179, 204, 230 + qwe: + lda #$32 + // [5] *((byte*) 1024) ← (byte) 'c' -- _deref_pbuc1=vbuc2 + lda #'c' + sta $400 + jmp breturn + // main::@return + breturn: + // [6] return + rts +} + // File Data + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } always clobbers reg byte a +Statement [5] *((byte*) 1024) ← (byte) 'c' [ ] ( main:2 [ ] ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [] + +Uplifting [main] best 32 combination +Uplifting [] best 32 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Example of inline ASM where a JMP is erronously culled during compilation +// https://gitlab.com/camelot/kickc/issues/302 + // 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 + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend + // @end +bend: + // main +main: { + // asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } + jmp qwe + .byte 0, 25, 51, 76, 102, 128, 153, 179, 204, 230 + qwe: + lda #$32 + // [5] *((byte*) 1024) ← (byte) 'c' -- _deref_pbuc1=vbuc2 + lda #'c' + sta $400 + jmp breturn + // main::@return + breturn: + // [6] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction bend_from_b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +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 +(void()) main() +(label) main::@return + + + +FINAL ASSEMBLER +Score: 17 + + // File Comments +// Example of inline ASM where a JMP is erronously culled during compilation +// https://gitlab.com/camelot/kickc/issues/302 + // 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 + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + // asm + // asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } + jmp qwe + .byte 0, 25, 51, 76, 102, 128, 153, 179, 204, 230 + qwe: + lda #$32 + // *((char*)0x0400) = 'c' + // [5] *((byte*) 1024) ← (byte) 'c' -- _deref_pbuc1=vbuc2 + lda #'c' + sta $400 + // main::@return + // } + // [6] return + rts +} + // File Data + diff --git a/src/test/ref/asm-culling-jmp.sym b/src/test/ref/asm-culling-jmp.sym new file mode 100644 index 000000000..5b1ee8133 --- /dev/null +++ b/src/test/ref/asm-culling-jmp.sym @@ -0,0 +1,6 @@ +(label) @1 +(label) @begin +(label) @end +(void()) main() +(label) main::@return +