1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Added test for optimizing comparisons to types outside range of type. Added a missing fragment (that won't be used when the optimization is implemented). #291

This commit is contained in:
jespergravgaard 2019-08-25 22:44:06 +02:00
parent 3aad07f4e1
commit 2739456cc3
7 changed files with 626 additions and 0 deletions

View File

@ -0,0 +1 @@
jmp {la1}

View File

@ -36,6 +36,13 @@ public class TestPrograms {
public TestPrograms() {
}
// TODO: Optimize comparisons with values outside the range of types https://gitlab.com/camelot/kickc/issues/291
@Test
public void testOptimizeUnsignedComparisons() throws IOException, URISyntaxException {
compileAndCompare("optimize-unsigned-comparisons");
}
// TODO: Fix loop head problem! https://gitlab.com/camelot/kickc/issues/261
@Test
public void testLoopheadProblem() throws IOException, URISyntaxException {

View File

@ -0,0 +1,21 @@
// Examples of unsigned comparisons to values outside the range of unsigned
// These should be optimized to constants
byte[8] ball_active = { 0, 1, 0, 1, 0, 1, 1, 1 };
void main() {
const byte* screen = 0x0400;
byte temp;
for( char i: 0..7) {
// Always false
if (ball_active[i]<0) {
screen[i] = '-';
}
temp = ball_active[i];
}
// Always false
if (temp<0) {
screen[40] = temp;
}
}

View File

@ -0,0 +1,17 @@
// Examples of unsigned comparisons to values outside the range of unsigned
// These should be optimized to constants
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
.label screen = $400
ldx #0
b1:
lda ball_active,x
lda ball_active,x
inx
cpx #8
bne b1
rts
}
ball_active: .byte 0, 1, 0, 1, 0, 1, 1, 1

View File

@ -0,0 +1,33 @@
@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] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
[6] if(*((const byte[8]) ball_active#0 + (byte) main::i#2)>=(byte) 0) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@1
[7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte) '-'
to:main::@2
main::@2: scope:[main] from main::@1 main::@3
[8] (byte) main::temp#1 ← *((const byte[8]) ball_active#0 + (byte) main::i#2)
[9] (byte) main::i#1 ← ++ (byte) main::i#2
[10] if((byte) main::i#1!=(byte) 8) goto main::@1
to:main::@4
main::@4: scope:[main] from main::@2
[11] if((byte) main::temp#1>=(byte) 0) goto main::@return
to:main::@5
main::@5: scope:[main] from main::@4
[12] *((const byte*) main::screen#0+(byte) $28) ← (byte) main::temp#1
to:main::@return
main::@return: scope:[main] from main::@4 main::@5
[13] return
to:@return

View File

@ -0,0 +1,525 @@
Culled Empty Block (label) main::@1
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
(byte[8]) ball_active#0 ← { (number) 0, (number) 1, (number) 0, (number) 1, (number) 0, (number) 1, (number) 1, (number) 1 }
to:@1
main: scope:[main] from @1
(byte*) main::screen#0 ← ((byte*)) (number) $400
(byte) main::temp#0 ← (byte) 0
(byte) main::i#0 ← (byte) 0
to:main::@2
main::@2: scope:[main] from main main::@3
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@3/(byte) main::i#1 )
(bool~) main::$2 ← *((byte[8]) ball_active#0 + (byte) main::i#2) < (number) 0
(bool~) main::$3 ← ! (bool~) main::$2
if((bool~) main::$3) goto main::@3
to:main::@4
main::@3: scope:[main] from main::@2 main::@4
(byte) main::i#3 ← phi( main::@2/(byte) main::i#2 main::@4/(byte) main::i#4 )
(byte) main::temp#1 ← *((byte[8]) ball_active#0 + (byte) main::i#3)
(byte) main::i#1 ← (byte) main::i#3 + rangenext(0,7)
(bool~) main::$4 ← (byte) main::i#1 != rangelast(0,7)
if((bool~) main::$4) goto main::@2
to:main::@5
main::@4: scope:[main] from main::@2
(byte) main::i#4 ← phi( main::@2/(byte) main::i#2 )
*((byte*) main::screen#0 + (byte) main::i#4) ← (byte) '-'
to:main::@3
main::@5: scope:[main] from main::@3
(byte) main::temp#2 ← phi( main::@3/(byte) main::temp#1 )
(bool~) main::$0 ← (byte) main::temp#2 < (number) 0
(bool~) main::$1 ← ! (bool~) main::$0
if((bool~) main::$1) goto main::@return
to:main::@6
main::@6: scope:[main] from main::@5
(byte) main::temp#3 ← phi( main::@5/(byte) main::temp#2 )
*((byte*) main::screen#0 + (number) $28) ← (byte) main::temp#3
to:main::@return
main::@return: scope:[main] from main::@5 main::@6
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
(byte[8]) ball_active
(byte[8]) ball_active#0
(void()) main()
(bool~) main::$0
(bool~) main::$1
(bool~) main::$2
(bool~) main::$3
(bool~) main::$4
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@return
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte) main::i#3
(byte) main::i#4
(byte*) main::screen
(byte*) main::screen#0
(byte) main::temp
(byte) main::temp#0
(byte) main::temp#1
(byte) main::temp#2
(byte) main::temp#3
Adding number conversion cast (unumber) 0 in (bool~) main::$2 ← *((byte[8]) ball_active#0 + (byte) main::i#2) < (number) 0
Adding number conversion cast (unumber) 0 in (bool~) main::$0 ← (byte) main::temp#2 < (number) 0
Adding number conversion cast (unumber) $28 in *((byte*) main::screen#0 + (number) $28) ← (byte) main::temp#3
Successful SSA optimization PassNAddNumberTypeConversions
Added casts to value list in (byte[8]) ball_active#0 ← (byte[8]){ (byte)(number) 0, (byte)(number) 1, (byte)(number) 0, (byte)(number) 1, (byte)(number) 0, (byte)(number) 1, (byte)(number) 1, (byte)(number) 1 }
Successful SSA optimization PassNAddInitializerValueListTypeCasts
Inlining cast (byte*) main::screen#0 ← (byte*)(number) $400
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 0
Simplifying constant integer cast 1
Simplifying constant integer cast 1
Simplifying constant integer cast 1
Simplifying constant pointer cast (byte*) 1024
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast $28
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) 0
Finalized unsigned number type (byte) $28
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inversing boolean not [6] (bool~) main::$3 ← *((byte[8]) ball_active#0 + (byte) main::i#2) >= (byte) 0 from [5] (bool~) main::$2 ← *((byte[8]) ball_active#0 + (byte) main::i#2) < (byte) 0
Inversing boolean not [17] (bool~) main::$1 ← (byte) main::temp#2 >= (byte) 0 from [16] (bool~) main::$0 ← (byte) main::temp#2 < (byte) 0
Successful SSA optimization Pass2UnaryNotSimplification
Alias (byte) main::i#2 = (byte) main::i#4
Alias (byte) main::temp#1 = (byte) main::temp#2 (byte) main::temp#3
Successful SSA optimization Pass2AliasElimination
Alias (byte) main::i#2 = (byte) main::i#3
Successful SSA optimization Pass2AliasElimination
Simple Condition (bool~) main::$3 [7] if(*((byte[8]) ball_active#0 + (byte) main::i#2)>=(byte) 0) goto main::@3
Simple Condition (bool~) main::$4 [12] if((byte) main::i#1!=rangelast(0,7)) goto main::@2
Simple Condition (bool~) main::$1 [18] if((byte) main::temp#1>=(byte) 0) goto main::@return
Successful SSA optimization Pass2ConditionalJumpSimplification
Identified constant from value list (byte[8]) { (byte) 0, (byte) 1, (byte) 0, (byte) 1, (byte) 0, (byte) 1, (byte) 1, (byte) 1 }
Successful SSA optimization Pass2ConstantInitializerValueLists
Constant (const byte[8]) ball_active#0 = { 0, 1, 0, 1, 0, 1, 1, 1 }
Constant (const byte*) main::screen#0 = (byte*) 1024
Constant (const byte) main::temp#0 = 0
Constant (const byte) main::i#0 = 0
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value [10] main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value [12] if(main::i#1!=rangelast(0,7)) goto main::@2 to (number) 8
Eliminating unused constant (const byte) main::temp#0
Successful SSA optimization PassNEliminateUnusedVars
Adding number conversion cast (unumber) 8 in if((byte) main::i#1!=(number) 8) goto main::@2
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast 8
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (byte) 8
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte) 0
Successful SSA optimization Pass2ConstantInlining
Consolidated array index constant in *(main::screen#0+$28)
Successful SSA optimization Pass2ConstantAdditionElimination
Added new block during phi lifting main::@7(between main::@3 and main::@2)
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
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Created 1 initial phi equivalence classes
Coalesced [15] main::i#5 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) @2
Culled Empty Block (label) main::@7
Renumbering block main::@2 to main::@1
Renumbering block main::@3 to main::@2
Renumbering block main::@4 to main::@3
Renumbering block main::@5 to main::@4
Renumbering block main::@6 to main::@5
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
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] phi()
to:main::@1
main::@1: scope:[main] from main main::@2
[5] (byte) main::i#2 ← phi( main/(byte) 0 main::@2/(byte) main::i#1 )
[6] if(*((const byte[8]) ball_active#0 + (byte) main::i#2)>=(byte) 0) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@1
[7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte) '-'
to:main::@2
main::@2: scope:[main] from main::@1 main::@3
[8] (byte) main::temp#1 ← *((const byte[8]) ball_active#0 + (byte) main::i#2)
[9] (byte) main::i#1 ← ++ (byte) main::i#2
[10] if((byte) main::i#1!=(byte) 8) goto main::@1
to:main::@4
main::@4: scope:[main] from main::@2
[11] if((byte) main::temp#1>=(byte) 0) goto main::@return
to:main::@5
main::@5: scope:[main] from main::@4
[12] *((const byte*) main::screen#0+(byte) $28) ← (byte) main::temp#1
to:main::@return
main::@return: scope:[main] from main::@4 main::@5
[13] return
to:@return
VARIABLE REGISTER WEIGHTS
(byte[8]) ball_active
(void()) main()
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 13.75
(byte*) main::screen
(byte) main::temp
(byte) main::temp#1 3.75
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Added variable main::temp#1 to zero page equivalence class [ main::temp#1 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::temp#1 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:3 [ main::temp#1 ]
INITIAL ASM
Target platform is c64basic
// File Comments
// Examples of unsigned comparisons to values outside the range of unsigned
// These should be optimized to constants
// 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
// [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 screen = $400
.label temp = 3
.label i = 2
// [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
jmp b1
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
b1_from_b2:
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
jmp b1
// main::@1
b1:
// [6] if(*((const byte[8]) ball_active#0 + (byte) main::i#2)>=(byte) 0) goto main::@2 -- pbuc1_derefidx_vbuz1_ge_0_then_la1
ldy.z i
lda ball_active,y
jmp b2
jmp b3
// main::@3
b3:
// [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte) '-' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'-'
ldy.z i
sta screen,y
jmp b2
// main::@2
b2:
// [8] (byte) main::temp#1 ← *((const byte[8]) ball_active#0 + (byte) main::i#2) -- vbuz1=pbuc1_derefidx_vbuz2
ldy.z i
lda ball_active,y
sta.z temp
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc.z i
// [10] if((byte) main::i#1!=(byte) 8) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #8
cmp.z i
bne b1_from_b2
jmp b4
// main::@4
b4:
// [11] if((byte) main::temp#1>=(byte) 0) goto main::@return -- vbuz1_ge_0_then_la1
lda.z temp
jmp breturn
jmp b5
// main::@5
b5:
// [12] *((const byte*) main::screen#0+(byte) $28) ← (byte) main::temp#1 -- _deref_pbuc1=vbuz1
lda.z temp
sta screen+$28
jmp breturn
// main::@return
breturn:
// [13] return
rts
}
// File Data
ball_active: .byte 0, 1, 0, 1, 0, 1, 1, 1
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] if(*((const byte[8]) ball_active#0 + (byte) main::i#2)>=(byte) 0) goto main::@2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Statement [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte) '-' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [6] if(*((const byte[8]) ball_active#0 + (byte) main::i#2)>=(byte) 0) goto main::@2 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte) '-' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:3 [ main::temp#1 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 30.25: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 3.75: zp ZP_BYTE:3 [ main::temp#1 ]
Uplift Scope []
Uplifting [main] best 456 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::temp#1 ]
Uplifting [] best 456 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Examples of unsigned comparisons to values outside the range of unsigned
// These should be optimized to constants
// 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
// [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 screen = $400
// [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
jmp b1
// [5] phi from main::@2 to main::@1 [phi:main::@2->main::@1]
b1_from_b2:
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
jmp b1
// main::@1
b1:
// [6] if(*((const byte[8]) ball_active#0 + (byte) main::i#2)>=(byte) 0) goto main::@2 -- pbuc1_derefidx_vbuxx_ge_0_then_la1
lda ball_active,x
jmp b2
jmp b3
// main::@3
b3:
// [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte) '-' -- pbuc1_derefidx_vbuxx=vbuc2
lda #'-'
sta screen,x
jmp b2
// main::@2
b2:
// [8] (byte) main::temp#1 ← *((const byte[8]) ball_active#0 + (byte) main::i#2) -- vbuaa=pbuc1_derefidx_vbuxx
lda ball_active,x
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
// [10] if((byte) main::i#1!=(byte) 8) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #8
bne b1_from_b2
jmp b4
// main::@4
b4:
// [11] if((byte) main::temp#1>=(byte) 0) goto main::@return -- vbuaa_ge_0_then_la1
jmp breturn
jmp b5
// main::@5
b5:
// [12] *((const byte*) main::screen#0+(byte) $28) ← (byte) main::temp#1 -- _deref_pbuc1=vbuaa
sta screen+$28
jmp breturn
// main::@return
breturn:
// [13] return
rts
}
// File Data
ball_active: .byte 0, 1, 0, 1, 0, 1, 1, 1
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b3
Removing instruction jmp b2
Removing instruction jmp b4
Removing instruction jmp b5
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1_from_b2 with b1
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Removing instruction b1_from_b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction b3:
Removing instruction b4:
Removing instruction b5:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Replacing jump to rts with rts in jmp breturn
Succesful ASM optimization Pass5DoubleJumpElimination
Removing unreachable instruction lda #'-'
Removing unreachable instruction sta screen,x
Removing unreachable instruction sta screen+$28
Succesful ASM optimization Pass5UnreachableCodeElimination
Removing instruction jmp b1
Removing instruction jmp b2
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Removing instruction b2:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Removing unreachable instruction rts
Succesful ASM optimization Pass5UnreachableCodeElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(byte[8]) ball_active
(const byte[8]) ball_active#0 ball_active = { (byte) 0, (byte) 1, (byte) 0, (byte) 1, (byte) 0, (byte) 1, (byte) 1, (byte) 1 }
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 13.75
(byte*) main::screen
(const byte*) main::screen#0 screen = (byte*) 1024
(byte) main::temp
(byte) main::temp#1 reg byte a 3.75
reg byte x [ main::i#2 main::i#1 ]
reg byte a [ main::temp#1 ]
FINAL ASSEMBLER
Score: 181
// File Comments
// Examples of unsigned comparisons to values outside the range of unsigned
// These should be optimized to constants
// 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
// [4] phi from @1 to main [phi:@1->main]
// [3] phi from @1 to @end [phi:@1->@end]
// @end
// main
main: {
.label screen = $400
// [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 from main::@2 to main::@1 [phi:main::@2->main::@1]
// [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@2->main::@1#0] -- register_copy
// main::@1
b1:
// if (ball_active[i]<0)
// [6] if(*((const byte[8]) ball_active#0 + (byte) main::i#2)>=(byte) 0) goto main::@2 -- pbuc1_derefidx_vbuxx_ge_0_then_la1
lda ball_active,x
// main::@3
// screen[i] = '-'
// [7] *((const byte*) main::screen#0 + (byte) main::i#2) ← (byte) '-' -- pbuc1_derefidx_vbuxx=vbuc2
// main::@2
// temp = ball_active[i]
// [8] (byte) main::temp#1 ← *((const byte[8]) ball_active#0 + (byte) main::i#2) -- vbuaa=pbuc1_derefidx_vbuxx
lda ball_active,x
// for( char i: 0..7)
// [9] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
// [10] if((byte) main::i#1!=(byte) 8) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #8
bne b1
// main::@4
// if (temp<0)
// [11] if((byte) main::temp#1>=(byte) 0) goto main::@return -- vbuaa_ge_0_then_la1
rts
// main::@5
// screen[40] = temp
// [12] *((const byte*) main::screen#0+(byte) $28) ← (byte) main::temp#1 -- _deref_pbuc1=vbuaa
// main::@return
// }
// [13] return
}
// File Data
ball_active: .byte 0, 1, 0, 1, 0, 1, 1, 1

View File

@ -0,0 +1,22 @@
(label) @1
(label) @begin
(label) @end
(byte[8]) ball_active
(const byte[8]) ball_active#0 ball_active = { (byte) 0, (byte) 1, (byte) 0, (byte) 1, (byte) 0, (byte) 1, (byte) 1, (byte) 1 }
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@return
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 13.75
(byte*) main::screen
(const byte*) main::screen#0 screen = (byte*) 1024
(byte) main::temp
(byte) main::temp#1 reg byte a 3.75
reg byte x [ main::i#2 main::i#1 ]
reg byte a [ main::temp#1 ]