1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-23 23:32:55 +00:00

Merge remote-tracking branch 'origin/master' into 180-type-system

This commit is contained in:
jespergravgaard 2019-04-27 08:13:57 +02:00
commit 93937b60d0
27 changed files with 12462 additions and 10 deletions

View File

@ -222,6 +222,7 @@ public class Compiler {
assertions.add(new Pass2AssertNoLabels(program));
assertions.add(new Pass2AssertSingleAssignment(program));
assertions.add(new Pass2AssertRValues(program));
assertions.add(new Pass2AssertPhiPredecessors(program));
for(Pass2SsaAssertion assertion : assertions) {
assertion.check();
}

View File

@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementLabel;
import dk.camelot64.kickc.model.statements.StatementProcedureBegin;
import dk.camelot64.kickc.model.statements.StatementProcedureEnd;
import dk.camelot64.kickc.model.values.LabelRef;
import java.util.ArrayList;
import java.util.List;
@ -11,7 +12,7 @@ import java.util.List;
/** A sequence of Statements */
public class StatementSequence {
private List<Statement> statements;
private ArrayList<Statement> statements;
public StatementSequence() {
this.statements = new ArrayList<>();
@ -43,4 +44,17 @@ public class StatementSequence {
return out.toString();
}
/**
* Look backwar from the end of the sequence and find the last label
* @return The label of the block, currently being build
*/
public LabelRef getCurrentBlockLabel() {
for(int i = statements.size()-1; i >= 0; i--) {
Statement statement = statements.get(i);
if(statement instanceof StatementLabel) {
return ((StatementLabel) statement).getLabel();
}
}
return null;
}
}

View File

@ -5,6 +5,7 @@ import dk.camelot64.kickc.model.types.SymbolType;
import dk.camelot64.kickc.model.types.SymbolTypeInteger;
import dk.camelot64.kickc.model.types.SymbolTypePointer;
import dk.camelot64.kickc.model.types.SymbolTypeSimple;
import dk.camelot64.kickc.model.values.ConstantChar;
import dk.camelot64.kickc.model.values.ConstantInteger;
import dk.camelot64.kickc.model.values.ConstantLiteral;
import dk.camelot64.kickc.model.values.ConstantPointer;
@ -24,6 +25,8 @@ public class OperatorMinus extends OperatorBinary {
} else if(left instanceof ConstantPointer && right instanceof ConstantInteger) {
long location = ((ConstantPointer) left).getLocation() - ((ConstantInteger) right).getInteger();
return new ConstantPointer(location, ((ConstantPointer) left).getElementType());
} else if(left instanceof ConstantChar && right instanceof ConstantInteger) {
return new ConstantInteger(((ConstantChar) left).getChar() - ((ConstantInteger) right).getInteger());
}
throw new CompileError("Calculation not implemented " + left + " " + getOperator() + " " + right);
}

View File

@ -1371,18 +1371,20 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
RValue falseValue = (RValue) this.visit(ctx.expr(2));
VariableRef falseVar = getCurrentScope().addVariableIntermediate().getRef();
sequence.addStatement(new StatementAssignment(falseVar, null, null, falseValue, new StatementSource(ctx), Comment.NO_COMMENTS));
LabelRef falseExitLabel = sequence.getCurrentBlockLabel();
sequence.addStatement(new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
sequence.addStatement(new StatementLabel(trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
RValue trueValue = (RValue) this.visit(ctx.expr(1));
VariableRef trueVar = getCurrentScope().addVariableIntermediate().getRef();
sequence.addStatement(new StatementAssignment(trueVar, null, null, trueValue, new StatementSource(ctx), Comment.NO_COMMENTS));
LabelRef trueExitLabel = sequence.getCurrentBlockLabel();
sequence.addStatement(new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
StatementPhiBlock phiBlock = new StatementPhiBlock(Comment.NO_COMMENTS);
phiBlock.setSource(new StatementSource(ctx));
VariableRef finalVar = getCurrentScope().addVariableIntermediate().getRef();
StatementPhiBlock.PhiVariable phiVariable = phiBlock.addPhiVariable(finalVar);
phiVariable.setrValue(trueLabel.getRef(), trueVar);
phiVariable.setrValue(falseLabel.getRef(), falseVar);
phiVariable.setrValue(trueExitLabel, trueVar);
phiVariable.setrValue(falseExitLabel, falseVar);
sequence.addStatement(phiBlock);
return finalVar;
}

View File

@ -197,7 +197,7 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
VariableRef phiLValVarRef = phiVariable.getVariable();
VariableVersion versioned = (VariableVersion) getScope().getVariable(phiLValVarRef);
VariableUnversioned unversioned = versioned.getVersionOf();
List<ControlFlowBlock> predecessors = getPredecessors(block);
List<ControlFlowBlock> predecessors = getPhiPredecessors(block, getProgram());
for(ControlFlowBlock predecessor : predecessors) {
LabelRef predecessorLabel = predecessor.getLabel();
Map<VariableUnversioned, VariableVersion> predecessorMap = symbolMap.get(predecessorLabel);
@ -245,15 +245,15 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
* @param block The block to examine
* @return All predecessor blocks
*/
private List<ControlFlowBlock> getPredecessors(ControlFlowBlock block) {
List<ControlFlowBlock> predecessors = getGraph().getPredecessors(block);
Symbol symbol = getScope().getSymbol(block.getLabel());
public static List<ControlFlowBlock> getPhiPredecessors(ControlFlowBlock block, Program program) {
List<ControlFlowBlock> predecessors = program.getGraph().getPredecessors(block);
Symbol symbol = program.getScope().getSymbol(block.getLabel());
if(symbol instanceof Procedure) {
Procedure procedure = (Procedure) symbol;
if(procedure.getInterruptType()!=null || Pass2ConstantIdentification.isAddressOfUsed(procedure.getRef(), getProgram())) {
if(procedure.getInterruptType()!=null || Pass2ConstantIdentification.isAddressOfUsed(procedure.getRef(), program)) {
// Find all root-level predecessors to the main block
ControlFlowBlock mainBlock = getGraph().getBlock(new LabelRef(SymbolRef.MAIN_PROC_NAME));
List<ControlFlowBlock> mainPredecessors = getGraph().getPredecessors(mainBlock);
ControlFlowBlock mainBlock = program.getGraph().getBlock(new LabelRef(SymbolRef.MAIN_PROC_NAME));
List<ControlFlowBlock> mainPredecessors = program.getGraph().getPredecessors(mainBlock);
for(ControlFlowBlock mainPredecessor : mainPredecessors) {
if(mainPredecessor.getScope().equals(ScopeRef.ROOT)) {
predecessors.add(mainPredecessor);

View File

@ -0,0 +1,39 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.values.LabelRef;
import java.util.List;
import java.util.stream.Collectors;
/** Asserts that the program does not contain any predecessors in Phi-blocks that are not true predecessors */
public class Pass2AssertPhiPredecessors extends Pass2SsaAssertion {
public Pass2AssertPhiPredecessors(Program program) {
super(program);
}
@Override
public void check() throws AssertionFailed {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
if(block.hasPhiBlock()) {
StatementPhiBlock phiBlock = block.getPhiBlock();
List<ControlFlowBlock> phiPredecessors = Pass1GenerateSingleStaticAssignmentForm.getPhiPredecessors(block, getProgram());
List<LabelRef> predecessors =
phiPredecessors.stream().map(ControlFlowBlock::getLabel).collect(Collectors.toList());
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(!predecessors.contains(phiRValue.getPredecessor())) {
throw new CompileError("INTERNAL ERROR! Block "+block.getLabel()+" phi references non-predecessor block "+phiRValue.getPredecessor()+
"\n "+phiBlock.toString(getProgram(), false));
}
}
}
}
}
}
}

View File

@ -32,6 +32,27 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testSimpleLoop() throws IOException, URISyntaxException {
compileAndCompare("simple-loop");
}
@Test
public void testLiteralCharMinusNumber() throws IOException, URISyntaxException {
compileAndCompare("literal-char-minus-number");
}
@Test
public void testPaulNelsenSandboxTernaryError() throws IOException, URISyntaxException {
compileAndCompare("sandbox-ternary-error", log().verboseParse().verboseCreateSsa().setVerboseSSAOptimize().verboseStatementSequence());
}
@Test
public void testPaulNelsenSandbox() throws IOException, URISyntaxException {
compileAndCompare("sandbox");
}
//@Test
//public void testPointerCast3() throws IOException, URISyntaxException {
// compileAndCompare("pointer-cast-3");

View File

@ -0,0 +1,6 @@
// Tests subtracting a number from a literal char
void main() {
const byte* SCREEN = 0x0400;
*SCREEN = 'a' - 1;
}

View File

@ -0,0 +1,13 @@
// Demonstrates error with nested ternary operator
void main(void) {
const byte* SCREEN = 0x0400;
for ( byte b: 0..2 ) {
*SCREEN = (b == 0) ? 'a' : ((b == 1) ? 'b' : 'c');
}
}

126
src/test/kc/sandbox.kc Normal file
View File

@ -0,0 +1,126 @@
import "division"
const byte * zp1 = 0x61; // #define zp1 *(byte *)0x61 -- allows "zp1" vs "*zp1" below -- not supported -- https://gitlab.com/camelot/kickc/issues/169
const byte * zp2 = 0x62;
const byte * TIMEHI = 0xA1;
const byte * TIMELO = 0xA2;
const byte * VICBANK = 0xD018;
byte[16] buf16; // "char buf16[16]" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/162
byte[100] strTemp;
// simple 'utoa' without using multiply or divide
word append(byte *dst, word value, word sub){
*dst = '0';
while (value >= sub){ ++*dst; value -= sub; }
return value;
}
void utoa(word value, byte *dst){
byte bStarted = 0;
if (bStarted == 1 || value >= 10000){ value = append(dst++, value, 10000); bStarted = 1; }
if (bStarted == 1 || value >= 1000){ value = append(dst++, value, 1000); bStarted = 1; }
if (bStarted == 1 || value >= 100){ value = append(dst++, value, 100); bStarted = 1; }
if (bStarted == 1 || value >= 10){ value = append(dst++, value, 10); bStarted = 1; }
*dst++ = '0' + (byte)value;
*dst = 0;
}
byte myprintf(byte *dst, byte *str, word w1, word w2, word w3) {
byte bArg = 0, bFormat = 0, bLen = 0;
byte bLeadZero, bDigits, bTrailing; // formats
byte b, digit;
byte[6] buf6;
word w;
for (; *str != 0; ++str) {
b = *str;
if (bFormat != 0) { // "(bFormat)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/135
if (b == '0') { bLeadZero = 1; continue; }
if (b >= '1' && b <= '9') { bDigits = b - '0'; continue; }
if (b == '-') { bTrailing = 1; continue; }
if (b == 'c'){ // "switch" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/170
dst[bLen++] = (byte)w;
} else if (b == 'd') {
utoa(w, buf6);
b = 1; while(buf6[b] != 0) ++b; // strlen() not supported -- https://gitlab.com/camelot/kickc/issues/182
// if (bDigits > b) is used because non-executing for loop is not supported -- https://gitlab.com/camelot/kickc/issues/183
if (bTrailing == 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = (bLeadZero == 0) ? ' ' : '0';
for (digit = 0; digit < b; ++digit) dst[bLen++] = buf6[digit];
if (bTrailing != 0 && bDigits > b) for (; bDigits > b; --bDigits) dst[bLen++] = ' ';
} else if (b == 'x' || b == 'X'){ // hex
b = (w >> 4) & 0xF;
dst[bLen++] = (b < 10 ? '0' : 0x57) + b; // "('a' - 10)" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/184 [FIXED]
b = w & 0xF; dst[bLen++] = (b < 10 ? '0' : 0x57) + b;
}
bFormat = 0;
continue;
}
if (b == '%') {
bFormat = 1;
bLeadZero = 0; bDigits = 1; bTrailing = 0; // default format
//w = (bArg == 0) ? w1 : ((bArg == 1) ? w2 : w3); -- "?" is the normal way, but error "sequence does not contain all blocks" -- https://gitlab.com/camelot/kickc/issues/185 [FIXED]
if (bArg == 0) w = w1;
else if (bArg == 1) w = w2;
else w = w3;
++bArg;
continue;
}
if (b >= 0x41 && b <= 0x5A) b += 0x20; // swap 0x41 / 0x61 when in lower case mode
dst[bLen++] = b;
}
dst[bLen] = 0;
return bLen;
}
void Print(){ // can this assembly be placed in a separate file and call it from the C code here?
asm {
ldy #0
loop:
lda strTemp,y
beq done
jsr $FFD2
iny
jmp loop
done:
}
}
word div10(word val){
val = (val >> 1) + 1;
val += val << 1;
val += val >> 4;
val += val >> 4 >> 4; // >> 8 is not supported?
return val >> 4;
}
int main(void) {
word u;
word v;
*VICBANK = 23; // lower case mode
// test performance of 'div16u(10)'
u = 28293;
for (*zp1 = 0; *zp1 < 10; ++*zp1){
*TIMEHI = 0;
*TIMELO = 0;
for (*zp2 = 0; *zp2 < 200; ++*zp2) v = div16u(u, 10);
// lower case letters in string literal are placed in string as 0x01-0x1A, should be 0x61-0x7A
// -- as a side-effect of above issue, we can use "m" for carriage return. The normal way is the escape code "\r" but that is not supported --
myprintf(strTemp, "200 DIV16U: %5d,%4d IN %04d FRAMESm", u, v, ((word)*TIMEHI << 8) + (word)*TIMELO);
Print();
u -= 1234;
}
// test performance of 'div10'
u = 28293;
for (*zp1 = 0; *zp1 < 10; ++*zp1){
*TIMEHI = 0;
*TIMELO = 0;
for (*zp2 = 0; *zp2 < 200; ++*zp2) v = div10(u);
myprintf(strTemp, "200 DIV10 : %5d,%4d IN %04d FRAMESm", u, v, ((word)*TIMEHI << 8) + (word)*TIMELO);
Print();
u -= 1234;
}
return 0;
}

View File

@ -0,0 +1,8 @@
void main() {
const unsigned char* SCREEN = 0x0400;
for( unsigned char i = 0; i<128; i+=2) {
SCREEN[i] = 'a';
(*(unsigned char*)0xD020)=0;
}
}

View File

@ -0,0 +1,10 @@
// Tests subtracting a number from a literal char
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
.label SCREEN = $400
lda #'a'-1
sta SCREEN
rts
}

View File

@ -0,0 +1,15 @@
@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] *((const byte*) main::SCREEN#0) ← (byte) 'a'-(byte/signed byte/word/signed word/dword/signed dword) 1
to:main::@return
main::@return: scope:[main] from main
[5] return
to:@return

View File

@ -0,0 +1,210 @@
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
(byte/signed byte/word/signed word/dword/signed dword~) main::$0 ← (byte) 'a' - (byte/signed byte/word/signed word/dword/signed dword) 1
*((byte*) main::SCREEN#0) ← (byte/signed byte/word/signed word/dword/signed dword~) main::$0
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/signed byte/word/signed word/dword/signed dword~) main::$0
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
Culled Empty Block (label) @2
Successful SSA optimization Pass2CullEmptyBlocks
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
Constant (const byte/signed byte/word/signed word/dword/signed dword) main::$0 = 'a'-1
Successful SSA optimization Pass2ConstantIdentification
Constant inlined main::$0 = (byte) 'a'-(byte/signed byte/word/signed word/dword/signed dword) 1
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
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
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
[4] *((const byte*) main::SCREEN#0) ← (byte) 'a'-(byte/signed byte/word/signed word/dword/signed dword) 1
to:main::@return
main::@return: scope:[main] from main
[5] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::SCREEN
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
//SEG0 File Comments
// Tests subtracting a number from a literal char
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label SCREEN = $400
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (byte) 'a'-(byte/signed byte/word/signed word/dword/signed dword) 1 -- _deref_pbuc1=vbuc2
lda #'a'-1
sta SCREEN
jmp breturn
//SEG11 main::@return
breturn:
//SEG12 [5] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [4] *((const byte*) main::SCREEN#0) ← (byte) 'a'-(byte/signed byte/word/signed word/dword/signed dword) 1 [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 27 combination
Uplifting [] best 27 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
// Tests subtracting a number from a literal char
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
jsr main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG8 @end
bend:
//SEG9 main
main: {
.label SCREEN = $400
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (byte) 'a'-(byte/signed byte/word/signed word/dword/signed dword) 1 -- _deref_pbuc1=vbuc2
lda #'a'-1
sta SCREEN
jmp breturn
//SEG11 main::@return
breturn:
//SEG12 [5] return
rts
}
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
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
FINAL ASSEMBLER
Score: 12
//SEG0 File Comments
// Tests subtracting a number from a literal char
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [3] phi from @1 to @end [phi:@1->@end]
//SEG8 @end
//SEG9 main
main: {
.label SCREEN = $400
//SEG10 [4] *((const byte*) main::SCREEN#0) ← (byte) 'a'-(byte/signed byte/word/signed word/dword/signed dword) 1 -- _deref_pbuc1=vbuc2
lda #'a'-1
sta SCREEN
//SEG11 main::@return
//SEG12 [5] return
rts
}

View File

@ -0,0 +1,8 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400

View File

@ -0,0 +1,26 @@
// Demonstrates error with nested ternary operator
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
.label SCREEN = $400
ldx #0
b1:
cpx #0
beq b4
cpx #1
beq b2
lda #'c'
jmp b3
b2:
lda #'b'
jmp b3
b4:
lda #'a'
b3:
sta SCREEN
inx
cpx #3
bne b1
rts
}

View File

@ -0,0 +1,34 @@
@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::@3
[5] (byte) main::b#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::b#1 )
[6] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3
to:main::@2
main::@2: scope:[main] from main::@1
[7] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@5
to:main::@4
main::@4: scope:[main] from main::@2
[8] phi()
to:main::@5
main::@5: scope:[main] from main::@2 main::@4
[9] (byte~) main::$5 ← phi( main::@2/(byte) 'b' main::@4/(byte) 'c' )
to:main::@3
main::@3: scope:[main] from main::@1 main::@5
[10] (byte~) main::$7 ← phi( main::@1/(byte) 'a' main::@5/(byte~) main::$5 )
[11] *((const byte*) main::SCREEN#0) ← (byte~) main::$7
[12] (byte) main::b#1 ← ++ (byte) main::b#2
[13] if((byte) main::b#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
[14] return
to:@return

View File

@ -0,0 +1,988 @@
PARSING src/test/kc/sandbox-ternary-error.kc
// Demonstrates error with nested ternary operator
void main(void) {
const byte* SCREEN = 0x0400;
for ( byte b: 0..2 ) {
*SCREEN = (b == 0) ? 'a' : ((b == 1) ? 'b' : 'c');
}
}
STATEMENTS
proc (void()) main()
(byte*) main::SCREEN ← (word/signed word/dword/signed dword) $400
(byte) main:::1::b ← (byte/signed byte/word/signed word/dword/signed dword) 0
main:::1::@1:
(var) main:::1::$0 ← (byte) main:::1::b == (byte/signed byte/word/signed word/dword/signed dword) 0
if((var) main:::1::$0) goto main:::1::@2
main:::1::@3:
(var) main:::1::$1 ← (byte) main:::1::b == (byte/signed byte/word/signed word/dword/signed dword) 1
if((var) main:::1::$1) goto main:::1::@5
main:::1::@6:
(var) main:::1::$2 ← (byte) 'c'
goto main:::1::@7
main:::1::@5:
(var) main:::1::$3 ← (byte) 'b'
main:::1::@7:
(var) main:::1::$4 ← phi( main:::1::@5/(var) main:::1::$3 main:::1::@6/(var) main:::1::$2 )
(var) main:::1::$5 ← (var) main:::1::$4
goto main:::1::@4
main:::1::@2:
(var) main:::1::$6 ← (byte) 'a'
main:::1::@4:
(var) main:::1::$7 ← phi( main:::1::@2/(var) main:::1::$6 main:::1::@7/(var) main:::1::$5 )
*((byte*) main::SCREEN) ← (var) main:::1::$7
(byte) main:::1::b ← (byte) main:::1::b + rangenext(0,2)
(var) main:::1::$8 ← (byte) main:::1::b != rangelast(0,2)
if((var) main:::1::$8) goto main:::1::@1
main::@return:
return
endproc // main()
call main
SYMBOLS
(label) @1
(label) @begin
(label) @end
(void()) main()
(bool~) main::$0
(bool~) main::$1
(byte~) main::$2
(byte~) main::$3
(byte~) main::$4
(byte~) main::$5
(byte~) main::$6
(byte~) main::$7
(bool~) main::$8
(label) main::@1
(label) main::@10
(label) main::@11
(label) main::@12
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@7
(label) main::@8
(label) main::@9
(label) main::@return
(byte*) main::SCREEN
(byte) main::b
Promoting word/signed word/dword/signed dword to byte* in main::SCREEN ← ((byte*)) $400
INITIAL CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from
[0] (byte*) main::SCREEN ← ((byte*)) (word/signed word/dword/signed dword) $400
[1] (byte) main::b ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@4
[2] (bool~) main::$0 ← (byte) main::b == (byte/signed byte/word/signed word/dword/signed dword) 0
[3] if((bool~) main::$0) goto main::@2
to:main::@8
main::@2: scope:[main] from main::@1 main::@11
[4] (byte~) main::$6 ← (byte) 'a'
to:main::@4
main::@8: scope:[main] from main::@1
to:main::@3
main::@3: scope:[main] from main::@8
[5] (bool~) main::$1 ← (byte) main::b == (byte/signed byte/word/signed word/dword/signed dword) 1
[6] if((bool~) main::$1) goto main::@5
to:main::@9
main::@5: scope:[main] from main::@10 main::@3
[7] (byte~) main::$3 ← (byte) 'b'
to:main::@7
main::@9: scope:[main] from main::@3
to:main::@6
main::@6: scope:[main] from main::@9
[8] (byte~) main::$2 ← (byte) 'c'
to:main::@7
main::@7: scope:[main] from main::@5 main::@6
[9] (byte~) main::$4 ← phi( main::@5/(byte~) main::$3 main::@6/(byte~) main::$2 )
[10] (byte~) main::$5 ← (byte~) main::$4
to:main::@4
main::@10: scope:[main] from
to:main::@5
main::@4: scope:[main] from main::@2 main::@7
[11] (byte~) main::$7 ← phi( main::@2/(byte~) main::$6 main::@7/(byte~) main::$5 )
[12] *((byte*) main::SCREEN) ← (byte~) main::$7
[13] (byte) main::b ← (byte) main::b + rangenext(0,2)
[14] (bool~) main::$8 ← (byte) main::b != rangelast(0,2)
[15] if((bool~) main::$8) goto main::@1
to:main::@12
main::@11: scope:[main] from
to:main::@2
main::@12: scope:[main] from main::@4
to:main::@return
main::@return: scope:[main] from main::@12
[16] return
to:@return
@1: scope:[] from @begin
[17] call main
to:@end
@end: scope:[] from @1
Removing empty block main::@8
Removing empty block main::@9
Removing empty block main::@10
Removing empty block main::@11
Removing empty block main::@12
PROCEDURE MODIFY VARIABLE ANALYSIS
Completing Phi functions...
Completing Phi functions...
Completing Phi functions...
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
(byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@4
(byte) main::b#2 ← phi( main/(byte) main::b#0 main::@4/(byte) main::b#1 )
(bool~) main::$0 ← (byte) main::b#2 == (byte/signed byte/word/signed word/dword/signed dword) 0
if((bool~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte) main::b#5 ← phi( main::@1/(byte) main::b#2 )
(byte~) main::$6 ← (byte) 'a'
to:main::@4
main::@3: scope:[main] from main::@1
(byte) main::b#3 ← phi( main::@1/(byte) main::b#2 )
(bool~) main::$1 ← (byte) main::b#3 == (byte/signed byte/word/signed word/dword/signed dword) 1
if((bool~) main::$1) goto main::@5
to:main::@6
main::@5: scope:[main] from main::@3
(byte) main::b#7 ← phi( main::@3/(byte) main::b#3 )
(byte~) main::$3 ← (byte) 'b'
to:main::@7
main::@6: scope:[main] from main::@3
(byte) main::b#8 ← phi( main::@3/(byte) main::b#3 )
(byte~) main::$2 ← (byte) 'c'
to:main::@7
main::@7: scope:[main] from main::@5 main::@6
(byte) main::b#6 ← phi( main::@5/(byte) main::b#7 main::@6/(byte) main::b#8 )
(byte~) main::$4 ← phi( main::@5/(byte~) main::$3 main::@6/(byte~) main::$2 )
(byte~) main::$5 ← (byte~) main::$4
to:main::@4
main::@4: scope:[main] from main::@2 main::@7
(byte) main::b#4 ← phi( main::@2/(byte) main::b#5 main::@7/(byte) main::b#6 )
(byte~) main::$7 ← phi( main::@2/(byte~) main::$6 main::@7/(byte~) main::$5 )
*((byte*) main::SCREEN#0) ← (byte~) main::$7
(byte) main::b#1 ← (byte) main::b#4 + rangenext(0,2)
(bool~) main::$8 ← (byte) main::b#1 != rangelast(0,2)
if((bool~) main::$8) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
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()
(bool~) main::$0
(bool~) main::$1
(byte~) main::$2
(byte~) main::$3
(byte~) main::$4
(byte~) main::$5
(byte~) main::$6
(byte~) main::$7
(bool~) main::$8
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@7
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(byte) main::b
(byte) main::b#0
(byte) main::b#1
(byte) main::b#2
(byte) main::b#3
(byte) main::b#4
(byte) main::b#5
(byte) main::b#6
(byte) main::b#7
(byte) main::b#8
Culled Empty Block (label) @2
Successful SSA optimization Pass2CullEmptyBlocks
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
(byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@4
(byte) main::b#2 ← phi( main/(byte) main::b#0 main::@4/(byte) main::b#1 )
(bool~) main::$0 ← (byte) main::b#2 == (byte/signed byte/word/signed word/dword/signed dword) 0
if((bool~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte) main::b#5 ← phi( main::@1/(byte) main::b#2 )
(byte~) main::$6 ← (byte) 'a'
to:main::@4
main::@3: scope:[main] from main::@1
(byte) main::b#3 ← phi( main::@1/(byte) main::b#2 )
(bool~) main::$1 ← (byte) main::b#3 == (byte/signed byte/word/signed word/dword/signed dword) 1
if((bool~) main::$1) goto main::@5
to:main::@6
main::@5: scope:[main] from main::@3
(byte) main::b#7 ← phi( main::@3/(byte) main::b#3 )
(byte~) main::$3 ← (byte) 'b'
to:main::@7
main::@6: scope:[main] from main::@3
(byte) main::b#8 ← phi( main::@3/(byte) main::b#3 )
(byte~) main::$2 ← (byte) 'c'
to:main::@7
main::@7: scope:[main] from main::@5 main::@6
(byte) main::b#6 ← phi( main::@5/(byte) main::b#7 main::@6/(byte) main::b#8 )
(byte~) main::$4 ← phi( main::@5/(byte~) main::$3 main::@6/(byte~) main::$2 )
(byte~) main::$5 ← (byte~) main::$4
to:main::@4
main::@4: scope:[main] from main::@2 main::@7
(byte) main::b#4 ← phi( main::@2/(byte) main::b#5 main::@7/(byte) main::b#6 )
(byte~) main::$7 ← phi( main::@2/(byte~) main::$6 main::@7/(byte~) main::$5 )
*((byte*) main::SCREEN#0) ← (byte~) main::$7
(byte) main::b#1 ← (byte) main::b#4 + rangenext(0,2)
(bool~) main::$8 ← (byte) main::b#1 != rangelast(0,2)
if((bool~) main::$8) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
return
to:@return
@1: scope:[] from @begin
call main
to:@end
@end: scope:[] from @1
Alias (byte) main::b#2 = (byte) main::b#5 (byte) main::b#3 (byte) main::b#7 (byte) main::b#8
Alias (byte~) main::$5 = (byte~) main::$4
Successful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
[0] (byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
[1] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@4
[2] (byte) main::b#2 ← phi( main/(byte) main::b#0 main::@4/(byte) main::b#1 )
[3] (bool~) main::$0 ← (byte) main::b#2 == (byte/signed byte/word/signed word/dword/signed dword) 0
[4] if((bool~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
[6] (byte~) main::$6 ← (byte) 'a'
to:main::@4
main::@3: scope:[main] from main::@1
[8] (bool~) main::$1 ← (byte) main::b#2 == (byte/signed byte/word/signed word/dword/signed dword) 1
[9] if((bool~) main::$1) goto main::@5
to:main::@6
main::@5: scope:[main] from main::@3
[11] (byte~) main::$3 ← (byte) 'b'
to:main::@7
main::@6: scope:[main] from main::@3
[13] (byte~) main::$2 ← (byte) 'c'
to:main::@7
main::@7: scope:[main] from main::@5 main::@6
[14] (byte) main::b#6 ← phi( main::@5/(byte) main::b#2 main::@6/(byte) main::b#2 )
[14] (byte~) main::$5 ← phi( main::@5/(byte~) main::$3 main::@6/(byte~) main::$2 )
to:main::@4
main::@4: scope:[main] from main::@2 main::@7
[16] (byte) main::b#4 ← phi( main::@2/(byte) main::b#2 main::@7/(byte) main::b#6 )
[16] (byte~) main::$7 ← phi( main::@2/(byte~) main::$6 main::@7/(byte~) main::$5 )
[17] *((byte*) main::SCREEN#0) ← (byte~) main::$7
[18] (byte) main::b#1 ← (byte) main::b#4 + rangenext(0,2)
[19] (bool~) main::$8 ← (byte) main::b#1 != rangelast(0,2)
[20] if((bool~) main::$8) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
[21] return
to:@return
@1: scope:[] from @begin
[22] call main
to:@end
@end: scope:[] from @1
Alias (byte) main::b#2 = (byte) main::b#6
Successful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
[0] (byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
[1] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@4
[2] (byte) main::b#2 ← phi( main/(byte) main::b#0 main::@4/(byte) main::b#1 )
[3] (bool~) main::$0 ← (byte) main::b#2 == (byte/signed byte/word/signed word/dword/signed dword) 0
[4] if((bool~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
[6] (byte~) main::$6 ← (byte) 'a'
to:main::@4
main::@3: scope:[main] from main::@1
[8] (bool~) main::$1 ← (byte) main::b#2 == (byte/signed byte/word/signed word/dword/signed dword) 1
[9] if((bool~) main::$1) goto main::@5
to:main::@6
main::@5: scope:[main] from main::@3
[11] (byte~) main::$3 ← (byte) 'b'
to:main::@7
main::@6: scope:[main] from main::@3
[13] (byte~) main::$2 ← (byte) 'c'
to:main::@7
main::@7: scope:[main] from main::@5 main::@6
[14] (byte~) main::$5 ← phi( main::@5/(byte~) main::$3 main::@6/(byte~) main::$2 )
to:main::@4
main::@4: scope:[main] from main::@2 main::@7
[16] (byte) main::b#4 ← phi( main::@2/(byte) main::b#2 main::@7/(byte) main::b#2 )
[16] (byte~) main::$7 ← phi( main::@2/(byte~) main::$6 main::@7/(byte~) main::$5 )
[17] *((byte*) main::SCREEN#0) ← (byte~) main::$7
[18] (byte) main::b#1 ← (byte) main::b#4 + rangenext(0,2)
[19] (bool~) main::$8 ← (byte) main::b#1 != rangelast(0,2)
[20] if((bool~) main::$8) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
[21] return
to:@return
@1: scope:[] from @begin
[22] call main
to:@end
@end: scope:[] from @1
Alias (byte) main::b#2 = (byte) main::b#4
Successful SSA optimization Pass2AliasElimination
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
[0] (byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
[1] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@4
[2] (byte) main::b#2 ← phi( main/(byte) main::b#0 main::@4/(byte) main::b#1 )
[3] (bool~) main::$0 ← (byte) main::b#2 == (byte/signed byte/word/signed word/dword/signed dword) 0
[4] if((bool~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
[6] (byte~) main::$6 ← (byte) 'a'
to:main::@4
main::@3: scope:[main] from main::@1
[8] (bool~) main::$1 ← (byte) main::b#2 == (byte/signed byte/word/signed word/dword/signed dword) 1
[9] if((bool~) main::$1) goto main::@5
to:main::@6
main::@5: scope:[main] from main::@3
[11] (byte~) main::$3 ← (byte) 'b'
to:main::@7
main::@6: scope:[main] from main::@3
[13] (byte~) main::$2 ← (byte) 'c'
to:main::@7
main::@7: scope:[main] from main::@5 main::@6
[14] (byte~) main::$5 ← phi( main::@5/(byte~) main::$3 main::@6/(byte~) main::$2 )
to:main::@4
main::@4: scope:[main] from main::@2 main::@7
[16] (byte~) main::$7 ← phi( main::@2/(byte~) main::$6 main::@7/(byte~) main::$5 )
[17] *((byte*) main::SCREEN#0) ← (byte~) main::$7
[18] (byte) main::b#1 ← (byte) main::b#2 + rangenext(0,2)
[19] (bool~) main::$8 ← (byte) main::b#1 != rangelast(0,2)
[20] if((bool~) main::$8) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
[21] return
to:@return
@1: scope:[] from @begin
[22] call main
to:@end
@end: scope:[] from @1
Simple Condition (bool~) main::$0 [4] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2
Simple Condition (bool~) main::$1 [9] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@5
Simple Condition (bool~) main::$8 [20] if((byte) main::b#1!=rangelast(0,2)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
[0] (byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
[1] (byte) main::b#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@4
[2] (byte) main::b#2 ← phi( main/(byte) main::b#0 main::@4/(byte) main::b#1 )
[4] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
[6] (byte~) main::$6 ← (byte) 'a'
to:main::@4
main::@3: scope:[main] from main::@1
[9] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@5
to:main::@6
main::@5: scope:[main] from main::@3
[11] (byte~) main::$3 ← (byte) 'b'
to:main::@7
main::@6: scope:[main] from main::@3
[13] (byte~) main::$2 ← (byte) 'c'
to:main::@7
main::@7: scope:[main] from main::@5 main::@6
[14] (byte~) main::$5 ← phi( main::@5/(byte~) main::$3 main::@6/(byte~) main::$2 )
to:main::@4
main::@4: scope:[main] from main::@2 main::@7
[16] (byte~) main::$7 ← phi( main::@2/(byte~) main::$6 main::@7/(byte~) main::$5 )
[17] *((byte*) main::SCREEN#0) ← (byte~) main::$7
[18] (byte) main::b#1 ← (byte) main::b#2 + rangenext(0,2)
[20] if((byte) main::b#1!=rangelast(0,2)) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
[21] return
to:@return
@1: scope:[] from @begin
[22] call main
to:@end
@end: scope:[] from @1
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
Constant (const byte) main::b#0 = 0
Constant (const byte) main::$6 = 'a'
Constant (const byte) main::$3 = 'b'
Constant (const byte) main::$2 = 'c'
Successful SSA optimization Pass2ConstantIdentification
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
to:main::@1
main::@1: scope:[main] from main main::@4
[2] (byte) main::b#2 ← phi( main/(const byte) main::b#0 main::@4/(byte) main::b#1 )
[4] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
to:main::@4
main::@3: scope:[main] from main::@1
[9] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@5
to:main::@6
main::@5: scope:[main] from main::@3
to:main::@7
main::@6: scope:[main] from main::@3
to:main::@7
main::@7: scope:[main] from main::@5 main::@6
[14] (byte~) main::$5 ← phi( main::@5/(const byte) main::$3 main::@6/(const byte) main::$2 )
to:main::@4
main::@4: scope:[main] from main::@2 main::@7
[16] (byte~) main::$7 ← phi( main::@2/(const byte) main::$6 main::@7/(byte~) main::$5 )
[17] *((const byte*) main::SCREEN#0) ← (byte~) main::$7
[18] (byte) main::b#1 ← (byte) main::b#2 + rangenext(0,2)
[20] if((byte) main::b#1!=rangelast(0,2)) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
[21] return
to:@return
@1: scope:[] from @begin
[22] call main
to:@end
@end: scope:[] from @1
Resolved ranged next value main::b#1 ← ++ main::b#2 to ++
Resolved ranged comparison value if(main::b#1!=rangelast(0,2)) goto main::@1 to (byte/signed byte/word/signed word/dword/signed dword) 3
Culled Empty Block (label) main::@2
Culled Empty Block (label) main::@5
Successful SSA optimization Pass2CullEmptyBlocks
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
to:main::@1
main::@1: scope:[main] from main main::@4
(byte) main::b#2 ← phi( main/(const byte) main::b#0 main::@4/(byte) main::b#1 )
if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@4
to:main::@3
main::@3: scope:[main] from main::@1
if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@7
to:main::@6
main::@6: scope:[main] from main::@3
to:main::@7
main::@7: scope:[main] from main::@3 main::@6
(byte~) main::$5 ← phi( main::@3/(const byte) main::$3 main::@6/(const byte) main::$2 )
to:main::@4
main::@4: scope:[main] from main::@1 main::@7
(byte~) main::$7 ← phi( main::@1/(const byte) main::$6 main::@7/(byte~) main::$5 )
*((const byte*) main::SCREEN#0) ← (byte~) main::$7
(byte) main::b#1 ← ++ (byte) main::b#2
if((byte) main::b#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
return
to:@return
@1: scope:[] from @begin
call main
to:@end
@end: scope:[] from @1
Inlining constant with var siblings (const byte) main::b#0
Constant inlined main::$6 = (byte) 'a'
Constant inlined main::$3 = (byte) 'b'
Constant inlined main::b#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
Constant inlined main::$2 = (byte) 'c'
Successful SSA optimization Pass2ConstantInlining
CONTROL FLOW GRAPH
@begin: scope:[] from
to:@1
main: scope:[main] from @1
to:main::@1
main::@1: scope:[main] from main main::@4
[0] (byte) main::b#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@4/(byte) main::b#1 )
[1] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@4
to:main::@3
main::@3: scope:[main] from main::@1
[2] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@7
to:main::@6
main::@6: scope:[main] from main::@3
to:main::@7
main::@7: scope:[main] from main::@3 main::@6
[3] (byte~) main::$5 ← phi( main::@3/(byte) 'b' main::@6/(byte) 'c' )
to:main::@4
main::@4: scope:[main] from main::@1 main::@7
[4] (byte~) main::$7 ← phi( main::@1/(byte) 'a' main::@7/(byte~) main::$5 )
[5] *((const byte*) main::SCREEN#0) ← (byte~) main::$7
[6] (byte) main::b#1 ← ++ (byte) main::b#2
[7] if((byte) main::b#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
[8] return
to:@return
@1: scope:[] from @begin
[9] call main
to:@end
@end: scope:[] from @1
Added new block during phi lifting main::@13(between main::@4 and main::@1)
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
Adding NOP phi() at start of main::@6
CALL GRAPH
Calls in [] to main:2
Created 3 initial phi equivalence classes
Coalesced [10] main::$9 ← main::$5
Coalesced [16] main::b#9 ← main::b#1
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) main::@13
Renumbering block main::@3 to main::@2
Renumbering block main::@4 to main::@3
Renumbering block main::@6 to main::@4
Renumbering block main::@7 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
Adding NOP phi() at start of main::@4
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::@3
[5] (byte) main::b#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::b#1 )
[6] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3
to:main::@2
main::@2: scope:[main] from main::@1
[7] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@5
to:main::@4
main::@4: scope:[main] from main::@2
[8] phi()
to:main::@5
main::@5: scope:[main] from main::@2 main::@4
[9] (byte~) main::$5 ← phi( main::@2/(byte) 'b' main::@4/(byte) 'c' )
to:main::@3
main::@3: scope:[main] from main::@1 main::@5
[10] (byte~) main::$7 ← phi( main::@1/(byte) 'a' main::@5/(byte~) main::$5 )
[11] *((const byte*) main::SCREEN#0) ← (byte~) main::$7
[12] (byte) main::b#1 ← ++ (byte) main::b#2
[13] if((byte) main::b#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
[14] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte~) main::$5 11.0
(byte~) main::$7 22.0
(byte*) main::SCREEN
(byte) main::b
(byte) main::b#1 16.5
(byte) main::b#2 6.285714285714286
Initial phi equivalence classes
[ main::b#2 main::b#1 ]
[ main::$7 main::$5 ]
Complete equivalence classes
[ main::b#2 main::b#1 ]
[ main::$7 main::$5 ]
Allocated zp ZP_BYTE:2 [ main::b#2 main::b#1 ]
Allocated zp ZP_BYTE:3 [ main::$7 main::$5 ]
INITIAL ASM
//SEG0 File Comments
// Demonstrates error with nested ternary operator
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
bend:
//SEG10 main
main: {
.label SCREEN = $400
.label _5 = 3
.label _7 = 3
.label b = 2
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG12 [5] phi (byte) main::b#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta b
jmp b1
//SEG13 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
//SEG14 [5] phi (byte) main::b#2 = (byte) main::b#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
//SEG15 main::@1
b1:
//SEG16 [6] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3 -- vbuz1_eq_0_then_la1
lda b
cmp #0
beq b3_from_b1
jmp b2
//SEG17 main::@2
b2:
//SEG18 [7] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@5 -- vbuz1_eq_vbuc1_then_la1
lda #1
cmp b
beq b5_from_b2
//SEG19 [8] phi from main::@2 to main::@4 [phi:main::@2->main::@4]
b4_from_b2:
jmp b4
//SEG20 main::@4
b4:
//SEG21 [9] phi from main::@4 to main::@5 [phi:main::@4->main::@5]
b5_from_b4:
//SEG22 [9] phi (byte~) main::$5 = (byte) 'c' [phi:main::@4->main::@5#0] -- vbuz1=vbuc1
lda #'c'
sta _5
jmp b5
//SEG23 [9] phi from main::@2 to main::@5 [phi:main::@2->main::@5]
b5_from_b2:
//SEG24 [9] phi (byte~) main::$5 = (byte) 'b' [phi:main::@2->main::@5#0] -- vbuz1=vbuc1
lda #'b'
sta _5
jmp b5
//SEG25 main::@5
b5:
//SEG26 [10] phi from main::@5 to main::@3 [phi:main::@5->main::@3]
b3_from_b5:
//SEG27 [10] phi (byte~) main::$7 = (byte~) main::$5 [phi:main::@5->main::@3#0] -- register_copy
jmp b3
//SEG28 [10] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
b3_from_b1:
//SEG29 [10] phi (byte~) main::$7 = (byte) 'a' [phi:main::@1->main::@3#0] -- vbuz1=vbuc1
lda #'a'
sta _7
jmp b3
//SEG30 main::@3
b3:
//SEG31 [11] *((const byte*) main::SCREEN#0) ← (byte~) main::$7 -- _deref_pbuc1=vbuz1
lda _7
sta SCREEN
//SEG32 [12] (byte) main::b#1 ← ++ (byte) main::b#2 -- vbuz1=_inc_vbuz1
inc b
//SEG33 [13] if((byte) main::b#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #3
cmp b
bne b1_from_b3
jmp breturn
//SEG34 main::@return
breturn:
//SEG35 [14] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Potential registers zp ZP_BYTE:2 [ main::b#2 main::b#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:3 [ main::$7 main::$5 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 33: zp ZP_BYTE:3 [ main::$7 main::$5 ] 22.79: zp ZP_BYTE:2 [ main::b#2 main::b#1 ]
Uplift Scope []
Uplifting [main] best 563 combination reg byte a [ main::$7 main::$5 ] reg byte x [ main::b#2 main::b#1 ]
Uplifting [] best 563 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
// Demonstrates error with nested ternary operator
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
bend:
//SEG10 main
main: {
.label SCREEN = $400
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG12 [5] phi (byte) main::b#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
jmp b1
//SEG13 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
//SEG14 [5] phi (byte) main::b#2 = (byte) main::b#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
//SEG15 main::@1
b1:
//SEG16 [6] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3 -- vbuxx_eq_0_then_la1
cpx #0
beq b3_from_b1
jmp b2
//SEG17 main::@2
b2:
//SEG18 [7] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@5 -- vbuxx_eq_vbuc1_then_la1
cpx #1
beq b5_from_b2
//SEG19 [8] phi from main::@2 to main::@4 [phi:main::@2->main::@4]
b4_from_b2:
jmp b4
//SEG20 main::@4
b4:
//SEG21 [9] phi from main::@4 to main::@5 [phi:main::@4->main::@5]
b5_from_b4:
//SEG22 [9] phi (byte~) main::$5 = (byte) 'c' [phi:main::@4->main::@5#0] -- vbuaa=vbuc1
lda #'c'
jmp b5
//SEG23 [9] phi from main::@2 to main::@5 [phi:main::@2->main::@5]
b5_from_b2:
//SEG24 [9] phi (byte~) main::$5 = (byte) 'b' [phi:main::@2->main::@5#0] -- vbuaa=vbuc1
lda #'b'
jmp b5
//SEG25 main::@5
b5:
//SEG26 [10] phi from main::@5 to main::@3 [phi:main::@5->main::@3]
b3_from_b5:
//SEG27 [10] phi (byte~) main::$7 = (byte~) main::$5 [phi:main::@5->main::@3#0] -- register_copy
jmp b3
//SEG28 [10] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
b3_from_b1:
//SEG29 [10] phi (byte~) main::$7 = (byte) 'a' [phi:main::@1->main::@3#0] -- vbuaa=vbuc1
lda #'a'
jmp b3
//SEG30 main::@3
b3:
//SEG31 [11] *((const byte*) main::SCREEN#0) ← (byte~) main::$7 -- _deref_pbuc1=vbuaa
sta SCREEN
//SEG32 [12] (byte) main::b#1 ← ++ (byte) main::b#2 -- vbuxx=_inc_vbuxx
inx
//SEG33 [13] if((byte) main::b#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #3
bne b1_from_b3
jmp breturn
//SEG34 main::@return
breturn:
//SEG35 [14] return
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp b4
Removing instruction jmp b5
Removing instruction jmp b3
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1_from_b3 with b1
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Removing instruction b1_from_b3:
Removing instruction b4_from_b2:
Removing instruction b5_from_b4:
Removing instruction b3_from_b5:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction b2:
Removing instruction b4:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Skipping double jump to b3 in jmp b5
Succesful ASM optimization Pass5DoubleJumpElimination
Relabelling long label b5_from_b2 to b2
Relabelling long label b3_from_b1 to b4
Succesful ASM optimization Pass5RelabelLongLabels
Removing instruction jmp b1
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Removing instruction b5:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) main()
(byte~) main::$5 reg byte a 11.0
(byte~) main::$7 reg byte a 22.0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
(byte) main::b
(byte) main::b#1 reg byte x 16.5
(byte) main::b#2 reg byte x 6.285714285714286
reg byte x [ main::b#2 main::b#1 ]
reg byte a [ main::$7 main::$5 ]
FINAL ASSEMBLER
Score: 341
//SEG0 File Comments
// Demonstrates error with nested ternary operator
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
//SEG9 @end
//SEG10 main
main: {
.label SCREEN = $400
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
//SEG12 [5] phi (byte) main::b#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
//SEG13 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
//SEG14 [5] phi (byte) main::b#2 = (byte) main::b#1 [phi:main::@3->main::@1#0] -- register_copy
//SEG15 main::@1
b1:
//SEG16 [6] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3 -- vbuxx_eq_0_then_la1
cpx #0
beq b4
//SEG17 main::@2
//SEG18 [7] if((byte) main::b#2==(byte/signed byte/word/signed word/dword/signed dword) 1) goto main::@5 -- vbuxx_eq_vbuc1_then_la1
cpx #1
beq b2
//SEG19 [8] phi from main::@2 to main::@4 [phi:main::@2->main::@4]
//SEG20 main::@4
//SEG21 [9] phi from main::@4 to main::@5 [phi:main::@4->main::@5]
//SEG22 [9] phi (byte~) main::$5 = (byte) 'c' [phi:main::@4->main::@5#0] -- vbuaa=vbuc1
lda #'c'
jmp b3
//SEG23 [9] phi from main::@2 to main::@5 [phi:main::@2->main::@5]
b2:
//SEG24 [9] phi (byte~) main::$5 = (byte) 'b' [phi:main::@2->main::@5#0] -- vbuaa=vbuc1
lda #'b'
//SEG25 main::@5
//SEG26 [10] phi from main::@5 to main::@3 [phi:main::@5->main::@3]
//SEG27 [10] phi (byte~) main::$7 = (byte~) main::$5 [phi:main::@5->main::@3#0] -- register_copy
jmp b3
//SEG28 [10] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
b4:
//SEG29 [10] phi (byte~) main::$7 = (byte) 'a' [phi:main::@1->main::@3#0] -- vbuaa=vbuc1
lda #'a'
//SEG30 main::@3
b3:
//SEG31 [11] *((const byte*) main::SCREEN#0) ← (byte~) main::$7 -- _deref_pbuc1=vbuaa
sta SCREEN
//SEG32 [12] (byte) main::b#1 ← ++ (byte) main::b#2 -- vbuxx=_inc_vbuxx
inx
//SEG33 [13] if((byte) main::b#1!=(byte/signed byte/word/signed word/dword/signed dword) 3) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #3
bne b1
//SEG34 main::@return
//SEG35 [14] return
rts
}

View File

@ -0,0 +1,20 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(byte~) main::$5 reg byte a 11.0
(byte~) main::$7 reg byte a 22.0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
(byte) main::b
(byte) main::b#1 reg byte x 16.5
(byte) main::b#2 reg byte x 6.285714285714286
reg byte x [ main::b#2 main::b#1 ]
reg byte a [ main::$7 main::$5 ]

726
src/test/ref/sandbox.asm Normal file
View File

@ -0,0 +1,726 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
.label zp1 = $61
// #define zp1 *(byte *)0x61 -- allows "zp1" vs "*zp1" below -- not supported -- https://gitlab.com/camelot/kickc/issues/169
.label zp2 = $62
.label TIMEHI = $a1
.label TIMELO = $a2
.label VICBANK = $d018
main: {
.label _2 = 6
.label _3 = 6
.label _4 = 8
.label _11 = 6
.label _12 = 6
.label _13 = 8
.label v = 4
.label u = 2
lda #$17
sta VICBANK
lda #0
sta zp1
lda #<$6e85
sta u
lda #>$6e85
sta u+1
b1:
lda #0
sta TIMEHI
sta TIMELO
sta zp2
b2:
jsr div16u
inc zp2
lda zp2
cmp #$c8
bcc b2
lda TIMEHI
sta _2
lda #0
sta _2+1
ldy #8
cpy #0
beq !e+
!:
asl _3
rol _3+1
dey
bne !-
!e:
lda TIMELO
sta _4
lda #0
sta _4+1
lda myprintf.w3
clc
adc _4
sta myprintf.w3
lda myprintf.w3+1
adc _4+1
sta myprintf.w3+1
lda #<str
sta myprintf.str
lda #>str
sta myprintf.str+1
jsr myprintf
jsr Print
lda u
sec
sbc #<$4d2
sta u
lda u+1
sbc #>$4d2
sta u+1
inc zp1
lda zp1
cmp #$a
bcc b1
lda #0
sta zp1
lda #<$6e85
sta u
lda #>$6e85
sta u+1
b5:
lda #0
sta TIMEHI
sta TIMELO
sta zp2
b6:
jsr div10
inc zp2
lda zp2
cmp #$c8
bcc b6
lda TIMEHI
sta _11
lda #0
sta _11+1
ldy #8
cpy #0
beq !e+
!:
asl _12
rol _12+1
dey
bne !-
!e:
lda TIMELO
sta _13
lda #0
sta _13+1
lda myprintf.w3
clc
adc _13
sta myprintf.w3
lda myprintf.w3+1
adc _13+1
sta myprintf.w3+1
lda #<str1
sta myprintf.str
lda #>str1
sta myprintf.str+1
jsr myprintf
jsr Print
lda u
sec
sbc #<$4d2
sta u
lda u+1
sbc #>$4d2
sta u+1
inc zp1
lda zp1
cmp #$a
bcc b5
rts
str: .text "200 DIV16U: %5d,%4d IN %04d FRAMESm@"
str1: .text "200 DIV10 : %5d,%4d IN %04d FRAMESm@"
}
Print: {
// can this assembly be placed in a separate file and call it from the C code here?
ldy #0
loop:
lda strTemp,y
beq done
jsr $ffd2
iny
jmp loop
done:
rts
}
// myprintf(byte* zeropage(8) str, word zeropage(2) w1, word zeropage(4) w2, word zeropage(6) w3)
myprintf: {
.label _17 = $12
.label str = 8
.label bDigits = $11
.label bLen = $10
.label digit = $a
.label bArg = $b
.label return = $10
.label w1 = 2
.label w2 = 4
.label w3 = 6
.label bFormat = $a
.label w = $c
.label bTrailing = $e
.label bLeadZero = $f
lda #0
sta bLeadZero
sta bDigits
sta bTrailing
sta w
sta w+1
sta bLen
sta bArg
sta bFormat
b1:
ldy #0
lda (str),y
tax
lda bFormat
cmp #0
bne !b2+
jmp b2
!b2:
cpx #'0'
bne b3
lda #1
sta bLeadZero
b27:
inc str
bne !+
inc str+1
!:
ldy #0
lda (str),y
cmp #0
bne b1
tya
ldy return
sta strTemp,y
rts
b3:
cpx #'1'
bcc !b37+
jmp b37
!b37:
b4:
cpx #'-'
bne b5
lda #1
sta bTrailing
jmp b27
b5:
cpx #'c'
bne !b6+
jmp b6
!b6:
cpx #'d'
beq b7
cpx #'x'
beq b26
cpx #'X'
beq b26
b22:
lda #0
sta bFormat
jmp b27
b26:
lda w+1
sta _17+1
lda w
sta _17
ldy #4
!:
lsr _17+1
ror _17
dey
bne !-
lda _17
and #$f
tax
cpx #$a
bcc b8
lda #$57
jmp b9
b8:
lda #'0'
b9:
stx $ff
clc
adc $ff
ldy bLen
sta strTemp,y
iny
lda w
and #$f
tax
cpx #$a
bcc b10
lda #$57
jmp b11
b10:
lda #'0'
b11:
stx $ff
clc
adc $ff
sta strTemp,y
iny
sty bLen
jmp b22
b7:
lda w
sta utoa.value
lda w+1
sta utoa.value+1
jsr utoa
ldx #1
b12:
lda buf6,x
cmp #0
bne b13
lda bTrailing
cmp #0
beq b39
b15:
lda #0
sta digit
b19:
ldy digit
lda buf6,y
ldy bLen
sta strTemp,y
inc bLen
inc digit
txa
cmp digit
beq !+
bcs b19
!:
lda bTrailing
cmp #0
bne b40
jmp b22
b40:
cpx bDigits
bcc b21
jmp b22
b21:
lda #' '
ldy bLen
sta strTemp,y
inc bLen
dec bDigits
cpx bDigits
bcc b21
jmp b22
b39:
cpx bDigits
bcc b16
jmp b15
b16:
lda bLeadZero
cmp #0
beq b14
lda #'0'
jmp b18
b14:
lda #' '
b18:
ldy bLen
sta strTemp,y
inc bLen
dec bDigits
cpx bDigits
bcc b16
jmp b15
b13:
inx
jmp b12
b6:
lda w
// "switch" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/170
ldy bLen
sta strTemp,y
inc bLen
jmp b22
b37:
cpx #'9'
bcc b23
beq b23
jmp b4
b23:
txa
axs #'0'
stx bDigits
jmp b27
b2:
cpx #'%'
bne b28
// default format
//w = (bArg == 0) ? w1 : ((bArg == 1) ? w2 : w3); -- "?" is the normal way, but error "sequence does not contain all blocks" -- https://gitlab.com/camelot/kickc/issues/185 [FIXED]
lda bArg
cmp #0
beq b42
lda #1
cmp bArg
beq b43
lda w3
sta w
lda w3+1
sta w+1
b29:
inc bArg
lda #0
sta bLeadZero
lda #1
sta bDigits
lda #0
sta bTrailing
lda #1
sta bFormat
jmp b27
b43:
lda w2
sta w
lda w2+1
sta w+1
jmp b29
b42:
lda w1
sta w
lda w1+1
sta w+1
jmp b29
b28:
cpx #$41
bcs b41
b30:
// swap 0x41 / 0x61 when in lower case mode
ldy bLen
txa
sta strTemp,y
inc bLen
jmp b27
b41:
cpx #$5a+1
bcc b35
jmp b30
b35:
txa
axs #-[$20]
jmp b30
buf6: .fill 6, 0
}
// utoa(word zeropage($12) value, byte* zeropage($14) dst)
utoa: {
.label value = $12
.label dst = $14
lda value+1
cmp #>$2710
bcc !+
beq !b5+
jmp b5
!b5:
lda value
cmp #<$2710
bcc !b5+
jmp b5
!b5:
!:
lda #<myprintf.buf6
sta dst
lda #>myprintf.buf6
sta dst+1
ldx #0
b1:
cpx #1
beq b6
lda value+1
cmp #>$3e8
bcc !+
bne b6
lda value
cmp #<$3e8
bcs b6
!:
b2:
cpx #1
beq b7
lda value+1
cmp #>$64
bcc !+
bne b7
lda value
cmp #<$64
bcs b7
!:
b3:
cpx #1
beq b8
lda value+1
cmp #>$a
bcc !+
bne b8
lda value
cmp #<$a
bcs b8
!:
b4:
lda value
clc
adc #'0'
ldy #0
sta (dst),y
inc dst
bne !+
inc dst+1
!:
lda #0
tay
sta (dst),y
rts
b8:
lda #$a
sta append.sub
lda #0
sta append.sub+1
jsr append
inc dst
bne !+
inc dst+1
!:
jmp b4
b7:
lda #$64
sta append.sub
lda #0
sta append.sub+1
jsr append
inc dst
bne !+
inc dst+1
!:
ldx #1
jmp b3
b6:
lda #<$3e8
sta append.sub
lda #>$3e8
sta append.sub+1
jsr append
inc dst
bne !+
inc dst+1
!:
ldx #1
jmp b2
b5:
lda #<$2710
sta append.sub
lda #>$2710
sta append.sub+1
lda #<myprintf.buf6
sta append.dst
lda #>myprintf.buf6
sta append.dst+1
jsr append
lda #<myprintf.buf6+1
sta dst
lda #>myprintf.buf6+1
sta dst+1
ldx #1
jmp b1
}
// simple 'utoa' without using multiply or divide
// append(byte* zeropage($14) dst, word zeropage($12) value, word zeropage($16) sub)
append: {
.label value = $12
.label return = $12
.label dst = $14
.label sub = $16
lda #'0'
ldy #0
sta (dst),y
b1:
lda sub+1
cmp value+1
bne !+
lda sub
cmp value
!:
bcc b2
beq b2
rts
b2:
ldy #0
lda (dst),y
clc
adc #1
sta (dst),y
lda value
sec
sbc sub
sta value
lda value+1
sbc sub+1
sta value+1
jmp b1
}
// div10(word zeropage(4) val)
div10: {
.label _0 = 4
.label _2 = 6
.label _3 = 4
.label _4 = 6
.label _5 = 6
.label val = 4
.label val_1 = 6
.label return = 4
.label val_4 = 2
lda val_4+1
lsr
sta _0+1
lda val_4
ror
sta _0
inc val
bne !+
inc val+1
!:
lda val
asl
sta _2
lda val+1
rol
sta _2+1
lda val_1
clc
adc val
sta val_1
lda val_1+1
adc val+1
sta val_1+1
sta _3+1
lda val_1
sta _3
ldy #4
!:
lsr _3+1
ror _3
dey
bne !-
lda val
clc
adc val_1
sta val
lda val+1
adc val_1+1
sta val+1
sta _4+1
lda val
sta _4
ldy #4
!:
lsr _4+1
ror _4
dey
bne !-
ldy #4
!:
lsr _5+1
ror _5
dey
bne !-
lda val
clc
adc _5
sta val
lda val+1
adc _5+1
sta val+1
ldy #4
!:
lsr return+1
ror return
dey
bne !-
rts
}
// Performs division on two 16 bit unsigned words
// Returns the quotient dividend/divisor.
// The remainder will be set into the global variable rem16u
// Implemented using simple binary division
// div16u(word zeropage(2) dividend)
div16u: {
.label divisor = $a
.label return = 4
.label dividend = 2
lda dividend
sta divr16u.dividend
lda dividend+1
sta divr16u.dividend+1
jsr divr16u
rts
}
// Performs division on two 16 bit unsigned words and an initial remainder
// Returns the quotient dividend/divisor.
// The final remainder will be set into the global variable rem16u
// Implemented using simple binary division
// divr16u(word zeropage(8) dividend, word zeropage(6) rem)
divr16u: {
.label rem = 6
.label dividend = 8
.label quotient = 4
.label return = 4
ldx #0
txa
sta quotient
sta quotient+1
sta rem
sta rem+1
b1:
asl rem
rol rem+1
lda dividend+1
and #$80
cmp #0
beq b2
lda #1
ora rem
sta rem
b2:
asl dividend
rol dividend+1
asl quotient
rol quotient+1
lda rem+1
cmp #>div16u.divisor
bcc b3
bne !+
lda rem
cmp #<div16u.divisor
bcc b3
!:
inc quotient
bne !+
inc quotient+1
!:
lda rem
sec
sbc #<div16u.divisor
sta rem
lda rem+1
sbc #>div16u.divisor
sta rem+1
b3:
inx
cpx #$10
bne b1
rts
}
// "char buf16[16]" is the normal way -- not supported -- https://gitlab.com/camelot/kickc/issues/162
strTemp: .fill $64, 0

444
src/test/ref/sandbox.cfg Normal file
View File

@ -0,0 +1,444 @@
@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] *((const byte*) VICBANK#0) ← (byte/signed byte/word/signed word/dword/signed dword) $17
[5] *((const byte*) zp1#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@10
[6] (word) main::u#11 ← phi( main/(word/signed word/dword/signed dword) $6e85 main::@10/(word) main::u#2 )
[7] *((const byte*) TIMEHI#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
[8] *((const byte*) TIMELO#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
[9] *((const byte*) zp2#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@2
main::@2: scope:[main] from main::@1 main::@8
[10] (word) div16u::dividend#0 ← (word) main::u#11
[11] call div16u
[12] (word) div16u::return#2 ← (word) div16u::return#0
to:main::@8
main::@8: scope:[main] from main::@2
[13] (word) main::v#1 ← (word) div16u::return#2
[14] *((const byte*) zp2#0) ← ++ *((const byte*) zp2#0)
[15] if(*((const byte*) zp2#0)<(byte/word/signed word/dword/signed dword) $c8) goto main::@2
to:main::@3
main::@3: scope:[main] from main::@8
[16] (word~) main::$2 ← ((word)) *((const byte*) TIMEHI#0)
[17] (word~) main::$3 ← (word~) main::$2 << (byte/signed byte/word/signed word/dword/signed dword) 8
[18] (word~) main::$4 ← ((word)) *((const byte*) TIMELO#0)
[19] (word) myprintf::w3#0 ← (word~) main::$3 + (word~) main::$4
[20] (word) myprintf::w1#0 ← (word) main::u#11
[21] (word) myprintf::w2#0 ← (word) main::v#1
[22] call myprintf
to:main::@9
main::@9: scope:[main] from main::@3
[23] phi()
[24] call Print
to:main::@10
main::@10: scope:[main] from main::@9
[25] (word) main::u#2 ← (word) main::u#11 - (word/signed word/dword/signed dword) $4d2
[26] *((const byte*) zp1#0) ← ++ *((const byte*) zp1#0)
[27] if(*((const byte*) zp1#0)<(byte/signed byte/word/signed word/dword/signed dword) $a) goto main::@1
to:main::@4
main::@4: scope:[main] from main::@10
[28] *((const byte*) zp1#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@5
main::@5: scope:[main] from main::@13 main::@4
[29] (word) main::u#15 ← phi( main::@13/(word) main::u#4 main::@4/(word/signed word/dword/signed dword) $6e85 )
[30] *((const byte*) TIMEHI#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
[31] *((const byte*) TIMELO#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
[32] *((const byte*) zp2#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@6
main::@6: scope:[main] from main::@11 main::@5
[33] (word) div10::val#4 ← (word) main::u#15
[34] call div10
[35] (word) div10::return#2 ← (word) div10::return#0
to:main::@11
main::@11: scope:[main] from main::@6
[36] (word) main::v#2 ← (word) div10::return#2
[37] *((const byte*) zp2#0) ← ++ *((const byte*) zp2#0)
[38] if(*((const byte*) zp2#0)<(byte/word/signed word/dword/signed dword) $c8) goto main::@6
to:main::@7
main::@7: scope:[main] from main::@11
[39] (word~) main::$11 ← ((word)) *((const byte*) TIMEHI#0)
[40] (word~) main::$12 ← (word~) main::$11 << (byte/signed byte/word/signed word/dword/signed dword) 8
[41] (word~) main::$13 ← ((word)) *((const byte*) TIMELO#0)
[42] (word) myprintf::w3#1 ← (word~) main::$12 + (word~) main::$13
[43] (word) myprintf::w1#1 ← (word) main::u#15
[44] (word) myprintf::w2#1 ← (word) main::v#2
[45] call myprintf
to:main::@12
main::@12: scope:[main] from main::@7
[46] phi()
[47] call Print
to:main::@13
main::@13: scope:[main] from main::@12
[48] (word) main::u#4 ← (word) main::u#15 - (word/signed word/dword/signed dword) $4d2
[49] *((const byte*) zp1#0) ← ++ *((const byte*) zp1#0)
[50] if(*((const byte*) zp1#0)<(byte/signed byte/word/signed word/dword/signed dword) $a) goto main::@5
to:main::@return
main::@return: scope:[main] from main::@13
[51] return
to:@return
Print: scope:[Print] from main::@12 main::@9
asm { ldy#0 loop: ldastrTemp,y beqdone jsr$FFD2 iny jmploop done: }
to:Print::@return
Print::@return: scope:[Print] from Print
[53] return
to:@return
myprintf: scope:[myprintf] from main::@3 main::@7
[54] (word) myprintf::w3#7 ← phi( main::@3/(word) myprintf::w3#0 main::@7/(word) myprintf::w3#1 )
[54] (word) myprintf::w2#7 ← phi( main::@3/(word) myprintf::w2#0 main::@7/(word) myprintf::w2#1 )
[54] (word) myprintf::w1#6 ← phi( main::@3/(word) myprintf::w1#0 main::@7/(word) myprintf::w1#1 )
[54] (byte*) myprintf::str#5 ← phi( main::@3/(const string) main::str main::@7/(const string) main::str1 )
to:myprintf::@1
myprintf::@1: scope:[myprintf] from myprintf myprintf::@27
[55] (byte) myprintf::bLeadZero#10 ← phi( myprintf/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@27/(byte) myprintf::bLeadZero#18 )
[55] (byte) myprintf::bDigits#14 ← phi( myprintf/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@27/(byte) myprintf::bDigits#24 )
[55] (byte) myprintf::bTrailing#10 ← phi( myprintf/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@27/(byte) myprintf::bTrailing#21 )
[55] (word) myprintf::w#10 ← phi( myprintf/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@27/(word) myprintf::w#17 )
[55] (byte) myprintf::bLen#14 ← phi( myprintf/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@27/(byte) myprintf::return#0 )
[55] (byte) myprintf::bArg#12 ← phi( myprintf/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@27/(byte) myprintf::bArg#10 )
[55] (byte) myprintf::bFormat#10 ← phi( myprintf/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@27/(byte) myprintf::bFormat#4 )
[55] (byte*) myprintf::str#10 ← phi( myprintf/(byte*) myprintf::str#5 myprintf::@27/(byte*) myprintf::str#0 )
[56] (byte) myprintf::b#1 ← *((byte*) myprintf::str#10)
[57] if((byte) myprintf::bFormat#10==(byte/signed byte/word/signed word/dword/signed dword) 0) goto myprintf::@2
to:myprintf::@31
myprintf::@31: scope:[myprintf] from myprintf::@1
[58] if((byte) myprintf::b#1!=(byte) '0') goto myprintf::@3
to:myprintf::@27
myprintf::@27: scope:[myprintf] from myprintf::@22 myprintf::@23 myprintf::@29 myprintf::@30 myprintf::@31 myprintf::@4
[59] (byte) myprintf::bLeadZero#18 ← phi( myprintf::@22/(byte) myprintf::bLeadZero#10 myprintf::@23/(byte) myprintf::bLeadZero#10 myprintf::@4/(byte) myprintf::bLeadZero#10 myprintf::@29/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@30/(byte) myprintf::bLeadZero#10 myprintf::@31/(byte/signed byte/word/signed word/dword/signed dword) 1 )
[59] (byte) myprintf::bDigits#24 ← phi( myprintf::@22/(byte) myprintf::bDigits#25 myprintf::@23/(byte) myprintf::bDigits#1 myprintf::@4/(byte) myprintf::bDigits#14 myprintf::@29/(byte/signed byte/word/signed word/dword/signed dword) 1 myprintf::@30/(byte) myprintf::bDigits#14 myprintf::@31/(byte) myprintf::bDigits#14 )
[59] (byte) myprintf::bTrailing#21 ← phi( myprintf::@22/(byte) myprintf::bTrailing#10 myprintf::@23/(byte) myprintf::bTrailing#10 myprintf::@4/(byte/signed byte/word/signed word/dword/signed dword) 1 myprintf::@29/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@30/(byte) myprintf::bTrailing#10 myprintf::@31/(byte) myprintf::bTrailing#10 )
[59] (word) myprintf::w#17 ← phi( myprintf::@22/(word) myprintf::w#10 myprintf::@23/(word) myprintf::w#10 myprintf::@4/(word) myprintf::w#10 myprintf::@29/(word) myprintf::w#21 myprintf::@30/(word) myprintf::w#10 myprintf::@31/(word) myprintf::w#10 )
[59] (byte) myprintf::bArg#10 ← phi( myprintf::@22/(byte) myprintf::bArg#12 myprintf::@23/(byte) myprintf::bArg#12 myprintf::@4/(byte) myprintf::bArg#12 myprintf::@29/(byte) myprintf::bArg#1 myprintf::@30/(byte) myprintf::bArg#12 myprintf::@31/(byte) myprintf::bArg#12 )
[59] (byte) myprintf::return#0 ← phi( myprintf::@22/(byte) myprintf::bLen#28 myprintf::@23/(byte) myprintf::bLen#14 myprintf::@4/(byte) myprintf::bLen#14 myprintf::@29/(byte) myprintf::bLen#14 myprintf::@30/(byte) myprintf::bLen#7 myprintf::@31/(byte) myprintf::bLen#14 )
[59] (byte) myprintf::bFormat#4 ← phi( myprintf::@22/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@23/(byte) myprintf::bFormat#10 myprintf::@4/(byte) myprintf::bFormat#10 myprintf::@29/(byte/signed byte/word/signed word/dword/signed dword) 1 myprintf::@30/(byte) myprintf::bFormat#10 myprintf::@31/(byte) myprintf::bFormat#10 )
[60] (byte*) myprintf::str#0 ← ++ (byte*) myprintf::str#10
[61] if(*((byte*) myprintf::str#0)!=(byte/signed byte/word/signed word/dword/signed dword) 0) goto myprintf::@1
to:myprintf::@36
myprintf::@36: scope:[myprintf] from myprintf::@27
[62] *((const byte[$64]) strTemp#0 + (byte) myprintf::return#0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:myprintf::@return
myprintf::@return: scope:[myprintf] from myprintf::@36
[63] return
to:@return
myprintf::@3: scope:[myprintf] from myprintf::@31
[64] if((byte) myprintf::b#1>=(byte) '1') goto myprintf::@37
to:myprintf::@4
myprintf::@4: scope:[myprintf] from myprintf::@3 myprintf::@37
[65] if((byte) myprintf::b#1!=(byte) '-') goto myprintf::@5
to:myprintf::@27
myprintf::@5: scope:[myprintf] from myprintf::@4
[66] if((byte) myprintf::b#1==(byte) 'c') goto myprintf::@6
to:myprintf::@24
myprintf::@24: scope:[myprintf] from myprintf::@5
[67] if((byte) myprintf::b#1==(byte) 'd') goto myprintf::@7
to:myprintf::@25
myprintf::@25: scope:[myprintf] from myprintf::@24
[68] if((byte) myprintf::b#1==(byte) 'x') goto myprintf::@26
to:myprintf::@38
myprintf::@38: scope:[myprintf] from myprintf::@25
[69] if((byte) myprintf::b#1==(byte) 'X') goto myprintf::@26
to:myprintf::@22
myprintf::@22: scope:[myprintf] from myprintf::@11 myprintf::@20 myprintf::@21 myprintf::@38 myprintf::@40 myprintf::@6
[70] (byte) myprintf::bDigits#25 ← phi( myprintf::@11/(byte) myprintf::bDigits#14 myprintf::@20/(byte) myprintf::bDigits#16 myprintf::@21/(byte) myprintf::bDigits#3 myprintf::@6/(byte) myprintf::bDigits#14 myprintf::@38/(byte) myprintf::bDigits#14 myprintf::@40/(byte) myprintf::bDigits#16 )
[70] (byte) myprintf::bLen#28 ← phi( myprintf::@11/(byte) myprintf::bLen#3 myprintf::@20/(byte) myprintf::bLen#24 myprintf::@21/(byte) myprintf::bLen#6 myprintf::@6/(byte) myprintf::bLen#1 myprintf::@38/(byte) myprintf::bLen#14 myprintf::@40/(byte) myprintf::bLen#24 )
to:myprintf::@27
myprintf::@26: scope:[myprintf] from myprintf::@25 myprintf::@38
[71] (word~) myprintf::$17 ← (word) myprintf::w#10 >> (byte/signed byte/word/signed word/dword/signed dword) 4
[72] (byte) myprintf::b#15 ← (word~) myprintf::$17 & (byte/signed byte/word/signed word/dword/signed dword) $f
[73] if((byte) myprintf::b#15<(byte/signed byte/word/signed word/dword/signed dword) $a) goto myprintf::@9
to:myprintf::@8
myprintf::@8: scope:[myprintf] from myprintf::@26
[74] phi()
to:myprintf::@9
myprintf::@9: scope:[myprintf] from myprintf::@26 myprintf::@8
[75] (byte~) myprintf::$22 ← phi( myprintf::@26/(byte) '0' myprintf::@8/(byte/signed byte/word/signed word/dword/signed dword) $57 )
[76] (byte~) myprintf::$23 ← (byte~) myprintf::$22 + (byte) myprintf::b#15
[77] *((const byte[$64]) strTemp#0 + (byte) myprintf::bLen#14) ← (byte~) myprintf::$23
[78] (byte) myprintf::bLen#10 ← ++ (byte) myprintf::bLen#14
[79] (byte) myprintf::b#16 ← (word) myprintf::w#10 & (byte/signed byte/word/signed word/dword/signed dword) $f
[80] if((byte) myprintf::b#16<(byte/signed byte/word/signed word/dword/signed dword) $a) goto myprintf::@11
to:myprintf::@10
myprintf::@10: scope:[myprintf] from myprintf::@9
[81] phi()
to:myprintf::@11
myprintf::@11: scope:[myprintf] from myprintf::@10 myprintf::@9
[82] (byte~) myprintf::$28 ← phi( myprintf::@9/(byte) '0' myprintf::@10/(byte/signed byte/word/signed word/dword/signed dword) $57 )
[83] (byte~) myprintf::$29 ← (byte~) myprintf::$28 + (byte) myprintf::b#16
[84] *((const byte[$64]) strTemp#0 + (byte) myprintf::bLen#10) ← (byte~) myprintf::$29
[85] (byte) myprintf::bLen#3 ← ++ (byte) myprintf::bLen#10
to:myprintf::@22
myprintf::@7: scope:[myprintf] from myprintf::@24
[86] (word) utoa::value#4 ← (word) myprintf::w#10
[87] call utoa
to:myprintf::@12
myprintf::@12: scope:[myprintf] from myprintf::@13 myprintf::@7
[88] (byte) myprintf::b#17 ← phi( myprintf::@13/(byte) myprintf::b#5 myprintf::@7/(byte/signed byte/word/signed word/dword/signed dword) 1 )
[89] if(*((const byte[6]) myprintf::buf6#0 + (byte) myprintf::b#17)!=(byte/signed byte/word/signed word/dword/signed dword) 0) goto myprintf::@13
to:myprintf::@14
myprintf::@14: scope:[myprintf] from myprintf::@12
[90] if((byte) myprintf::bTrailing#10==(byte/signed byte/word/signed word/dword/signed dword) 0) goto myprintf::@39
to:myprintf::@15
myprintf::@15: scope:[myprintf] from myprintf::@14 myprintf::@18 myprintf::@39
[91] (byte) myprintf::bDigits#16 ← phi( myprintf::@14/(byte) myprintf::bDigits#14 myprintf::@18/(byte) myprintf::bDigits#2 )
[91] (byte) myprintf::bLen#23 ← phi( myprintf::@14/(byte) myprintf::bLen#14 myprintf::@18/(byte) myprintf::bLen#4 )
to:myprintf::@19
myprintf::@19: scope:[myprintf] from myprintf::@15 myprintf::@19
[92] (byte) myprintf::bLen#12 ← phi( myprintf::@15/(byte) myprintf::bLen#23 myprintf::@19/(byte) myprintf::bLen#24 )
[92] (byte) myprintf::digit#3 ← phi( myprintf::@15/(byte/signed byte/word/signed word/dword/signed dword) 0 myprintf::@19/(byte) myprintf::digit#2 )
[93] *((const byte[$64]) strTemp#0 + (byte) myprintf::bLen#12) ← *((const byte[6]) myprintf::buf6#0 + (byte) myprintf::digit#3)
[94] (byte) myprintf::bLen#24 ← ++ (byte) myprintf::bLen#12
[95] (byte) myprintf::digit#2 ← ++ (byte) myprintf::digit#3
[96] if((byte) myprintf::digit#2<(byte) myprintf::b#17) goto myprintf::@19
to:myprintf::@20
myprintf::@20: scope:[myprintf] from myprintf::@19
[97] if((byte) myprintf::bTrailing#10!=(byte/signed byte/word/signed word/dword/signed dword) 0) goto myprintf::@40
to:myprintf::@22
myprintf::@40: scope:[myprintf] from myprintf::@20
[98] if((byte) myprintf::bDigits#16>(byte) myprintf::b#17) goto myprintf::@21
to:myprintf::@22
myprintf::@21: scope:[myprintf] from myprintf::@21 myprintf::@40
[99] (byte) myprintf::bDigits#8 ← phi( myprintf::@40/(byte) myprintf::bDigits#16 myprintf::@21/(byte) myprintf::bDigits#3 )
[99] (byte) myprintf::bLen#13 ← phi( myprintf::@40/(byte) myprintf::bLen#24 myprintf::@21/(byte) myprintf::bLen#6 )
[100] *((const byte[$64]) strTemp#0 + (byte) myprintf::bLen#13) ← (byte) ' '
[101] (byte) myprintf::bLen#6 ← ++ (byte) myprintf::bLen#13
[102] (byte) myprintf::bDigits#3 ← -- (byte) myprintf::bDigits#8
[103] if((byte) myprintf::bDigits#3>(byte) myprintf::b#17) goto myprintf::@21
to:myprintf::@22
myprintf::@39: scope:[myprintf] from myprintf::@14
[104] if((byte) myprintf::bDigits#14>(byte) myprintf::b#17) goto myprintf::@16
to:myprintf::@15
myprintf::@16: scope:[myprintf] from myprintf::@18 myprintf::@39
[105] (byte) myprintf::bDigits#10 ← phi( myprintf::@39/(byte) myprintf::bDigits#14 myprintf::@18/(byte) myprintf::bDigits#2 )
[105] (byte) myprintf::bLen#11 ← phi( myprintf::@39/(byte) myprintf::bLen#14 myprintf::@18/(byte) myprintf::bLen#4 )
[106] if((byte) myprintf::bLeadZero#10==(byte/signed byte/word/signed word/dword/signed dword) 0) goto myprintf::@18
to:myprintf::@17
myprintf::@17: scope:[myprintf] from myprintf::@16
[107] phi()
to:myprintf::@18
myprintf::@18: scope:[myprintf] from myprintf::@16 myprintf::@17
[108] (byte~) myprintf::$39 ← phi( myprintf::@16/(byte) ' ' myprintf::@17/(byte) '0' )
[109] *((const byte[$64]) strTemp#0 + (byte) myprintf::bLen#11) ← (byte~) myprintf::$39
[110] (byte) myprintf::bLen#4 ← ++ (byte) myprintf::bLen#11
[111] (byte) myprintf::bDigits#2 ← -- (byte) myprintf::bDigits#10
[112] if((byte) myprintf::bDigits#2>(byte) myprintf::b#17) goto myprintf::@16
to:myprintf::@15
myprintf::@13: scope:[myprintf] from myprintf::@12
[113] (byte) myprintf::b#5 ← ++ (byte) myprintf::b#17
to:myprintf::@12
myprintf::@6: scope:[myprintf] from myprintf::@5
[114] (byte~) myprintf::$47 ← ((byte)) (word) myprintf::w#10
[115] *((const byte[$64]) strTemp#0 + (byte) myprintf::bLen#14) ← (byte~) myprintf::$47
[116] (byte) myprintf::bLen#1 ← ++ (byte) myprintf::bLen#14
to:myprintf::@22
myprintf::@37: scope:[myprintf] from myprintf::@3
[117] if((byte) myprintf::b#1<=(byte) '9') goto myprintf::@23
to:myprintf::@4
myprintf::@23: scope:[myprintf] from myprintf::@37
[118] (byte) myprintf::bDigits#1 ← (byte) myprintf::b#1 - (byte) '0'
to:myprintf::@27
myprintf::@2: scope:[myprintf] from myprintf::@1
[119] if((byte) myprintf::b#1!=(byte) '%') goto myprintf::@28
to:myprintf::@32
myprintf::@32: scope:[myprintf] from myprintf::@2
[120] if((byte) myprintf::bArg#12==(byte/signed byte/word/signed word/dword/signed dword) 0) goto myprintf::@42
to:myprintf::@33
myprintf::@33: scope:[myprintf] from myprintf::@32
[121] if((byte) myprintf::bArg#12==(byte/signed byte/word/signed word/dword/signed dword) 1) goto myprintf::@43
to:myprintf::@34
myprintf::@34: scope:[myprintf] from myprintf::@33
[122] (word~) myprintf::w#53 ← (word) myprintf::w3#7
to:myprintf::@29
myprintf::@29: scope:[myprintf] from myprintf::@34 myprintf::@42 myprintf::@43
[123] (word) myprintf::w#21 ← phi( myprintf::@42/(word~) myprintf::w#51 myprintf::@43/(word~) myprintf::w#52 myprintf::@34/(word~) myprintf::w#53 )
[124] (byte) myprintf::bArg#1 ← ++ (byte) myprintf::bArg#12
to:myprintf::@27
myprintf::@43: scope:[myprintf] from myprintf::@33
[125] (word~) myprintf::w#52 ← (word) myprintf::w2#7
to:myprintf::@29
myprintf::@42: scope:[myprintf] from myprintf::@32
[126] (word~) myprintf::w#51 ← (word) myprintf::w1#6
to:myprintf::@29
myprintf::@28: scope:[myprintf] from myprintf::@2
[127] if((byte) myprintf::b#1>=(byte/signed byte/word/signed word/dword/signed dword) $41) goto myprintf::@41
to:myprintf::@30
myprintf::@30: scope:[myprintf] from myprintf::@28 myprintf::@35 myprintf::@41
[128] (byte) myprintf::b#25 ← phi( myprintf::@28/(byte) myprintf::b#1 myprintf::@35/(byte) myprintf::b#6 )
[129] *((const byte[$64]) strTemp#0 + (byte) myprintf::bLen#14) ← (byte) myprintf::b#25
[130] (byte) myprintf::bLen#7 ← ++ (byte) myprintf::bLen#14
to:myprintf::@27
myprintf::@41: scope:[myprintf] from myprintf::@28
[131] if((byte) myprintf::b#1<(byte/signed byte/word/signed word/dword/signed dword) $5a+(byte/signed byte/word/signed word/dword/signed dword) 1) goto myprintf::@35
to:myprintf::@30
myprintf::@35: scope:[myprintf] from myprintf::@41
[132] (byte) myprintf::b#6 ← (byte) myprintf::b#1 + (byte/signed byte/word/signed word/dword/signed dword) $20
to:myprintf::@30
utoa: scope:[utoa] from myprintf::@7
[133] phi()
to:utoa::@13
utoa::@13: scope:[utoa] from utoa
[134] if((word) utoa::value#4>=(word/signed word/dword/signed dword) $2710) goto utoa::@5
to:utoa::@1
utoa::@1: scope:[utoa] from utoa::@13 utoa::@9
[135] (byte*) utoa::dst#16 ← phi( utoa::@13/(const byte[6]) myprintf::buf6#0 utoa::@9/++(const byte[6]) myprintf::buf6#0 )
[135] (word) utoa::value#6 ← phi( utoa::@13/(word) utoa::value#4 utoa::@9/(word) utoa::value#0 )
[135] (byte) utoa::bStarted#5 ← phi( utoa::@13/(byte/signed byte/word/signed word/dword/signed dword) 0 utoa::@9/(byte/signed byte/word/signed word/dword/signed dword) 1 )
[136] if((byte) utoa::bStarted#5==(byte/signed byte/word/signed word/dword/signed dword) 1) goto utoa::@6
to:utoa::@14
utoa::@14: scope:[utoa] from utoa::@1
[137] if((word) utoa::value#6>=(word/signed word/dword/signed dword) $3e8) goto utoa::@6
to:utoa::@2
utoa::@2: scope:[utoa] from utoa::@10 utoa::@14
[138] (byte*) utoa::dst#10 ← phi( utoa::@14/(byte*) utoa::dst#16 utoa::@10/(byte*) utoa::dst#1 )
[138] (word) utoa::value#11 ← phi( utoa::@14/(word) utoa::value#6 utoa::@10/(word) utoa::value#1 )
[138] (byte) utoa::bStarted#6 ← phi( utoa::@14/(byte) utoa::bStarted#5 utoa::@10/(byte/signed byte/word/signed word/dword/signed dword) 1 )
[139] if((byte) utoa::bStarted#6==(byte/signed byte/word/signed word/dword/signed dword) 1) goto utoa::@7
to:utoa::@15
utoa::@15: scope:[utoa] from utoa::@2
[140] if((word) utoa::value#11>=(byte/signed byte/word/signed word/dword/signed dword) $64) goto utoa::@7
to:utoa::@3
utoa::@3: scope:[utoa] from utoa::@11 utoa::@15
[141] (byte*) utoa::dst#13 ← phi( utoa::@11/(byte*) utoa::dst#2 utoa::@15/(byte*) utoa::dst#10 )
[141] (word) utoa::value#10 ← phi( utoa::@11/(word) utoa::value#2 utoa::@15/(word) utoa::value#11 )
[141] (byte) utoa::bStarted#7 ← phi( utoa::@11/(byte/signed byte/word/signed word/dword/signed dword) 1 utoa::@15/(byte) utoa::bStarted#6 )
[142] if((byte) utoa::bStarted#7==(byte/signed byte/word/signed word/dword/signed dword) 1) goto utoa::@8
to:utoa::@16
utoa::@16: scope:[utoa] from utoa::@3
[143] if((word) utoa::value#10>=(byte/signed byte/word/signed word/dword/signed dword) $a) goto utoa::@8
to:utoa::@4
utoa::@4: scope:[utoa] from utoa::@12 utoa::@16
[144] (byte*) utoa::dst#12 ← phi( utoa::@12/(byte*) utoa::dst#4 utoa::@16/(byte*) utoa::dst#13 )
[144] (word) utoa::value#12 ← phi( utoa::@12/(word) utoa::value#3 utoa::@16/(word) utoa::value#10 )
[145] (byte~) utoa::$16 ← ((byte)) (word) utoa::value#12
[146] (byte~) utoa::$17 ← (byte) '0' + (byte~) utoa::$16
[147] *((byte*) utoa::dst#12) ← (byte~) utoa::$17
[148] (byte*) utoa::dst#3 ← ++ (byte*) utoa::dst#12
[149] *((byte*) utoa::dst#3) ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:utoa::@return
utoa::@return: scope:[utoa] from utoa::@4
[150] return
to:@return
utoa::@8: scope:[utoa] from utoa::@16 utoa::@3
[151] (byte*) append::dst#3 ← (byte*) utoa::dst#13
[152] (word) append::value#4 ← (word) utoa::value#10
[153] call append
[154] (word) append::return#10 ← (word) append::value#5
to:utoa::@12
utoa::@12: scope:[utoa] from utoa::@8
[155] (word) utoa::value#3 ← (word) append::return#10
[156] (byte*) utoa::dst#4 ← ++ (byte*) utoa::dst#13
to:utoa::@4
utoa::@7: scope:[utoa] from utoa::@15 utoa::@2
[157] (byte*) append::dst#2 ← (byte*) utoa::dst#10
[158] (word) append::value#3 ← (word) utoa::value#11
[159] call append
[160] (word) append::return#4 ← (word) append::value#5
to:utoa::@11
utoa::@11: scope:[utoa] from utoa::@7
[161] (word) utoa::value#2 ← (word) append::return#4
[162] (byte*) utoa::dst#2 ← ++ (byte*) utoa::dst#10
to:utoa::@3
utoa::@6: scope:[utoa] from utoa::@1 utoa::@14
[163] (byte*) append::dst#1 ← (byte*) utoa::dst#16
[164] (word) append::value#2 ← (word) utoa::value#6
[165] call append
[166] (word) append::return#3 ← (word) append::value#5
to:utoa::@10
utoa::@10: scope:[utoa] from utoa::@6
[167] (word) utoa::value#1 ← (word) append::return#3
[168] (byte*) utoa::dst#1 ← ++ (byte*) utoa::dst#16
to:utoa::@2
utoa::@5: scope:[utoa] from utoa::@13
[169] (word) append::value#1 ← (word) utoa::value#4
[170] call append
[171] (word) append::return#2 ← (word) append::value#5
to:utoa::@9
utoa::@9: scope:[utoa] from utoa::@5
[172] (word) utoa::value#0 ← (word) append::return#2
to:utoa::@1
append: scope:[append] from utoa::@5 utoa::@6 utoa::@7 utoa::@8
[173] (word) append::sub#6 ← phi( utoa::@5/(word/signed word/dword/signed dword) $2710 utoa::@6/(word/signed word/dword/signed dword) $3e8 utoa::@7/(byte/signed byte/word/signed word/dword/signed dword) $64 utoa::@8/(byte/signed byte/word/signed word/dword/signed dword) $a )
[173] (word) append::value#8 ← phi( utoa::@5/(word) append::value#1 utoa::@6/(word) append::value#2 utoa::@7/(word) append::value#3 utoa::@8/(word) append::value#4 )
[173] (byte*) append::dst#4 ← phi( utoa::@5/(const byte[6]) myprintf::buf6#0 utoa::@6/(byte*) append::dst#1 utoa::@7/(byte*) append::dst#2 utoa::@8/(byte*) append::dst#3 )
[174] *((byte*) append::dst#4) ← (byte) '0'
to:append::@1
append::@1: scope:[append] from append append::@2
[175] (word) append::value#5 ← phi( append/(word) append::value#8 append::@2/(word) append::value#0 )
[176] if((word) append::value#5>=(word) append::sub#6) goto append::@2
to:append::@return
append::@return: scope:[append] from append::@1
[177] return
to:@return
append::@2: scope:[append] from append::@1
[178] *((byte*) append::dst#4) ← ++ *((byte*) append::dst#4)
[179] (word) append::value#0 ← (word) append::value#5 - (word) append::sub#6
to:append::@1
div10: scope:[div10] from main::@6
[180] (word~) div10::$0 ← (word) div10::val#4 >> (byte/signed byte/word/signed word/dword/signed dword) 1
[181] (word) div10::val#0 ← (word~) div10::$0 + (byte/signed byte/word/signed word/dword/signed dword) 1
[182] (word~) div10::$2 ← (word) div10::val#0 << (byte/signed byte/word/signed word/dword/signed dword) 1
[183] (word) div10::val#1 ← (word) div10::val#0 + (word~) div10::$2
[184] (word~) div10::$3 ← (word) div10::val#1 >> (byte/signed byte/word/signed word/dword/signed dword) 4
[185] (word) div10::val#2 ← (word) div10::val#1 + (word~) div10::$3
[186] (word~) div10::$4 ← (word) div10::val#2 >> (byte/signed byte/word/signed word/dword/signed dword) 4
[187] (word~) div10::$5 ← (word~) div10::$4 >> (byte/signed byte/word/signed word/dword/signed dword) 4
[188] (word) div10::val#3 ← (word) div10::val#2 + (word~) div10::$5
[189] (word) div10::return#0 ← (word) div10::val#3 >> (byte/signed byte/word/signed word/dword/signed dword) 4
to:div10::@return
div10::@return: scope:[div10] from div10
[190] return
to:@return
div16u: scope:[div16u] from main::@2
[191] (word) divr16u::dividend#1 ← (word) div16u::dividend#0
[192] call divr16u
[193] (word) divr16u::return#2 ← (word) divr16u::return#0
to:div16u::@1
div16u::@1: scope:[div16u] from div16u
[194] (word) div16u::return#0 ← (word) divr16u::return#2
to:div16u::@return
div16u::@return: scope:[div16u] from div16u::@1
[195] return
to:@return
divr16u: scope:[divr16u] from div16u
[196] phi()
to:divr16u::@1
divr16u::@1: scope:[divr16u] from divr16u divr16u::@3
[197] (byte) divr16u::i#2 ← phi( divr16u/(byte/signed byte/word/signed word/dword/signed dword) 0 divr16u::@3/(byte) divr16u::i#1 )
[197] (word) divr16u::quotient#3 ← phi( divr16u/(byte/signed byte/word/signed word/dword/signed dword) 0 divr16u::@3/(word) divr16u::return#0 )
[197] (word) divr16u::dividend#2 ← phi( divr16u/(word) divr16u::dividend#1 divr16u::@3/(word) divr16u::dividend#0 )
[197] (word) divr16u::rem#4 ← phi( divr16u/(byte/signed byte/word/signed word/dword/signed dword) 0 divr16u::@3/(word) divr16u::rem#9 )
[198] (word) divr16u::rem#0 ← (word) divr16u::rem#4 << (byte/signed byte/word/signed word/dword/signed dword) 1
[199] (byte~) divr16u::$1 ← > (word) divr16u::dividend#2
[200] (byte~) divr16u::$2 ← (byte~) divr16u::$1 & (byte/word/signed word/dword/signed dword) $80
[201] if((byte~) divr16u::$2==(byte/signed byte/word/signed word/dword/signed dword) 0) goto divr16u::@2
to:divr16u::@4
divr16u::@4: scope:[divr16u] from divr16u::@1
[202] (word) divr16u::rem#1 ← (word) divr16u::rem#0 | (byte/signed byte/word/signed word/dword/signed dword) 1
to:divr16u::@2
divr16u::@2: scope:[divr16u] from divr16u::@1 divr16u::@4
[203] (word) divr16u::rem#5 ← phi( divr16u::@1/(word) divr16u::rem#0 divr16u::@4/(word) divr16u::rem#1 )
[204] (word) divr16u::dividend#0 ← (word) divr16u::dividend#2 << (byte/signed byte/word/signed word/dword/signed dword) 1
[205] (word) divr16u::quotient#1 ← (word) divr16u::quotient#3 << (byte/signed byte/word/signed word/dword/signed dword) 1
[206] if((word) divr16u::rem#5<(const word) div16u::divisor#0) goto divr16u::@3
to:divr16u::@5
divr16u::@5: scope:[divr16u] from divr16u::@2
[207] (word) divr16u::quotient#2 ← ++ (word) divr16u::quotient#1
[208] (word) divr16u::rem#2 ← (word) divr16u::rem#5 - (const word) div16u::divisor#0
to:divr16u::@3
divr16u::@3: scope:[divr16u] from divr16u::@2 divr16u::@5
[209] (word) divr16u::return#0 ← phi( divr16u::@2/(word) divr16u::quotient#1 divr16u::@5/(word) divr16u::quotient#2 )
[209] (word) divr16u::rem#9 ← phi( divr16u::@2/(word) divr16u::rem#5 divr16u::@5/(word) divr16u::rem#2 )
[210] (byte) divr16u::i#1 ← ++ (byte) divr16u::i#2
[211] if((byte) divr16u::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $10) goto divr16u::@1
to:divr16u::@return
divr16u::@return: scope:[divr16u] from divr16u::@3
[212] return
to:@return

9025
src/test/ref/sandbox.log Normal file

File diff suppressed because it is too large Load Diff

333
src/test/ref/sandbox.sym Normal file
View File

@ -0,0 +1,333 @@
(label) @1
(label) @begin
(label) @end
(void()) Print()
(label) Print::@return
(byte*) TIMEHI
(const byte*) TIMEHI#0 TIMEHI = ((byte*))(byte/word/signed word/dword/signed dword) $a1
(byte*) TIMELO
(const byte*) TIMELO#0 TIMELO = ((byte*))(byte/word/signed word/dword/signed dword) $a2
(byte*) VICBANK
(const byte*) VICBANK#0 VICBANK = ((byte*))(word/dword/signed dword) $d018
(word()) append((byte*) append::dst , (word) append::value , (word) append::sub)
(label) append::@1
(label) append::@2
(label) append::@return
(byte*) append::dst
(byte*) append::dst#1 dst zp ZP_WORD:20 2.0
(byte*) append::dst#2 dst zp ZP_WORD:20 2.0
(byte*) append::dst#3 dst zp ZP_WORD:20 2.0
(byte*) append::dst#4 dst zp ZP_WORD:20 335.0
(word) append::return
(word) append::return#10 return zp ZP_WORD:18 4.0
(word) append::return#2 return zp ZP_WORD:18 4.0
(word) append::return#3 return zp ZP_WORD:18 4.0
(word) append::return#4 return zp ZP_WORD:18 4.0
(word) append::sub
(word) append::sub#6 sub zp ZP_WORD:22 333.6666666666667
(word) append::value
(word) append::value#0 value zp ZP_WORD:18 2002.0
(word) append::value#1 value zp ZP_WORD:18 4.0
(word) append::value#2 value zp ZP_WORD:18 4.0
(word) append::value#3 value zp ZP_WORD:18 4.0
(word) append::value#4 value zp ZP_WORD:18 4.0
(word) append::value#5 value zp ZP_WORD:18 376.625
(word) append::value#8 value zp ZP_WORD:18 5.0
(word()) div10((word) div10::val)
(word~) div10::$0 $0 zp ZP_WORD:4 4.0
(word~) div10::$2 $2 zp ZP_WORD:6 4.0
(word~) div10::$3 $3 zp ZP_WORD:4 4.0
(word~) div10::$4 $4 zp ZP_WORD:6 4.0
(word~) div10::$5 $5 zp ZP_WORD:6 4.0
(label) div10::@return
(word) div10::return
(word) div10::return#0 return zp ZP_WORD:4 34.33333333333333
(word) div10::return#2 return zp ZP_WORD:4 202.0
(word) div10::val
(word) div10::val#0 val zp ZP_WORD:4 3.0
(word) div10::val#1 val#1 zp ZP_WORD:6 3.0
(word) div10::val#2 val zp ZP_WORD:4 2.0
(word) div10::val#3 val zp ZP_WORD:4 4.0
(word) div10::val#4 val#4 zp ZP_WORD:2 103.0
(word()) div16u((word) div16u::dividend , (word) div16u::divisor)
(label) div16u::@1
(label) div16u::@return
(word) div16u::dividend
(word) div16u::dividend#0 dividend zp ZP_WORD:2 103.0
(word) div16u::divisor
(const word) div16u::divisor#0 divisor = (byte/signed byte/word/signed word/dword/signed dword) $a
(word) div16u::return
(word) div16u::return#0 return zp ZP_WORD:4 34.33333333333333
(word) div16u::return#2 return zp ZP_WORD:4 202.0
(word()) divr16u((word) divr16u::dividend , (word) divr16u::divisor , (word) divr16u::rem)
(byte~) divr16u::$1 reg byte a 2002.0
(byte~) divr16u::$2 reg byte a 2002.0
(label) divr16u::@1
(label) divr16u::@2
(label) divr16u::@3
(label) divr16u::@4
(label) divr16u::@5
(label) divr16u::@return
(word) divr16u::dividend
(word) divr16u::dividend#0 dividend zp ZP_WORD:8 250.25
(word) divr16u::dividend#1 dividend zp ZP_WORD:8 2.0
(word) divr16u::dividend#2 dividend zp ZP_WORD:8 429.2857142857143
(word) divr16u::divisor
(byte) divr16u::i
(byte) divr16u::i#1 reg byte x 1501.5
(byte) divr16u::i#2 reg byte x 154.0
(word) divr16u::quotient
(word) divr16u::quotient#1 quotient zp ZP_WORD:4 1501.5
(word) divr16u::quotient#2 quotient zp ZP_WORD:4 1001.0
(word) divr16u::quotient#3 quotient zp ZP_WORD:4 250.25
(word) divr16u::rem
(word) divr16u::rem#0 rem zp ZP_WORD:6 750.75
(word) divr16u::rem#1 rem zp ZP_WORD:6 2002.0
(word) divr16u::rem#2 rem zp ZP_WORD:6 2002.0
(word) divr16u::rem#4 rem zp ZP_WORD:6 2002.0
(word) divr16u::rem#5 rem zp ZP_WORD:6 1001.0
(word) divr16u::rem#9 rem zp ZP_WORD:6 1001.0
(word) divr16u::return
(word) divr16u::return#0 return zp ZP_WORD:4 601.0
(word) divr16u::return#2 return zp ZP_WORD:4 4.0
(signed word()) main()
(word~) main::$11 $11 zp ZP_WORD:6 22.0
(word~) main::$12 $12 zp ZP_WORD:6 11.0
(word~) main::$13 $13 zp ZP_WORD:8 22.0
(word~) main::$2 $2 zp ZP_WORD:6 22.0
(word~) main::$3 $3 zp ZP_WORD:6 11.0
(word~) main::$4 $4 zp ZP_WORD:8 22.0
(label) main::@1
(label) main::@10
(label) main::@11
(label) main::@12
(label) main::@13
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@7
(label) main::@8
(label) main::@9
(label) main::@return
(signed word) main::return
(const string) main::str str = (string) "200 DIV16U: %5d,%4d IN %04d FRAMESm@"
(const string) main::str1 str1 = (string) "200 DIV10 : %5d,%4d IN %04d FRAMESm@"
(word) main::u
(word) main::u#11 u zp ZP_WORD:2 7.05263157894737
(word) main::u#15 u zp ZP_WORD:2 7.05263157894737
(word) main::u#2 u zp ZP_WORD:2 7.333333333333333
(word) main::u#4 u zp ZP_WORD:2 7.333333333333333
(word) main::v
(word) main::v#1 v zp ZP_WORD:4 14.0
(word) main::v#2 v zp ZP_WORD:4 14.0
(byte()) myprintf((byte*) myprintf::dst , (byte*) myprintf::str , (word) myprintf::w1 , (word) myprintf::w2 , (word) myprintf::w3)
(word~) myprintf::$17 $17 zp ZP_WORD:18 202.0
(byte~) myprintf::$22 reg byte a 101.0
(byte~) myprintf::$23 reg byte a 202.0
(byte~) myprintf::$28 reg byte a 101.0
(byte~) myprintf::$29 reg byte a 202.0
(byte~) myprintf::$39 reg byte a 1001.0
(byte~) myprintf::$47 reg byte a 202.0
(label) myprintf::@1
(label) myprintf::@10
(label) myprintf::@11
(label) myprintf::@12
(label) myprintf::@13
(label) myprintf::@14
(label) myprintf::@15
(label) myprintf::@16
(label) myprintf::@17
(label) myprintf::@18
(label) myprintf::@19
(label) myprintf::@2
(label) myprintf::@20
(label) myprintf::@21
(label) myprintf::@22
(label) myprintf::@23
(label) myprintf::@24
(label) myprintf::@25
(label) myprintf::@26
(label) myprintf::@27
(label) myprintf::@28
(label) myprintf::@29
(label) myprintf::@3
(label) myprintf::@30
(label) myprintf::@31
(label) myprintf::@32
(label) myprintf::@33
(label) myprintf::@34
(label) myprintf::@35
(label) myprintf::@36
(label) myprintf::@37
(label) myprintf::@38
(label) myprintf::@39
(label) myprintf::@4
(label) myprintf::@40
(label) myprintf::@41
(label) myprintf::@42
(label) myprintf::@43
(label) myprintf::@5
(label) myprintf::@6
(label) myprintf::@7
(label) myprintf::@8
(label) myprintf::@9
(label) myprintf::@return
(byte) myprintf::b
(byte) myprintf::b#1 reg byte x 126.25000000000003
(byte) myprintf::b#15 reg byte x 75.75
(byte) myprintf::b#16 reg byte x 75.75
(byte) myprintf::b#17 reg byte x 248.32
(byte) myprintf::b#25 reg byte x 303.0
(byte) myprintf::b#5 reg byte x 2002.0
(byte) myprintf::b#6 reg byte x 202.0
(byte) myprintf::bArg
(byte) myprintf::bArg#1 bArg zp ZP_BYTE:11 202.0
(byte) myprintf::bArg#10 bArg zp ZP_BYTE:11 235.66666666666663
(byte) myprintf::bArg#12 bArg zp ZP_BYTE:11 12.625
(byte) myprintf::bDigits
(byte) myprintf::bDigits#1 bDigits zp ZP_BYTE:17 202.0
(byte) myprintf::bDigits#10 bDigits zp ZP_BYTE:17 350.5
(byte) myprintf::bDigits#14 bDigits zp ZP_BYTE:17 23.488372093023255
(byte) myprintf::bDigits#16 bDigits zp ZP_BYTE:17 188.25
(byte) myprintf::bDigits#2 bDigits zp ZP_BYTE:17 2002.0
(byte) myprintf::bDigits#24 bDigits zp ZP_BYTE:17 201.99999999999997
(byte) myprintf::bDigits#25 bDigits zp ZP_BYTE:17 1607.0
(byte) myprintf::bDigits#3 bDigits zp ZP_BYTE:17 2002.0
(byte) myprintf::bDigits#8 bDigits zp ZP_BYTE:17 701.0
(byte) myprintf::bFormat
(byte) myprintf::bFormat#10 bFormat zp ZP_BYTE:10 40.4
(byte) myprintf::bFormat#4 bFormat zp ZP_BYTE:10 168.33333333333331
(byte) myprintf::bLeadZero
(byte) myprintf::bLeadZero#10 bLeadZero zp ZP_BYTE:15 22.818181818181817
(byte) myprintf::bLeadZero#18 bLeadZero zp ZP_BYTE:15 168.33333333333331
(byte) myprintf::bLen
(byte) myprintf::bLen#1 bLen zp ZP_BYTE:16 202.0
(byte) myprintf::bLen#10 reg byte y 43.285714285714285
(byte) myprintf::bLen#11 bLen zp ZP_BYTE:16 620.8
(byte) myprintf::bLen#12 bLen zp ZP_BYTE:16 1552.0
(byte) myprintf::bLen#13 bLen zp ZP_BYTE:16 1552.0
(byte) myprintf::bLen#14 bLen zp ZP_BYTE:16 34.487804878048784
(byte) myprintf::bLen#23 bLen zp ZP_BYTE:16 1203.0
(byte) myprintf::bLen#24 bLen zp ZP_BYTE:16 460.99999999999994
(byte) myprintf::bLen#28 bLen zp ZP_BYTE:16 1607.0
(byte) myprintf::bLen#3 bLen zp ZP_BYTE:16 202.0
(byte) myprintf::bLen#4 bLen zp ZP_BYTE:16 1001.0
(byte) myprintf::bLen#6 bLen zp ZP_BYTE:16 1001.0
(byte) myprintf::bLen#7 bLen zp ZP_BYTE:16 202.0
(byte) myprintf::bTrailing
(byte) myprintf::bTrailing#10 bTrailing zp ZP_BYTE:14 10.712121212121211
(byte) myprintf::bTrailing#21 bTrailing zp ZP_BYTE:14 168.33333333333331
(byte[6]) myprintf::buf6
(const byte[6]) myprintf::buf6#0 buf6 = { fill( 6, 0) }
(byte) myprintf::digit
(byte) myprintf::digit#2 digit zp ZP_BYTE:10 1501.5
(byte) myprintf::digit#3 digit zp ZP_BYTE:10 1001.0
(byte*) myprintf::dst
(byte) myprintf::return
(byte) myprintf::return#0 return zp ZP_BYTE:16 236.3333333333333
(byte*) myprintf::str
(byte*) myprintf::str#0 str zp ZP_WORD:8 151.5
(byte*) myprintf::str#10 str zp ZP_WORD:8 4.121621621621622
(byte*) myprintf::str#5 str zp ZP_WORD:8 2.0
(word) myprintf::w
(word) myprintf::w#10 w zp ZP_WORD:12 15.303030303030305
(word) myprintf::w#17 w zp ZP_WORD:12 235.66666666666663
(word) myprintf::w#21 w zp ZP_WORD:12 202.0
(word~) myprintf::w#51 w zp ZP_WORD:12 202.0
(word~) myprintf::w#52 w zp ZP_WORD:12 202.0
(word~) myprintf::w#53 w zp ZP_WORD:12 202.0
(word) myprintf::w1
(word) myprintf::w1#0 w1 zp ZP_WORD:2 11.0
(word) myprintf::w1#1 w1 zp ZP_WORD:2 11.0
(word) myprintf::w1#6 w1 zp ZP_WORD:2 1.5974025974025974
(word) myprintf::w2
(word) myprintf::w2#0 w2 zp ZP_WORD:4 22.0
(word) myprintf::w2#1 w2 zp ZP_WORD:4 22.0
(word) myprintf::w2#7 w2 zp ZP_WORD:4 1.5974025974025974
(word) myprintf::w3
(word) myprintf::w3#0 w3 zp ZP_WORD:6 7.333333333333333
(word) myprintf::w3#1 w3 zp ZP_WORD:6 7.333333333333333
(word) myprintf::w3#7 w3 zp ZP_WORD:6 1.5974025974025974
(byte[$64]) strTemp
(const byte[$64]) strTemp#0 strTemp = { fill( $64, 0) }
(void()) utoa((word) utoa::value , (byte*) utoa::dst)
(byte~) utoa::$16 reg byte a 4.0
(byte~) utoa::$17 reg byte a 4.0
(label) utoa::@1
(label) utoa::@10
(label) utoa::@11
(label) utoa::@12
(label) utoa::@13
(label) utoa::@14
(label) utoa::@15
(label) utoa::@16
(label) utoa::@2
(label) utoa::@3
(label) utoa::@4
(label) utoa::@5
(label) utoa::@6
(label) utoa::@7
(label) utoa::@8
(label) utoa::@9
(label) utoa::@return
(byte) utoa::bStarted
(byte) utoa::bStarted#5 reg byte x 1.3333333333333333
(byte) utoa::bStarted#6 reg byte x 2.0
(byte) utoa::bStarted#7 reg byte x 4.0
(byte*) utoa::dst
(byte*) utoa::dst#1 dst zp ZP_WORD:20 4.0
(byte*) utoa::dst#10 dst zp ZP_WORD:20 1.25
(byte*) utoa::dst#12 dst zp ZP_WORD:20 2.0
(byte*) utoa::dst#13 dst zp ZP_WORD:20 1.25
(byte*) utoa::dst#16 dst zp ZP_WORD:20 0.75
(byte*) utoa::dst#2 dst zp ZP_WORD:20 4.0
(byte*) utoa::dst#3 dst zp ZP_WORD:20 4.0
(byte*) utoa::dst#4 dst zp ZP_WORD:20 4.0
(word) utoa::value
(word) utoa::value#0 value zp ZP_WORD:18 4.0
(word) utoa::value#1 value zp ZP_WORD:18 2.0
(word) utoa::value#10 value zp ZP_WORD:18 2.5
(word) utoa::value#11 value zp ZP_WORD:18 2.5
(word) utoa::value#12 value zp ZP_WORD:18 6.0
(word) utoa::value#2 value zp ZP_WORD:18 2.0
(word) utoa::value#3 value zp ZP_WORD:18 2.0
(word) utoa::value#4 value zp ZP_WORD:18 35.66666666666666
(word) utoa::value#6 value zp ZP_WORD:18 2.5
(byte*) zp1
(const byte*) zp1#0 zp1 = ((byte*))(byte/signed byte/word/signed word/dword/signed dword) $61
(byte*) zp2
(const byte*) zp2#0 zp2 = ((byte*))(byte/signed byte/word/signed word/dword/signed dword) $62
zp ZP_WORD:2 [ main::u#11 main::u#2 myprintf::w1#6 myprintf::w1#0 myprintf::w1#1 div16u::dividend#0 main::u#15 main::u#4 div10::val#4 ]
zp ZP_WORD:4 [ myprintf::w2#7 myprintf::w2#0 myprintf::w2#1 main::v#1 main::v#2 div16u::return#2 div16u::return#0 div10::return#2 div10::return#0 divr16u::quotient#3 divr16u::return#0 divr16u::quotient#1 divr16u::quotient#2 divr16u::return#2 div10::$3 div10::val#2 div10::val#3 div10::$0 div10::val#0 ]
zp ZP_WORD:6 [ myprintf::w3#7 myprintf::w3#0 myprintf::w3#1 main::$3 main::$12 main::$2 main::$11 divr16u::rem#4 divr16u::rem#9 divr16u::rem#5 divr16u::rem#0 divr16u::rem#1 divr16u::rem#2 div10::$2 div10::val#1 div10::$4 div10::$5 ]
zp ZP_WORD:8 [ myprintf::str#10 myprintf::str#5 myprintf::str#0 divr16u::dividend#2 divr16u::dividend#1 divr16u::dividend#0 main::$4 main::$13 ]
zp ZP_BYTE:10 [ myprintf::bFormat#10 myprintf::bFormat#4 myprintf::digit#3 myprintf::digit#2 ]
zp ZP_BYTE:11 [ myprintf::bArg#12 myprintf::bArg#10 myprintf::bArg#1 ]
zp ZP_WORD:12 [ myprintf::w#10 myprintf::w#17 myprintf::w#21 myprintf::w#51 myprintf::w#52 myprintf::w#53 ]
zp ZP_BYTE:14 [ myprintf::bTrailing#10 myprintf::bTrailing#21 ]
zp ZP_BYTE:15 [ myprintf::bLeadZero#10 myprintf::bLeadZero#18 ]
reg byte a [ myprintf::$22 ]
reg byte a [ myprintf::$28 ]
reg byte x [ myprintf::b#17 myprintf::b#5 ]
zp ZP_BYTE:16 [ myprintf::bLen#11 myprintf::bLen#13 myprintf::bLen#12 myprintf::bLen#23 myprintf::bLen#14 myprintf::return#0 myprintf::bLen#28 myprintf::bLen#7 myprintf::bLen#3 myprintf::bLen#24 myprintf::bLen#6 myprintf::bLen#1 myprintf::bLen#4 ]
zp ZP_BYTE:17 [ myprintf::bDigits#10 myprintf::bDigits#8 myprintf::bDigits#14 myprintf::bDigits#24 myprintf::bDigits#25 myprintf::bDigits#1 myprintf::bDigits#16 myprintf::bDigits#3 myprintf::bDigits#2 ]
reg byte a [ myprintf::$39 ]
reg byte x [ myprintf::b#25 myprintf::b#1 myprintf::b#6 ]
reg byte x [ utoa::bStarted#7 utoa::bStarted#6 utoa::bStarted#5 ]
zp ZP_WORD:18 [ utoa::value#12 utoa::value#3 utoa::value#10 utoa::value#2 utoa::value#11 utoa::value#6 utoa::value#4 utoa::value#0 utoa::value#1 append::value#5 append::value#8 append::value#1 append::value#2 append::value#3 append::value#4 append::value#0 append::return#10 append::return#4 append::return#3 append::return#2 myprintf::$17 ]
zp ZP_WORD:20 [ utoa::dst#12 utoa::dst#4 utoa::dst#13 utoa::dst#2 utoa::dst#10 utoa::dst#16 utoa::dst#1 append::dst#4 append::dst#1 append::dst#2 append::dst#3 utoa::dst#3 ]
zp ZP_WORD:22 [ append::sub#6 ]
reg byte x [ divr16u::i#2 divr16u::i#1 ]
reg byte x [ myprintf::b#15 ]
reg byte a [ myprintf::$23 ]
reg byte y [ myprintf::bLen#10 ]
reg byte x [ myprintf::b#16 ]
reg byte a [ myprintf::$29 ]
reg byte a [ myprintf::$47 ]
reg byte a [ utoa::$16 ]
reg byte a [ utoa::$17 ]
reg byte a [ divr16u::$1 ]
reg byte a [ divr16u::$2 ]

View File

@ -0,0 +1,17 @@
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
.label SCREEN = $400
ldx #0
b1:
lda #'a'
sta SCREEN,x
lda #0
sta $d020
inx
inx
cpx #$80
bcc b1
rts
}

View File

@ -0,0 +1,22 @@
@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::@1
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 )
[6] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte) 'a'
[7] *(((byte*))(word/dword/signed dword) $d020) ← (byte/signed byte/word/signed word/dword/signed dword) 0
[8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2
[9] if((byte) main::i#1<(byte/word/signed word/dword/signed dword) $80) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[10] return
to:@return

View File

@ -0,0 +1,328 @@
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
(byte) main::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@1
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@1/(byte) main::i#1 )
*((byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte) 'a'
(byte*~) main::$0 ← ((byte*)) (word/dword/signed dword) $d020
*((byte*~) main::$0) ← (byte/signed byte/word/signed word/dword/signed dword) 0
(byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2
(bool~) main::$1 ← (byte) main::i#1 < (byte/word/signed word/dword/signed dword) $80
if((bool~) main::$1) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
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
(bool~) main::$1
(label) main::@1
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
Culled Empty Block (label) @2
Successful SSA optimization Pass2CullEmptyBlocks
Simple Condition (bool~) main::$1 [8] if((byte) main::i#1<(byte/word/signed word/dword/signed dword) $80) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
Constant (const byte) main::i#0 = 0
Constant (const byte*) main::$0 = ((byte*))$d020
Successful SSA optimization Pass2ConstantIdentification
Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
Constant inlined main::$0 = ((byte*))(word/dword/signed dword) $d020
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@3(between main::@1 and main::@1)
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
CALL GRAPH
Calls in [] to main:2
Created 1 initial phi equivalence classes
Coalesced [11] main::i#3 ← main::i#1
Coalesced down to 1 phi equivalence classes
Culled Empty Block (label) main::@3
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::@1
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@1/(byte) main::i#1 )
[6] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte) 'a'
[7] *(((byte*))(word/dword/signed dword) $d020) ← (byte/signed byte/word/signed word/dword/signed dword) 0
[8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2
[9] if((byte) main::i#1<(byte/word/signed word/dword/signed dword) $80) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@1
[10] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::SCREEN
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 11.0
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
INITIAL ASM
//SEG0 File Comments
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
bend:
//SEG10 main
main: {
.label SCREEN = $400
.label i = 2
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta i
jmp b1
//SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
b1_from_b1:
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
jmp b1
//SEG15 main::@1
b1:
//SEG16 [6] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte) 'a' -- pbuc1_derefidx_vbuz1=vbuc2
lda #'a'
ldy i
sta SCREEN,y
//SEG17 [7] *(((byte*))(word/dword/signed dword) $d020) ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- _deref_pbuc1=vbuc2
lda #0
sta $d020
//SEG18 [8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 -- vbuz1=vbuz1_plus_2
lda i
clc
adc #2
sta i
//SEG19 [9] if((byte) main::i#1<(byte/word/signed word/dword/signed dword) $80) goto main::@1 -- vbuz1_lt_vbuc1_then_la1
lda i
cmp #$80
bcc b1_from_b1
jmp breturn
//SEG20 main::@return
breturn:
//SEG21 [10] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte) 'a' [ 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] *(((byte*))(word/dword/signed dword) $d020) ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte) 'a' [ main::i#2 ] ( main:2 [ main::i#2 ] ) always clobbers reg byte a
Statement [7] *(((byte*))(word/dword/signed dword) $d020) ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ 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 ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 27.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Uplift Scope []
Uplifting [main] best 343 combination reg byte x [ main::i#2 main::i#1 ]
Uplifting [] best 343 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
bend:
//SEG10 main
main: {
.label SCREEN = $400
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
jmp b1
//SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
b1_from_b1:
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
jmp b1
//SEG15 main::@1
b1:
//SEG16 [6] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte) 'a' -- pbuc1_derefidx_vbuxx=vbuc2
lda #'a'
sta SCREEN,x
//SEG17 [7] *(((byte*))(word/dword/signed dword) $d020) ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- _deref_pbuc1=vbuc2
lda #0
sta $d020
//SEG18 [8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 -- vbuxx=vbuxx_plus_2
inx
inx
//SEG19 [9] if((byte) main::i#1<(byte/word/signed word/dword/signed dword) $80) goto main::@1 -- vbuxx_lt_vbuc1_then_la1
cpx #$80
bcc b1_from_b1
jmp breturn
//SEG20 main::@return
breturn:
//SEG21 [10] return
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1_from_b1 with b1
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Removing instruction b1_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction jmp b1
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 11.0
reg byte x [ main::i#2 main::i#1 ]
FINAL ASSEMBLER
Score: 241
//SEG0 File Comments
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
//SEG9 @end
//SEG10 main
main: {
.label SCREEN = $400
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
//SEG13 [5] phi from main::@1 to main::@1 [phi:main::@1->main::@1]
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@1->main::@1#0] -- register_copy
//SEG15 main::@1
b1:
//SEG16 [6] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte) 'a' -- pbuc1_derefidx_vbuxx=vbuc2
lda #'a'
sta SCREEN,x
//SEG17 [7] *(((byte*))(word/dword/signed dword) $d020) ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- _deref_pbuc1=vbuc2
lda #0
sta $d020
//SEG18 [8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 -- vbuxx=vbuxx_plus_2
inx
inx
//SEG19 [9] if((byte) main::i#1<(byte/word/signed word/dword/signed dword) $80) goto main::@1 -- vbuxx_lt_vbuc1_then_la1
cpx #$80
bcc b1
//SEG20 main::@return
//SEG21 [10] return
rts
}

View File

@ -0,0 +1,13 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 11.0
reg byte x [ main::i#2 main::i#1 ]