mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-22 21:29:50 +00:00
Fixed exception "Block referenced, but not found in program" when encountering complex if(&&). Closes #676
This commit is contained in:
parent
72c5c7d537
commit
3dff5d04fb
@ -54,9 +54,9 @@ public class Procedure extends Scope {
|
||||
PHI_CALL("__phicall"),
|
||||
/** Parameters and return value over the stack. */
|
||||
STACK_CALL("__stackcall"),
|
||||
/** Parameters and return value handled through variables. */
|
||||
/** Parameters and return value handled through shared variables. */
|
||||
VAR_CALL("__varcall"),
|
||||
/** Intrinsic calling. */
|
||||
/** Intrinsic calling. Will be converted to intrinsic ASM late in the compile. */
|
||||
INTRINSIC_CALL("__intrinsiccall");
|
||||
|
||||
private final String name;
|
||||
|
@ -126,7 +126,7 @@ public class Pass2ConditionalAndOrRewriting extends Pass2SsaOptimization {
|
||||
ControlFlowBlock destBlock = getGraph().getBlock(destLabel);
|
||||
LinkedHashMap<LabelRef, LabelRef> replacements = new LinkedHashMap<>();
|
||||
replacements.put(block.getLabel(), newBlockLabel.getRef());
|
||||
replaceLabels(destBlock, replacements);
|
||||
replaceLabels(destBlock.getPhiBlock(), replacements);
|
||||
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,16 @@ public abstract class Pass2SsaOptimization extends Pass1Base implements PassStep
|
||||
visitor.visitBlock(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all usages of a label in a statement with another label.
|
||||
*
|
||||
* @param replacements Variables that have alias values.
|
||||
*/
|
||||
public void replaceLabels(Statement statement, final Map<LabelRef, LabelRef> replacements) {
|
||||
ControlFlowGraphBaseVisitor<Void> visitor = getLabelReplaceVisitor(replacements);
|
||||
visitor.visitStatement(statement);
|
||||
}
|
||||
|
||||
/** Creates a visitor that can replace labels. */
|
||||
private ControlFlowGraphBaseVisitor<Void> getLabelReplaceVisitor(final Map<LabelRef, LabelRef> replacements) {
|
||||
return new ControlFlowGraphBaseVisitor<Void>() {
|
||||
|
@ -9,6 +9,21 @@ import java.io.IOException;
|
||||
*/
|
||||
public class TestProgramsFast extends TestPrograms {
|
||||
|
||||
//@Test
|
||||
//public void testShadowVariableError1() throws IOException {
|
||||
// compileAndCompare("shadow-variable-error-1.c");
|
||||
//}
|
||||
|
||||
@Test
|
||||
public void testBlockError2() throws IOException {
|
||||
compileAndCompare("block-error-2.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBlockError1() throws IOException {
|
||||
compileAndCompare("block-error-1.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMakeLong42() throws IOException {
|
||||
assertError("makelong4-2.c", "Wrong number of parameters in call. Expected 4.");
|
||||
|
15
src/test/kc/block-error-1.c
Normal file
15
src/test/kc/block-error-1.c
Normal file
@ -0,0 +1,15 @@
|
||||
// Demonstrates error "Block referenced, but not found in program."
|
||||
|
||||
void main() {
|
||||
for(char i=0;i!=8;i++) {
|
||||
char move = 1;
|
||||
char pos = 1;
|
||||
char vacant = 1;
|
||||
do {
|
||||
pos += move;
|
||||
if(pos) {
|
||||
char vacant = 0;
|
||||
}
|
||||
} while(pos && vacant);
|
||||
}
|
||||
}
|
12
src/test/kc/block-error-2.c
Normal file
12
src/test/kc/block-error-2.c
Normal file
@ -0,0 +1,12 @@
|
||||
// Demonstrates error "Sequence does not contain all blocks from the program."
|
||||
|
||||
void main() {
|
||||
char move = 1;
|
||||
char pos = 1;
|
||||
char vacant = 1;
|
||||
do {
|
||||
pos += move;
|
||||
if(pos)
|
||||
vacant = 0;
|
||||
} while(pos && vacant);
|
||||
}
|
14
src/test/kc/shadow-variable-error-1.c
Normal file
14
src/test/kc/shadow-variable-error-1.c
Normal file
@ -0,0 +1,14 @@
|
||||
// Demonstrates error "Variable used before being defined."
|
||||
|
||||
void main() {
|
||||
for(char i=0;i!=8;i++) {
|
||||
char move = 1;
|
||||
char pos = 1;
|
||||
char vacant = 1;
|
||||
do {
|
||||
pos += move;
|
||||
if(pos)
|
||||
char vacant = 0;
|
||||
} while(pos && vacant);
|
||||
}
|
||||
}
|
34
src/test/ref/block-error-1.asm
Normal file
34
src/test/ref/block-error-1.asm
Normal file
@ -0,0 +1,34 @@
|
||||
// Demonstrates error "Block referenced, but not found in program."
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="block-error-1.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)
|
||||
.segment Code
|
||||
main: {
|
||||
.const move = 1
|
||||
ldx #0
|
||||
__b1:
|
||||
// for(char i=0;i!=8;i++)
|
||||
cpx #8
|
||||
bne __b4
|
||||
// }
|
||||
rts
|
||||
__b4:
|
||||
lda #1
|
||||
__b2:
|
||||
// pos += move
|
||||
clc
|
||||
adc #move
|
||||
// if(pos)
|
||||
cmp #0
|
||||
// while(pos && vacant)
|
||||
cmp #0
|
||||
bne __b2
|
||||
// for(char i=0;i!=8;i++)
|
||||
inx
|
||||
jmp __b1
|
||||
}
|
26
src/test/ref/block-error-1.cfg
Normal file
26
src/test/ref/block-error-1.cfg
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@5
|
||||
[1] main::i#2 = phi( main/0, main::@5/main::i#1 )
|
||||
[2] if(main::i#2!=8) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1 main::@3
|
||||
[4] main::pos#2 = phi( main::@1/1, main::@3/main::pos#1 )
|
||||
[5] main::pos#1 = main::pos#2 + main::move
|
||||
[6] if(0==main::pos#1) goto main::@3
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@2
|
||||
[7] phi()
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
[8] if(0!=main::pos#1) goto main::@2
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@3
|
||||
[9] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
389
src/test/ref/block-error-1.log
Normal file
389
src/test/ref/block-error-1.log
Normal file
@ -0,0 +1,389 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
main::i#0 = 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@6
|
||||
main::i#2 = phi( main/main::i#0, main::@6/main::i#1 )
|
||||
main::$0 = main::i#2 != 8
|
||||
if(main::$0) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
main::i#7 = phi( main::@1/main::i#2 )
|
||||
main::pos#0 = 1
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
main::i#5 = phi( main::@2/main::i#7, main::@4/main::i#4 )
|
||||
main::pos#2 = phi( main::@2/main::pos#0, main::@4/main::pos#3 )
|
||||
main::pos#1 = main::pos#2 + main::move
|
||||
main::$3 = 0 != main::pos#1
|
||||
main::$1 = ! main::$3
|
||||
if(main::$1) goto main::@4
|
||||
to:main::@5
|
||||
main::@4: scope:[main] from main::@3 main::@5
|
||||
main::i#4 = phi( main::@3/main::i#5, main::@5/main::i#6 )
|
||||
main::pos#3 = phi( main::@3/main::pos#1, main::@5/main::pos#4 )
|
||||
main::$2 = main::pos#3 && main::vacant
|
||||
if(main::$2) goto main::@3
|
||||
to:main::@6
|
||||
main::@5: scope:[main] from main::@3
|
||||
main::i#6 = phi( main::@3/main::i#5 )
|
||||
main::pos#4 = phi( main::@3/main::pos#1 )
|
||||
to:main::@4
|
||||
main::@6: scope:[main] from main::@4
|
||||
main::i#3 = phi( main::@4/main::i#4 )
|
||||
main::i#1 = ++ main::i#3
|
||||
to:main::@1
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
|
||||
void __start()
|
||||
__start: scope:[__start] from
|
||||
call main
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start
|
||||
to:__start::@return
|
||||
__start::@return: scope:[__start] from __start::@1
|
||||
return
|
||||
to:@return
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
void __start()
|
||||
void main()
|
||||
bool~ main::$0
|
||||
bool~ main::$1
|
||||
bool~ main::$2
|
||||
bool~ main::$3
|
||||
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::i#5
|
||||
byte main::i#6
|
||||
byte main::i#7
|
||||
constant byte main::move = 1
|
||||
byte main::pos
|
||||
byte main::pos#0
|
||||
byte main::pos#1
|
||||
byte main::pos#2
|
||||
byte main::pos#3
|
||||
byte main::pos#4
|
||||
constant byte main::vacant = 1
|
||||
|
||||
Adding number conversion cast (unumber) 8 in main::$0 = main::i#2 != 8
|
||||
Adding number conversion cast (unumber) 0 in main::$3 = 0 != main::pos#1
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant integer cast 8
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 8
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Inversing boolean not [9] main::$1 = 0 == main::pos#1 from [8] main::$3 = 0 != main::pos#1
|
||||
Successful SSA optimization Pass2UnaryNotSimplification
|
||||
Alias main::i#2 = main::i#7
|
||||
Alias main::pos#1 = main::pos#4
|
||||
Alias main::i#5 = main::i#6
|
||||
Alias main::i#3 = main::i#4
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Alias main::pos#1 = main::pos#3
|
||||
Alias main::i#3 = main::i#5
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values main::i#3 main::i#2
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition main::$0 [3] if(main::i#2!=8) goto main::@2
|
||||
Simple Condition main::$1 [8] if(0==main::pos#1) goto main::@4
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Rewriting && if()-condition to two if()s [9] main::$2 = main::pos#1 && main::vacant
|
||||
Successful SSA optimization Pass2ConditionalAndOrRewriting
|
||||
Warning! Adding boolean cast to non-boolean condition main::pos#1
|
||||
Warning! Adding boolean cast to non-boolean condition main::vacant
|
||||
Constant right-side identified main::$5 = 0 != main::vacant
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant main::i#0 = 0
|
||||
Constant main::pos#0 = 1
|
||||
Constant main::$5 = 0!=main::vacant
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
if() condition always true - replacing block destination if(main::$5) goto main::@3
|
||||
Successful SSA optimization Pass2ConstantIfs
|
||||
Eliminating unused constant main::$5
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Eliminating unused constant main::vacant
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Removing unused procedure __start
|
||||
Removing unused procedure block __start
|
||||
Removing unused procedure block __start::@1
|
||||
Removing unused procedure block __start::@return
|
||||
Successful SSA optimization PassNEliminateEmptyStart
|
||||
Adding number conversion cast (unumber) 0 in [5] main::$4 = 0 != main::pos#1
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Simple Condition main::$4 [6] if(0!=main::pos#1) goto main::@7
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Inlining constant with var siblings main::i#0
|
||||
Inlining constant with var siblings main::pos#0
|
||||
Constant inlined main::i#0 = 0
|
||||
Constant inlined main::pos#0 = 1
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@2
|
||||
Adding NOP phi() at start of main::@5
|
||||
CALL GRAPH
|
||||
|
||||
Created 2 initial phi equivalence classes
|
||||
Coalesced [11] main::i#8 = main::i#1
|
||||
Coalesced [12] main::pos#5 = main::pos#1
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block label main::@2
|
||||
Culled Empty Block label main::@7
|
||||
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 main
|
||||
Adding NOP phi() at start of main::@4
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@5
|
||||
[1] main::i#2 = phi( main/0, main::@5/main::i#1 )
|
||||
[2] if(main::i#2!=8) goto main::@2
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1 main::@3
|
||||
[4] main::pos#2 = phi( main::@1/1, main::@3/main::pos#1 )
|
||||
[5] main::pos#1 = main::pos#2 + main::move
|
||||
[6] if(0==main::pos#1) goto main::@3
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@2
|
||||
[7] phi()
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2 main::@4
|
||||
[8] if(0!=main::pos#1) goto main::@2
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@3
|
||||
[9] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
byte main::i
|
||||
byte main::i#1 22.0
|
||||
byte main::i#2 4.714285714285714
|
||||
byte main::pos
|
||||
byte main::pos#1 101.0
|
||||
byte main::pos#2 202.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ main::pos#2 main::pos#1 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ main::pos#2 main::pos#1 ]
|
||||
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp[1]:3 [ main::pos#2 main::pos#1 ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [5] main::pos#1 = main::pos#2 + main::move [ main::i#2 main::pos#1 ] ( [ main::i#2 main::pos#1 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Statement [5] main::pos#1 = main::pos#2 + main::move [ main::i#2 main::pos#1 ] ( [ main::i#2 main::pos#1 ] { } ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:3 [ main::pos#2 main::pos#1 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 303: zp[1]:3 [ main::pos#2 main::pos#1 ] 26.71: zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 2911 combination reg byte a [ main::pos#2 main::pos#1 ] reg byte x [ main::i#2 main::i#1 ]
|
||||
Uplifting [] best 2911 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Demonstrates error "Block referenced, but not found in program."
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="block-error-1.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.const move = 1
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [2] if(main::i#2!=8) goto main::@2 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #8
|
||||
bne __b2_from___b1
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [3] return
|
||||
rts
|
||||
// [4] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
__b2_from___b1:
|
||||
// [4] phi main::pos#2 = 1 [phi:main::@1->main::@2#0] -- vbuaa=vbuc1
|
||||
lda #1
|
||||
jmp __b2
|
||||
// [4] phi from main::@3 to main::@2 [phi:main::@3->main::@2]
|
||||
__b2_from___b3:
|
||||
// [4] phi main::pos#2 = main::pos#1 [phi:main::@3->main::@2#0] -- register_copy
|
||||
jmp __b2
|
||||
// main::@2
|
||||
__b2:
|
||||
// [5] main::pos#1 = main::pos#2 + main::move -- vbuaa=vbuaa_plus_vbuc1
|
||||
clc
|
||||
adc #move
|
||||
// [6] if(0==main::pos#1) goto main::@3 -- 0_eq_vbuaa_then_la1
|
||||
cmp #0
|
||||
beq __b3
|
||||
// [7] phi from main::@2 to main::@4 [phi:main::@2->main::@4]
|
||||
__b4_from___b2:
|
||||
jmp __b4
|
||||
// main::@4
|
||||
__b4:
|
||||
jmp __b3
|
||||
// main::@3
|
||||
__b3:
|
||||
// [8] if(0!=main::pos#1) goto main::@2 -- 0_neq_vbuaa_then_la1
|
||||
cmp #0
|
||||
bne __b2_from___b3
|
||||
jmp __b5
|
||||
// main::@5
|
||||
__b5:
|
||||
// [9] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [1] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
|
||||
__b1_from___b5:
|
||||
// [1] phi main::i#2 = main::i#1 [phi:main::@5->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __b2
|
||||
Removing instruction jmp __b4
|
||||
Removing instruction jmp __b3
|
||||
Removing instruction jmp __b5
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label __b2_from___b3 with __b2
|
||||
Removing instruction __b2_from___b3:
|
||||
Removing instruction __b4_from___b2:
|
||||
Removing instruction __b4:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1_from_main:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __b5:
|
||||
Removing instruction __b1_from___b5:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Relabelling long label __b2_from___b1 to __b4
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
Removing instruction jmp __b2
|
||||
Removing instruction beq __b3
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __b3:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
void main()
|
||||
byte main::i
|
||||
byte main::i#1 reg byte x 22.0
|
||||
byte main::i#2 reg byte x 4.714285714285714
|
||||
constant byte main::move = 1
|
||||
byte main::pos
|
||||
byte main::pos#1 reg byte a 101.0
|
||||
byte main::pos#2 reg byte a 202.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::pos#2 main::pos#1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 1371
|
||||
|
||||
// File Comments
|
||||
// Demonstrates error "Block referenced, but not found in program."
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="block-error-1.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.const move = 1
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [1] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// main::@1
|
||||
__b1:
|
||||
// for(char i=0;i!=8;i++)
|
||||
// [2] if(main::i#2!=8) goto main::@2 -- vbuxx_neq_vbuc1_then_la1
|
||||
cpx #8
|
||||
bne __b4
|
||||
// main::@return
|
||||
// }
|
||||
// [3] return
|
||||
rts
|
||||
// [4] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
__b4:
|
||||
// [4] phi main::pos#2 = 1 [phi:main::@1->main::@2#0] -- vbuaa=vbuc1
|
||||
lda #1
|
||||
// [4] phi from main::@3 to main::@2 [phi:main::@3->main::@2]
|
||||
// [4] phi main::pos#2 = main::pos#1 [phi:main::@3->main::@2#0] -- register_copy
|
||||
// main::@2
|
||||
__b2:
|
||||
// pos += move
|
||||
// [5] main::pos#1 = main::pos#2 + main::move -- vbuaa=vbuaa_plus_vbuc1
|
||||
clc
|
||||
adc #move
|
||||
// if(pos)
|
||||
// [6] if(0==main::pos#1) goto main::@3 -- 0_eq_vbuaa_then_la1
|
||||
cmp #0
|
||||
// [7] phi from main::@2 to main::@4 [phi:main::@2->main::@4]
|
||||
// main::@4
|
||||
// main::@3
|
||||
// while(pos && vacant)
|
||||
// [8] if(0!=main::pos#1) goto main::@2 -- 0_neq_vbuaa_then_la1
|
||||
cmp #0
|
||||
bne __b2
|
||||
// main::@5
|
||||
// for(char i=0;i!=8;i++)
|
||||
// [9] main::i#1 = ++ main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
// [1] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
|
||||
// [1] phi main::i#2 = main::i#1 [phi:main::@5->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
}
|
||||
// File Data
|
||||
|
11
src/test/ref/block-error-1.sym
Normal file
11
src/test/ref/block-error-1.sym
Normal file
@ -0,0 +1,11 @@
|
||||
void main()
|
||||
byte main::i
|
||||
byte main::i#1 reg byte x 22.0
|
||||
byte main::i#2 reg byte x 4.714285714285714
|
||||
constant byte main::move = 1
|
||||
byte main::pos
|
||||
byte main::pos#1 reg byte a 101.0
|
||||
byte main::pos#2 reg byte a 202.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::pos#2 main::pos#1 ]
|
32
src/test/ref/block-error-2.asm
Normal file
32
src/test/ref/block-error-2.asm
Normal file
@ -0,0 +1,32 @@
|
||||
// Demonstrates error "Sequence does not contain all blocks from the program."
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="block-error-2.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)
|
||||
.segment Code
|
||||
main: {
|
||||
.const move = 1
|
||||
ldx #1
|
||||
txa
|
||||
__b1:
|
||||
// pos += move
|
||||
clc
|
||||
adc #move
|
||||
// if(pos)
|
||||
cmp #0
|
||||
beq __b2
|
||||
ldx #0
|
||||
__b2:
|
||||
// while(pos && vacant)
|
||||
cmp #0
|
||||
beq __breturn
|
||||
cpx #0
|
||||
bne __b1
|
||||
__breturn:
|
||||
// }
|
||||
rts
|
||||
}
|
24
src/test/ref/block-error-2.cfg
Normal file
24
src/test/ref/block-error-2.cfg
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
[1] main::vacant#3 = phi( main/1, main::@3/main::vacant#2 )
|
||||
[1] main::pos#2 = phi( main/1, main::@3/main::pos#1 )
|
||||
[2] main::pos#1 = main::pos#2 + main::move
|
||||
[3] if(0==main::pos#1) goto main::@4
|
||||
to:main::@2
|
||||
main::@4: scope:[main] from main::@1
|
||||
[4] phi()
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@4
|
||||
[5] main::vacant#2 = phi( main::@4/main::vacant#3, main::@1/0 )
|
||||
[6] if(0==main::pos#1) goto main::@return
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[7] if(0!=main::vacant#2) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2 main::@3
|
||||
[8] return
|
||||
to:@return
|
357
src/test/ref/block-error-2.log
Normal file
357
src/test/ref/block-error-2.log
Normal file
@ -0,0 +1,357 @@
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
main::pos#0 = 1
|
||||
main::vacant#0 = 1
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
main::vacant#3 = phi( main/main::vacant#0, main::@2/main::vacant#2 )
|
||||
main::pos#2 = phi( main/main::pos#0, main::@2/main::pos#3 )
|
||||
main::pos#1 = main::pos#2 + main::move
|
||||
main::$2 = 0 != main::pos#1
|
||||
main::$0 = ! main::$2
|
||||
if(main::$0) goto main::@2
|
||||
to:main::@3
|
||||
main::@2: scope:[main] from main::@1 main::@3
|
||||
main::vacant#2 = phi( main::@1/main::vacant#3, main::@3/main::vacant#1 )
|
||||
main::pos#3 = phi( main::@1/main::pos#1, main::@3/main::pos#4 )
|
||||
main::$1 = main::pos#3 && main::vacant#2
|
||||
if(main::$1) goto main::@1
|
||||
to:main::@return
|
||||
main::@3: scope:[main] from main::@1
|
||||
main::pos#4 = phi( main::@1/main::pos#1 )
|
||||
main::vacant#1 = 0
|
||||
to:main::@2
|
||||
main::@return: scope:[main] from main::@2
|
||||
return
|
||||
to:@return
|
||||
|
||||
void __start()
|
||||
__start: scope:[__start] from
|
||||
call main
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start
|
||||
to:__start::@return
|
||||
__start::@return: scope:[__start] from __start::@1
|
||||
return
|
||||
to:@return
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
void __start()
|
||||
void main()
|
||||
bool~ main::$0
|
||||
bool~ main::$1
|
||||
bool~ main::$2
|
||||
constant byte main::move = 1
|
||||
byte main::pos
|
||||
byte main::pos#0
|
||||
byte main::pos#1
|
||||
byte main::pos#2
|
||||
byte main::pos#3
|
||||
byte main::pos#4
|
||||
byte main::vacant
|
||||
byte main::vacant#0
|
||||
byte main::vacant#1
|
||||
byte main::vacant#2
|
||||
byte main::vacant#3
|
||||
|
||||
Adding number conversion cast (unumber) 0 in main::$2 = 0 != main::pos#1
|
||||
Adding number conversion cast (unumber) 0 in main::vacant#1 = 0
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast main::vacant#1 = (unumber)0
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Inversing boolean not [5] main::$0 = 0 == main::pos#1 from [4] main::$2 = 0 != main::pos#1
|
||||
Successful SSA optimization Pass2UnaryNotSimplification
|
||||
Alias main::pos#1 = main::pos#4
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Alias main::pos#1 = main::pos#3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Simple Condition main::$0 [5] if(0==main::pos#1) goto main::@2
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Rewriting && if()-condition to two if()s [7] main::$1 = main::pos#1 && main::vacant#2
|
||||
Successful SSA optimization Pass2ConditionalAndOrRewriting
|
||||
Warning! Adding boolean cast to non-boolean condition main::pos#1
|
||||
Warning! Adding boolean cast to non-boolean condition main::vacant#2
|
||||
Constant main::pos#0 = 1
|
||||
Constant main::vacant#0 = 1
|
||||
Constant main::vacant#1 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Removing unused procedure __start
|
||||
Removing unused procedure block __start
|
||||
Removing unused procedure block __start::@1
|
||||
Removing unused procedure block __start::@return
|
||||
Successful SSA optimization PassNEliminateEmptyStart
|
||||
Adding number conversion cast (unumber) 0 in [4] main::$3 = 0 != main::pos#1
|
||||
Adding number conversion cast (unumber) 0 in [9] main::$4 = 0 != main::vacant#2
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 0
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 0
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Simple Condition main::$3 [5] if(0!=main::pos#1) goto main::@4
|
||||
Simple Condition main::$4 [8] if(0!=main::vacant#2) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Negating conditional jump and destination [5] if(0==main::pos#1) goto main::@return
|
||||
Successful SSA optimization Pass2ConditionalJumpSequenceImprovement
|
||||
Inlining constant with var siblings main::pos#0
|
||||
Inlining constant with var siblings main::vacant#0
|
||||
Inlining constant with var siblings main::vacant#1
|
||||
Constant inlined main::vacant#0 = 1
|
||||
Constant inlined main::vacant#1 = 0
|
||||
Constant inlined main::pos#0 = 1
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Added new block during phi lifting main::@5(between main::@4 and main::@1)
|
||||
Added new block during phi lifting main::@6(between main::@1 and main::@2)
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@3
|
||||
CALL GRAPH
|
||||
|
||||
Created 3 initial phi equivalence classes
|
||||
Coalesced [9] main::pos#5 = main::pos#1
|
||||
Coalesced [10] main::vacant#4 = main::vacant#2
|
||||
Coalesced (already) [11] main::vacant#5 = main::vacant#3
|
||||
Coalesced down to 2 phi equivalence classes
|
||||
Culled Empty Block label main::@3
|
||||
Culled Empty Block label main::@5
|
||||
Renumbering block main::@4 to main::@3
|
||||
Renumbering block main::@6 to main::@4
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@4
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@3
|
||||
[1] main::vacant#3 = phi( main/1, main::@3/main::vacant#2 )
|
||||
[1] main::pos#2 = phi( main/1, main::@3/main::pos#1 )
|
||||
[2] main::pos#1 = main::pos#2 + main::move
|
||||
[3] if(0==main::pos#1) goto main::@4
|
||||
to:main::@2
|
||||
main::@4: scope:[main] from main::@1
|
||||
[4] phi()
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@4
|
||||
[5] main::vacant#2 = phi( main::@4/main::vacant#3, main::@1/0 )
|
||||
[6] if(0==main::pos#1) goto main::@return
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[7] if(0!=main::vacant#2) goto main::@1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2 main::@3
|
||||
[8] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
byte main::pos
|
||||
byte main::pos#1 7.333333333333333
|
||||
byte main::pos#2 22.0
|
||||
byte main::vacant
|
||||
byte main::vacant#2 11.0
|
||||
byte main::vacant#3 5.5
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::pos#2 main::pos#1 ]
|
||||
[ main::vacant#3 main::vacant#2 ]
|
||||
Complete equivalence classes
|
||||
[ main::pos#2 main::pos#1 ]
|
||||
[ main::vacant#3 main::vacant#2 ]
|
||||
Allocated zp[1]:2 [ main::pos#2 main::pos#1 ]
|
||||
Allocated zp[1]:3 [ main::vacant#3 main::vacant#2 ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [2] main::pos#1 = main::pos#2 + main::move [ main::vacant#3 main::pos#1 ] ( [ main::vacant#3 main::pos#1 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:3 [ main::vacant#3 main::vacant#2 ]
|
||||
Statement [2] main::pos#1 = main::pos#2 + main::move [ main::vacant#3 main::pos#1 ] ( [ main::vacant#3 main::pos#1 ] { } ) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ main::pos#2 main::pos#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:3 [ main::vacant#3 main::vacant#2 ] : zp[1]:3 , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 29.33: zp[1]:2 [ main::pos#2 main::pos#1 ] 16.5: zp[1]:3 [ main::vacant#3 main::vacant#2 ]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 451 combination reg byte a [ main::pos#2 main::pos#1 ] reg byte x [ main::vacant#3 main::vacant#2 ]
|
||||
Uplifting [] best 451 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Demonstrates error "Sequence does not contain all blocks from the program."
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="block-error-2.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.const move = 1
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
// [1] phi main::vacant#3 = 1 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #1
|
||||
// [1] phi main::pos#2 = 1 [phi:main->main::@1#1] -- vbuaa=vbuc1
|
||||
lda #1
|
||||
jmp __b1
|
||||
// [1] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
__b1_from___b3:
|
||||
// [1] phi main::vacant#3 = main::vacant#2 [phi:main::@3->main::@1#0] -- register_copy
|
||||
// [1] phi main::pos#2 = main::pos#1 [phi:main::@3->main::@1#1] -- register_copy
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [2] main::pos#1 = main::pos#2 + main::move -- vbuaa=vbuaa_plus_vbuc1
|
||||
clc
|
||||
adc #move
|
||||
// [3] if(0==main::pos#1) goto main::@4 -- 0_eq_vbuaa_then_la1
|
||||
cmp #0
|
||||
beq __b4_from___b1
|
||||
// [5] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
__b2_from___b1:
|
||||
// [5] phi main::vacant#2 = 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp __b2
|
||||
// [4] phi from main::@1 to main::@4 [phi:main::@1->main::@4]
|
||||
__b4_from___b1:
|
||||
jmp __b4
|
||||
// main::@4
|
||||
__b4:
|
||||
// [5] phi from main::@4 to main::@2 [phi:main::@4->main::@2]
|
||||
__b2_from___b4:
|
||||
// [5] phi main::vacant#2 = main::vacant#3 [phi:main::@4->main::@2#0] -- register_copy
|
||||
jmp __b2
|
||||
// main::@2
|
||||
__b2:
|
||||
// [6] if(0==main::pos#1) goto main::@return -- 0_eq_vbuaa_then_la1
|
||||
cmp #0
|
||||
beq __breturn
|
||||
jmp __b3
|
||||
// main::@3
|
||||
__b3:
|
||||
// [7] if(0!=main::vacant#2) goto main::@1 -- 0_neq_vbuxx_then_la1
|
||||
cpx #0
|
||||
bne __b1_from___b3
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __b4
|
||||
Removing instruction jmp __b2
|
||||
Removing instruction jmp __b3
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing instruction lda #1 with TXA
|
||||
Replacing label __b4_from___b1 with __b2
|
||||
Replacing label __b1_from___b3 with __b1
|
||||
Removing instruction __b1_from___b3:
|
||||
Removing instruction __b4_from___b1:
|
||||
Removing instruction __b4:
|
||||
Removing instruction __b2_from___b4:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b1_from_main:
|
||||
Removing instruction __b2_from___b1:
|
||||
Removing instruction __b3:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __b2
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
void main()
|
||||
constant byte main::move = 1
|
||||
byte main::pos
|
||||
byte main::pos#1 reg byte a 7.333333333333333
|
||||
byte main::pos#2 reg byte a 22.0
|
||||
byte main::vacant
|
||||
byte main::vacant#2 reg byte x 11.0
|
||||
byte main::vacant#3 reg byte x 5.5
|
||||
|
||||
reg byte a [ main::pos#2 main::pos#1 ]
|
||||
reg byte x [ main::vacant#3 main::vacant#2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 241
|
||||
|
||||
// File Comments
|
||||
// Demonstrates error "Sequence does not contain all blocks from the program."
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="block-error-2.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
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.const move = 1
|
||||
// [1] phi from main to main::@1 [phi:main->main::@1]
|
||||
// [1] phi main::vacant#3 = 1 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #1
|
||||
// [1] phi main::pos#2 = 1 [phi:main->main::@1#1] -- vbuaa=vbuc1
|
||||
txa
|
||||
// [1] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
// [1] phi main::vacant#3 = main::vacant#2 [phi:main::@3->main::@1#0] -- register_copy
|
||||
// [1] phi main::pos#2 = main::pos#1 [phi:main::@3->main::@1#1] -- register_copy
|
||||
// main::@1
|
||||
__b1:
|
||||
// pos += move
|
||||
// [2] main::pos#1 = main::pos#2 + main::move -- vbuaa=vbuaa_plus_vbuc1
|
||||
clc
|
||||
adc #move
|
||||
// if(pos)
|
||||
// [3] if(0==main::pos#1) goto main::@4 -- 0_eq_vbuaa_then_la1
|
||||
cmp #0
|
||||
beq __b2
|
||||
// [5] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
|
||||
// [5] phi main::vacant#2 = 0 [phi:main::@1->main::@2#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
// [4] phi from main::@1 to main::@4 [phi:main::@1->main::@4]
|
||||
// main::@4
|
||||
// [5] phi from main::@4 to main::@2 [phi:main::@4->main::@2]
|
||||
// [5] phi main::vacant#2 = main::vacant#3 [phi:main::@4->main::@2#0] -- register_copy
|
||||
// main::@2
|
||||
__b2:
|
||||
// while(pos && vacant)
|
||||
// [6] if(0==main::pos#1) goto main::@return -- 0_eq_vbuaa_then_la1
|
||||
cmp #0
|
||||
beq __breturn
|
||||
// main::@3
|
||||
// [7] if(0!=main::vacant#2) goto main::@1 -- 0_neq_vbuxx_then_la1
|
||||
cpx #0
|
||||
bne __b1
|
||||
// main::@return
|
||||
__breturn:
|
||||
// }
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
11
src/test/ref/block-error-2.sym
Normal file
11
src/test/ref/block-error-2.sym
Normal file
@ -0,0 +1,11 @@
|
||||
void main()
|
||||
constant byte main::move = 1
|
||||
byte main::pos
|
||||
byte main::pos#1 reg byte a 7.333333333333333
|
||||
byte main::pos#2 reg byte a 22.0
|
||||
byte main::vacant
|
||||
byte main::vacant#2 reg byte x 11.0
|
||||
byte main::vacant#3 reg byte x 5.5
|
||||
|
||||
reg byte a [ main::pos#2 main::pos#1 ]
|
||||
reg byte x [ main::vacant#3 main::vacant#2 ]
|
Loading…
Reference in New Issue
Block a user