From 1c59ae231e2292c5c280d7b0af305f49a165be0b Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Wed, 29 Nov 2017 21:31:20 +0100 Subject: [PATCH] Fixed problem with inline string by extracting them as local constants. Closes #98 --- .../java/dk/camelot64/kickc/Compiler.java | 1 + .../java/dk/camelot64/kickc/model/Scope.java | 6 +- .../passes/Pass1ExtractInlineStrings.java | 80 + .../kickc/passes/Pass2ConstantInlining.java | 4 +- .../dk/camelot64/kickc/test/TestErrors.java | 4 - .../dk/camelot64/kickc/test/TestPrograms.java | 4 + .../dk/camelot64/kickc/test/inline-string.kc | 10 +- .../kickc/test/ref/inline-string.asm | 52 + .../kickc/test/ref/inline-string.cfg | 41 + .../kickc/test/ref/inline-string.log | 1772 +++++++++++++++++ .../kickc/test/ref/inline-string.sym | 27 + 11 files changed, 1991 insertions(+), 10 deletions(-) create mode 100644 src/main/java/dk/camelot64/kickc/passes/Pass1ExtractInlineStrings.java create mode 100644 src/main/java/dk/camelot64/kickc/test/ref/inline-string.asm create mode 100644 src/main/java/dk/camelot64/kickc/test/ref/inline-string.cfg create mode 100644 src/main/java/dk/camelot64/kickc/test/ref/inline-string.log create mode 100644 src/main/java/dk/camelot64/kickc/test/ref/inline-string.sym diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index fad6055e4..599ff3f5e 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -86,6 +86,7 @@ public class Compiler { log.append("INITIAL CONTROL FLOW GRAPH"); log.append(program.getGraph().toString(program)); + new Pass1ExtractInlineStrings(program).extract(); new Pass1EliminateUncalledProcedures(program).eliminate(); new Pass1EliminateEmptyBlocks(program).eliminate(); log.append("CONTROL FLOW GRAPH"); diff --git a/src/main/java/dk/camelot64/kickc/model/Scope.java b/src/main/java/dk/camelot64/kickc/model/Scope.java index e6e08c88a..996f558a4 100644 --- a/src/main/java/dk/camelot64/kickc/model/Scope.java +++ b/src/main/java/dk/camelot64/kickc/model/Scope.java @@ -112,12 +112,16 @@ public abstract class Scope implements Symbol { } public VariableIntermediate addVariableIntermediate() { - String name = "$" + intermediateVarCount++; + String name = allocateIntermediateVariableName(); VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolType.VAR); add(symbol); return symbol; } + public String allocateIntermediateVariableName() { + return "$" + intermediateVarCount++; + } + public Symbol getSymbol(SymbolRef symbolRef) { return getSymbol(symbolRef.getFullName()); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1ExtractInlineStrings.java b/src/main/java/dk/camelot64/kickc/passes/Pass1ExtractInlineStrings.java new file mode 100644 index 000000000..0a462d7a5 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1ExtractInlineStrings.java @@ -0,0 +1,80 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.*; + +import java.util.*; + +/** + * Eliminate uncalled methods + */ +public class Pass1ExtractInlineStrings { + + private Program program; + + public Pass1ExtractInlineStrings(Program program) { + this.program = program; + } + + public void extract() { + for (ControlFlowBlock block : program.getGraph().getAllBlocks()) { + ListIterator stmtIt = block.getStatements().listIterator(); + Scope blockScope = program.getScope().getScope(block.getScope()); + while (stmtIt.hasNext()) { + Statement statement = stmtIt.next(); + if (statement instanceof StatementCall) { + StatementCall call = (StatementCall) statement; + ListIterator parIt = call.getParameters().listIterator(); + int parNum = 0; + while (parIt.hasNext()) { + RValue parameter = parIt.next(); + if (parameter instanceof ConstantString) { + Procedure procedure = program.getScope().getProcedure(call.getProcedure()); + String parameterName = procedure.getParameterNames().get(parNum); + ConstantVar strConst = createStringConstantVar(blockScope, (ConstantString) parameter, parameterName); + parIt.set(strConst.getRef()); + } + parNum++; + } + } else if (statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + if(assignment.getrValue1() instanceof ConstantString && assignment.getrValue2() instanceof ConstantString) { + continue; + } + if (assignment.getrValue1() instanceof ConstantString) { + ConstantVar strConst = createStringConstantVar(blockScope, (ConstantString) assignment.getrValue1(), null); + assignment.setrValue1(strConst.getRef()); + } + if (assignment.getrValue2() instanceof ConstantString && assignment.getOperator() != null) { + ConstantVar strConst = createStringConstantVar(blockScope, (ConstantString) assignment.getrValue2(), null); + assignment.setrValue2(strConst.getRef()); + } + } else if (statement instanceof StatementReturn) { + StatementReturn statementReturn = (StatementReturn) statement; + if (statementReturn.getValue() instanceof ConstantString) { + ConstantVar strConst = createStringConstantVar(blockScope, (ConstantString) statementReturn.getValue(), null); + statementReturn.setValue(strConst.getRef()); + } + } + } + } + + } + + private ConstantVar createStringConstantVar(Scope blockScope, ConstantString constantString, String nameHint) { + String name; + if (nameHint == null) { + name = blockScope.allocateIntermediateVariableName(); + } else { + int nameHintIdx = 1; + name = nameHint; + while (blockScope.getSymbol(name) != null) { + name = nameHint + nameHintIdx++; + } + } + ConstantVar strConst = new ConstantVar(name, blockScope, new SymbolTypeArray(SymbolType.BYTE), constantString); + blockScope.add(strConst); + program.getLog().append("Creating constant string variable for inline " + strConst.toString(program) + " \"" + constantString.getValue() + "\""); + return strConst; + } + +} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java index 5a51183a1..cefd3f61a 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantInlining.java @@ -92,7 +92,9 @@ public class Pass2ConstantInlining extends Pass2SsaOptimization { Collection allConstants = getProgram().getScope().getAllConstants(true); for (ConstantVar constant : allConstants) { if(constant.getRef().isIntermediate()) { - unnamed.put(constant.getRef(), constant.getValue()); + if(!(constant.getValue() instanceof ConstantString) && !(constant.getValue() instanceof ConstantArray)) { + unnamed.put(constant.getRef(), constant.getValue()); + } } } return unnamed; diff --git a/src/main/java/dk/camelot64/kickc/test/TestErrors.java b/src/main/java/dk/camelot64/kickc/test/TestErrors.java index 399efe827..d2f4324a8 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestErrors.java +++ b/src/main/java/dk/camelot64/kickc/test/TestErrors.java @@ -24,10 +24,6 @@ public class TestErrors extends TestCase { helper = new ReferenceHelper("dk/camelot64/kickc/test/ref/"); } - public void testInlineString() throws IOException, URISyntaxException { - compileAndCompare("inline-string"); - } - public void testConstants() throws IOException, URISyntaxException { compileAndCompare("constants"); } diff --git a/src/main/java/dk/camelot64/kickc/test/TestPrograms.java b/src/main/java/dk/camelot64/kickc/test/TestPrograms.java index 429b807d4..6844d2281 100644 --- a/src/main/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/main/java/dk/camelot64/kickc/test/TestPrograms.java @@ -40,6 +40,10 @@ public class TestPrograms extends TestCase { compileAndCompare("unused-method"); } + public void testInlineString() throws IOException, URISyntaxException { + compileAndCompare("inline-string"); + } + public void testLocalString() throws IOException, URISyntaxException { compileAndCompare("local-string"); } diff --git a/src/main/java/dk/camelot64/kickc/test/inline-string.kc b/src/main/java/dk/camelot64/kickc/test/inline-string.kc index c7ac1af69..c68370ecb 100644 --- a/src/main/java/dk/camelot64/kickc/test/inline-string.kc +++ b/src/main/java/dk/camelot64/kickc/test/inline-string.kc @@ -1,14 +1,16 @@ -// Inline Strings in method calls are attempted inlined all the way to ASM. This creates error during binding. Instead a local constant byte[] st = "..."; variable should be created (generating an ASM .text). +// Inline Strings in method calls are automatically converted to local constant variables byte[] st = "..."; - generating an ASM .text). -byte* screen = $0400; byte[] msg1 = "message 1 @"; void main() { + byte[] msg2 = "message 2 @"; print(msg1); - print("message 2 @"); + print(msg2); + print("message 3 @"); } +byte* screen = $0400; void print(byte* msg) { while(*msg!='@') { - *(screen++) = *msg; + *(screen++) = *(msg++); } } diff --git a/src/main/java/dk/camelot64/kickc/test/ref/inline-string.asm b/src/main/java/dk/camelot64/kickc/test/ref/inline-string.asm new file mode 100644 index 000000000..ce52508e1 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/inline-string.asm @@ -0,0 +1,52 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label screen = 2 + msg1: .text "message 1 @" + jsr main +main: { + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + lda #msg1 + sta print.msg+1 + jsr print + lda #msg2 + sta print.msg+1 + jsr print + lda #msg + sta print.msg+1 + jsr print + rts + msg: .text "message 3 @" + msg2: .text "message 2 @" +} +print: { + .label msg = 4 + b1: + ldy #0 + lda (msg),y + cmp #'@' + bne b2 + rts + b2: + ldy #0 + lda (msg),y + sta (screen),y + inc screen + bne !+ + inc screen+1 + !: + inc msg + bne !+ + inc msg+1 + !: + jmp b1 +} diff --git a/src/main/java/dk/camelot64/kickc/test/ref/inline-string.cfg b/src/main/java/dk/camelot64/kickc/test/ref/inline-string.cfg new file mode 100644 index 000000000..5c38a9a27 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/inline-string.cfg @@ -0,0 +1,41 @@ +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@2 +@2: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @2 + [3] phi() [ ] ( ) +main: scope:[main] from @2 + [4] phi() [ ] ( main:2 [ ] ) + [5] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + to:main::@1 +main::@1: scope:[main] from main + [6] phi() [ screen#12 ] ( main:2 [ screen#12 ] ) + [7] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + to:main::@2 +main::@2: scope:[main] from main::@1 + [8] phi() [ screen#12 ] ( main:2 [ screen#12 ] ) + [9] call print param-assignment [ ] ( main:2 [ ] ) + to:main::@return +main::@return: scope:[main] from main::@2 + [10] return [ ] ( main:2 [ ] ) + to:@return +print: scope:[print] from main main::@1 main::@2 + [11] (byte*) screen#18 ← phi( main/((byte*))(word/signed word) 1024 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) [ print::msg#6 screen#18 ] ( main:2::print:5 [ print::msg#6 screen#18 ] main:2::print:7 [ print::msg#6 screen#18 ] main:2::print:9 [ print::msg#6 screen#18 ] ) + [11] (byte*) print::msg#6 ← phi( main/(const byte[]) msg1#0 main::@1/(const byte[]) main::msg2#0 main::@2/(const byte[]) main::msg ) [ print::msg#6 screen#18 ] ( main:2::print:5 [ print::msg#6 screen#18 ] main:2::print:7 [ print::msg#6 screen#18 ] main:2::print:9 [ print::msg#6 screen#18 ] ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + [12] (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) + [12] (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) + [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) + to:print::@return +print::@return: scope:[print] from print::@1 + [14] return [ screen#12 ] ( main:2::print:5 [ screen#12 ] main:2::print:7 [ screen#12 ] main:2::print:9 [ screen#12 ] ) + to:@return +print::@2: scope:[print] from print::@1 + [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) + [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] ( main:2::print:5 [ print::msg#4 screen#5 ] main:2::print:7 [ print::msg#4 screen#5 ] main:2::print:9 [ print::msg#4 screen#5 ] ) + [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] ( main:2::print:5 [ print::msg#3 screen#5 ] main:2::print:7 [ print::msg#3 screen#5 ] main:2::print:9 [ print::msg#3 screen#5 ] ) + to:print::@1 diff --git a/src/main/java/dk/camelot64/kickc/test/ref/inline-string.log b/src/main/java/dk/camelot64/kickc/test/ref/inline-string.log new file mode 100644 index 000000000..7abafef85 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/inline-string.log @@ -0,0 +1,1772 @@ +// Inline Strings in method calls are automatically converted to local constant variables byte[] st = "..."; - generating an ASM .text). + +byte[] msg1 = "message 1 @"; +void main() { + byte[] msg2 = "message 2 @"; + print(msg1); + print(msg2); + print("message 3 @"); +} + +byte* screen = $0400; +void print(byte* msg) { + while(*msg!='@') { + *(screen++) = *(msg++); + } +} + +Adding pre/post-modifier (byte*) screen ← ++ (byte*) screen +Adding pre/post-modifier (byte*) print::msg ← ++ (byte*) print::msg +PROGRAM + (byte[]) msg1 ← (string) "message 1 @" +proc (void()) main() + (byte[]) main::msg2 ← (string) "message 2 @" + (void~) main::$0 ← call print (byte[]) msg1 + (void~) main::$1 ← call print (byte[]) main::msg2 + (void~) main::$2 ← call print (string) "message 3 @" +main::@return: + return +endproc // main() + (byte*) screen ← (word/signed word) 1024 +proc (void()) print((byte*) print::msg) +print::@1: + (boolean~) print::$0 ← *((byte*) print::msg) != (byte) '@' + if((boolean~) print::$0) goto print::@2 + goto print::@3 +print::@2: + *((byte*) screen) ← *((byte*) print::msg) + (byte*) screen ← ++ (byte*) screen + (byte*) print::msg ← ++ (byte*) print::msg + goto print::@1 +print::@3: +print::@return: + return +endproc // print() + call main + +SYMBOLS +(void()) main() +(void~) main::$0 +(void~) main::$1 +(void~) main::$2 +(label) main::@return +(byte[]) main::msg2 +(byte[]) msg1 +(void()) print((byte*) print::msg) +(boolean~) print::$0 +(label) print::@1 +(label) print::@2 +(label) print::@3 +(label) print::@return +(byte*) print::msg +(byte*) screen + +Promoting word/signed word to byte* in screen ← ((byte*)) 1024 +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + (byte[]) msg1 ← (string) "message 1 @" + to:@1 +main: scope:[main] from + (byte[]) main::msg2 ← (string) "message 2 @" + (void~) main::$0 ← call print (byte[]) msg1 + (void~) main::$1 ← call print (byte[]) main::msg2 + (void~) main::$2 ← call print (string) "message 3 @" + to:main::@return +main::@return: scope:[main] from main + return + to:@return +@1: scope:[] from @begin + (byte*) screen ← ((byte*)) (word/signed word) 1024 + to:@2 +print: scope:[print] from + to:print::@1 +print::@1: scope:[print] from print print::@2 + (boolean~) print::$0 ← *((byte*) print::msg) != (byte) '@' + if((boolean~) print::$0) goto print::@2 + to:print::@4 +print::@2: scope:[print] from print::@1 print::@5 + *((byte*) screen) ← *((byte*) print::msg) + (byte*) screen ← ++ (byte*) screen + (byte*) print::msg ← ++ (byte*) print::msg + to:print::@1 +print::@4: scope:[print] from print::@1 + to:print::@3 +print::@3: scope:[print] from print::@4 print::@6 + to:print::@return +print::@5: scope:[print] from + to:print::@2 +print::@6: scope:[print] from + to:print::@3 +print::@return: scope:[print] from print::@3 + return + to:@return +@2: scope:[] from @1 + call main + to:@end +@end: scope:[] from @2 + +Creating constant string variable for inline (const byte[]) main::msg "message 3 @" +Removing empty block print::@4 +Removing empty block print::@3 +Removing empty block print::@5 +Removing empty block print::@6 +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte[]) msg1 ← (string) "message 1 @" + to:@1 +main: scope:[main] from + (byte[]) main::msg2 ← (string) "message 2 @" + (void~) main::$0 ← call print (byte[]) msg1 + (void~) main::$1 ← call print (byte[]) main::msg2 + (void~) main::$2 ← call print (const byte[]) main::msg + to:main::@return +main::@return: scope:[main] from main + return + to:@return +@1: scope:[] from @begin + (byte*) screen ← ((byte*)) (word/signed word) 1024 + to:@2 +print: scope:[print] from + to:print::@1 +print::@1: scope:[print] from print print::@2 + (boolean~) print::$0 ← *((byte*) print::msg) != (byte) '@' + if((boolean~) print::$0) goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen) ← *((byte*) print::msg) + (byte*) screen ← ++ (byte*) screen + (byte*) print::msg ← ++ (byte*) print::msg + to:print::@1 +print::@return: scope:[print] from print::@1 + return + to:@return +@2: scope:[] from @1 + call main + to:@end +@end: scope:[] from @2 + +PROCEDURE MODIFY VARIABLE ANALYSIS +main modifies screen +print modifies screen + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL +@begin: scope:[] from + (byte[]) msg1 ← (string) "message 1 @" + to:@1 +main: scope:[main] from @2 + (byte[]) main::msg2 ← (string) "message 2 @" + (byte*) print::msg ← (byte[]) msg1 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte*) screen ← (byte*) screen + (byte*) print::msg ← (byte[]) main::msg2 + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte*) screen ← (byte*) screen + (byte*) print::msg ← (const byte[]) main::msg + call print param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte*) screen ← (byte*) screen + to:main::@return +main::@return: scope:[main] from main::@3 + (byte*) screen ← (byte*) screen + return + to:@return +@1: scope:[] from @begin + (byte*) screen ← ((byte*)) (word/signed word) 1024 + to:@2 +print: scope:[print] from main main::@1 main::@2 + to:print::@1 +print::@1: scope:[print] from print print::@2 + (boolean~) print::$0 ← *((byte*) print::msg) != (byte) '@' + if((boolean~) print::$0) goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen) ← *((byte*) print::msg) + (byte*) screen ← ++ (byte*) screen + (byte*) print::msg ← ++ (byte*) print::msg + to:print::@1 +print::@return: scope:[print] from print::@1 + (byte*) screen ← (byte*) screen + return + to:@return +@2: scope:[] from @1 + call main param-assignment + to:@3 +@3: scope:[] from @2 + (byte*) screen ← (byte*) screen + to:@end +@end: scope:[] from @3 + +Completing Phi functions... +Completing Phi functions... +Completing Phi functions... +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte[]) msg1#0 ← (string) "message 1 @" + to:@1 +main: scope:[main] from @2 + (byte*) screen#15 ← phi( @2/(byte*) screen#17 ) + (byte[]) msg1#1 ← phi( @2/(byte[]) msg1#2 ) + (byte[]) main::msg2#0 ← (string) "message 2 @" + (byte*) print::msg#0 ← (byte[]) msg1#1 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte[]) main::msg2#1 ← phi( main/(byte[]) main::msg2#0 ) + (byte*) screen#8 ← phi( main/(byte*) screen#15 ) + (byte*) screen#0 ← (byte*) screen#8 + (byte*) print::msg#1 ← (byte[]) main::msg2#1 + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte*) screen#9 ← phi( main::@1/(byte*) screen#0 ) + (byte*) screen#1 ← (byte*) screen#9 + (byte*) print::msg#2 ← (const byte[]) main::msg + call print param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte*) screen#10 ← phi( main::@2/(byte*) screen#1 ) + (byte*) screen#2 ← (byte*) screen#10 + to:main::@return +main::@return: scope:[main] from main::@3 + (byte*) screen#11 ← phi( main::@3/(byte*) screen#2 ) + (byte*) screen#3 ← (byte*) screen#11 + return + to:@return +@1: scope:[] from @begin + (byte[]) msg1#3 ← phi( @begin/(byte[]) msg1#0 ) + (byte*) screen#4 ← ((byte*)) (word/signed word) 1024 + to:@2 +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/(byte*) screen#15 main::@1/(byte*) screen#0 main::@2/(byte*) screen#1 ) + (byte*) print::msg#6 ← phi( main/(byte*) print::msg#0 main::@1/(byte*) print::msg#1 main::@2/(byte*) print::msg#2 ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#16 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + (boolean~) print::$0 ← *((byte*) print::msg#4) != (byte) '@' + if((boolean~) print::$0) goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + (byte*) screen#12 ← phi( print::@1/(byte*) screen#16 ) + (byte*) print::msg#5 ← phi( print::@1/(byte*) print::msg#4 ) + *((byte*) screen#12) ← *((byte*) print::msg#5) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#5 + to:print::@1 +print::@return: scope:[print] from print::@1 + (byte*) screen#13 ← phi( print::@1/(byte*) screen#16 ) + (byte*) screen#6 ← (byte*) screen#13 + return + to:@return +@2: scope:[] from @1 + (byte*) screen#17 ← phi( @1/(byte*) screen#4 ) + (byte[]) msg1#2 ← phi( @1/(byte[]) msg1#3 ) + call main param-assignment + to:@3 +@3: scope:[] from @2 + (byte*) screen#14 ← phi( @2/(byte*) screen#17 ) + (byte*) screen#7 ← (byte*) screen#14 + to:@end +@end: scope:[] from @3 + +CONTROL FLOW GRAPH WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + (byte[]) msg1#0 ← (string) "message 1 @" + to:@1 +main: scope:[main] from @2 + (byte*) screen#15 ← phi( @2/(byte*) screen#17 ) + (byte[]) msg1#1 ← phi( @2/(byte[]) msg1#2 ) + (byte[]) main::msg2#0 ← (string) "message 2 @" + (byte*) print::msg#0 ← (byte[]) msg1#1 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte[]) main::msg2#1 ← phi( main/(byte[]) main::msg2#0 ) + (byte*) screen#8 ← phi( main/(byte*) screen#6 ) + (byte*) screen#0 ← (byte*) screen#8 + (byte*) print::msg#1 ← (byte[]) main::msg2#1 + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte*) screen#9 ← phi( main::@1/(byte*) screen#6 ) + (byte*) screen#1 ← (byte*) screen#9 + (byte*) print::msg#2 ← (const byte[]) main::msg + call print param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte*) screen#10 ← phi( main::@2/(byte*) screen#6 ) + (byte*) screen#2 ← (byte*) screen#10 + to:main::@return +main::@return: scope:[main] from main::@3 + (byte*) screen#11 ← phi( main::@3/(byte*) screen#2 ) + (byte*) screen#3 ← (byte*) screen#11 + return + to:@return +@1: scope:[] from @begin + (byte[]) msg1#3 ← phi( @begin/(byte[]) msg1#0 ) + (byte*) screen#4 ← ((byte*)) (word/signed word) 1024 + to:@2 +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/(byte*) screen#15 main::@1/(byte*) screen#0 main::@2/(byte*) screen#1 ) + (byte*) print::msg#6 ← phi( main/(byte*) print::msg#0 main::@1/(byte*) print::msg#1 main::@2/(byte*) print::msg#2 ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#16 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + (boolean~) print::$0 ← *((byte*) print::msg#4) != (byte) '@' + if((boolean~) print::$0) goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + (byte*) screen#12 ← phi( print::@1/(byte*) screen#16 ) + (byte*) print::msg#5 ← phi( print::@1/(byte*) print::msg#4 ) + *((byte*) screen#12) ← *((byte*) print::msg#5) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#5 + to:print::@1 +print::@return: scope:[print] from print::@1 + (byte*) screen#13 ← phi( print::@1/(byte*) screen#16 ) + (byte*) screen#6 ← (byte*) screen#13 + return + to:@return +@2: scope:[] from @1 + (byte*) screen#17 ← phi( @1/(byte*) screen#4 ) + (byte[]) msg1#2 ← phi( @1/(byte[]) msg1#3 ) + call main param-assignment + to:@3 +@3: scope:[] from @2 + (byte*) screen#14 ← phi( @2/(byte*) screen#3 ) + (byte*) screen#7 ← (byte*) screen#14 + to:@end +@end: scope:[] from @3 + +INITIAL SSA SYMBOL TABLE +(label) @1 +(label) @2 +(label) @3 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(const byte[]) main::msg = (string) "message 3 @" +(byte[]) main::msg2 +(byte[]) main::msg2#0 +(byte[]) main::msg2#1 +(byte[]) msg1 +(byte[]) msg1#0 +(byte[]) msg1#1 +(byte[]) msg1#2 +(byte[]) msg1#3 +(void()) print((byte*) print::msg) +(boolean~) print::$0 +(label) print::@1 +(label) print::@2 +(label) print::@return +(byte*) print::msg +(byte*) print::msg#0 +(byte*) print::msg#1 +(byte*) print::msg#2 +(byte*) print::msg#3 +(byte*) print::msg#4 +(byte*) print::msg#5 +(byte*) print::msg#6 +(byte*) screen +(byte*) screen#0 +(byte*) screen#1 +(byte*) screen#10 +(byte*) screen#11 +(byte*) screen#12 +(byte*) screen#13 +(byte*) screen#14 +(byte*) screen#15 +(byte*) screen#16 +(byte*) screen#17 +(byte*) screen#18 +(byte*) screen#2 +(byte*) screen#3 +(byte*) screen#4 +(byte*) screen#5 +(byte*) screen#6 +(byte*) screen#7 +(byte*) screen#8 +(byte*) screen#9 + +Not aliassing across scopes: msg1#1 msg1#2 +Not aliassing across scopes: screen#15 screen#17 +Not aliassing across scopes: print::msg#0 msg1#1 +Not aliassing across scopes: screen#8 screen#6 +Not aliassing across scopes: print::msg#1 main::msg2#1 +Not aliassing across scopes: screen#9 screen#6 +Not aliassing across scopes: screen#10 screen#6 +Not aliassing across scopes: print::msg#6 print::msg#0 +Not aliassing across scopes: screen#18 screen#15 +Not aliassing across scopes: screen#14 screen#3 +Alias (byte[]) main::msg2#0 = (byte[]) main::msg2#1 +Alias (byte*) screen#0 = (byte*) screen#8 +Alias (byte*) screen#1 = (byte*) screen#9 +Alias (byte*) screen#10 = (byte*) screen#2 (byte*) screen#11 (byte*) screen#3 +Alias (byte[]) msg1#0 = (byte[]) msg1#3 (byte[]) msg1#2 +Alias (byte*) print::msg#4 = (byte*) print::msg#5 +Alias (byte*) screen#12 = (byte*) screen#16 (byte*) screen#13 (byte*) screen#6 +Alias (byte*) screen#17 = (byte*) screen#4 +Alias (byte*) screen#14 = (byte*) screen#7 +Succesful SSA optimization Pass2AliasElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte[]) msg1#0 ← (string) "message 1 @" + to:@1 +main: scope:[main] from @2 + (byte*) screen#15 ← phi( @2/(byte*) screen#17 ) + (byte[]) msg1#1 ← phi( @2/(byte[]) msg1#0 ) + (byte[]) main::msg2#0 ← (string) "message 2 @" + (byte*) print::msg#0 ← (byte[]) msg1#1 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte*) screen#0 ← phi( main/(byte*) screen#12 ) + (byte*) print::msg#1 ← (byte[]) main::msg2#0 + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte*) screen#1 ← phi( main::@1/(byte*) screen#12 ) + (byte*) print::msg#2 ← (const byte[]) main::msg + call print param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte*) screen#10 ← phi( main::@2/(byte*) screen#12 ) + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + (byte*) screen#17 ← ((byte*)) (word/signed word) 1024 + to:@2 +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/(byte*) screen#15 main::@1/(byte*) screen#0 main::@2/(byte*) screen#1 ) + (byte*) print::msg#6 ← phi( main/(byte*) print::msg#0 main::@1/(byte*) print::msg#1 main::@2/(byte*) print::msg#2 ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + (boolean~) print::$0 ← *((byte*) print::msg#4) != (byte) '@' + if((boolean~) print::$0) goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen#12) ← *((byte*) print::msg#4) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#4 + to:print::@1 +print::@return: scope:[print] from print::@1 + return + to:@return +@2: scope:[] from @1 + call main param-assignment + to:@3 +@3: scope:[] from @2 + (byte*) screen#14 ← phi( @2/(byte*) screen#10 ) + to:@end +@end: scope:[] from @3 + +Not aliassing across scopes: msg1#1 msg1#0 +Not aliassing across scopes: screen#15 screen#17 +Not aliassing across scopes: print::msg#0 msg1#1 +Not aliassing across scopes: screen#0 screen#12 +Not aliassing across scopes: print::msg#1 main::msg2#0 +Not aliassing across scopes: screen#1 screen#12 +Not aliassing across scopes: screen#10 screen#12 +Not aliassing across scopes: print::msg#6 print::msg#0 +Not aliassing across scopes: screen#18 screen#15 +Not aliassing across scopes: screen#14 screen#10 +Redundant Phi (byte[]) msg1#1 (byte[]) msg1#0 +Redundant Phi (byte*) screen#15 (byte*) screen#17 +Redundant Phi (byte*) screen#0 (byte*) screen#12 +Redundant Phi (byte*) screen#1 (byte*) screen#12 +Redundant Phi (byte*) screen#10 (byte*) screen#12 +Redundant Phi (byte*) screen#14 (byte*) screen#10 +Succesful SSA optimization Pass2RedundantPhiElimination +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte[]) msg1#0 ← (string) "message 1 @" + to:@1 +main: scope:[main] from @2 + (byte[]) main::msg2#0 ← (string) "message 2 @" + (byte*) print::msg#0 ← (byte[]) msg1#0 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte*) print::msg#1 ← (byte[]) main::msg2#0 + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte*) print::msg#2 ← (const byte[]) main::msg + call print param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + (byte*) screen#17 ← ((byte*)) (word/signed word) 1024 + to:@2 +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/(byte*) screen#17 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) + (byte*) print::msg#6 ← phi( main/(byte*) print::msg#0 main::@1/(byte*) print::msg#1 main::@2/(byte*) print::msg#2 ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + (boolean~) print::$0 ← *((byte*) print::msg#4) != (byte) '@' + if((boolean~) print::$0) goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen#12) ← *((byte*) print::msg#4) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#4 + to:print::@1 +print::@return: scope:[print] from print::@1 + return + to:@return +@2: scope:[] from @1 + call main param-assignment + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +Simple Condition (boolean~) print::$0 if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 +Succesful SSA optimization Pass2ConditionalJumpSimplification +CONTROL FLOW GRAPH +@begin: scope:[] from + (byte[]) msg1#0 ← (string) "message 1 @" + to:@1 +main: scope:[main] from @2 + (byte[]) main::msg2#0 ← (string) "message 2 @" + (byte*) print::msg#0 ← (byte[]) msg1#0 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte*) print::msg#1 ← (byte[]) main::msg2#0 + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte*) print::msg#2 ← (const byte[]) main::msg + call print param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + (byte*) screen#17 ← ((byte*)) (word/signed word) 1024 + to:@2 +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/(byte*) screen#17 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) + (byte*) print::msg#6 ← phi( main/(byte*) print::msg#0 main::@1/(byte*) print::msg#1 main::@2/(byte*) print::msg#2 ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen#12) ← *((byte*) print::msg#4) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#4 + to:print::@1 +print::@return: scope:[print] from print::@1 + return + to:@return +@2: scope:[] from @1 + call main param-assignment + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +Constant (const byte[]) msg1#0 = "message 1 @" +Constant (const byte[]) main::msg2#0 = "message 2 @" +Constant (const byte*) print::msg#2 = main::msg +Constant (const byte*) screen#17 = ((byte*))1024 +Succesful SSA optimization Pass2ConstantIdentification +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @2 + (byte*) print::msg#0 ← (const byte[]) msg1#0 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte*) print::msg#1 ← (const byte[]) main::msg2#0 + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + call print param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + to:@2 +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/(const byte*) screen#17 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) + (byte*) print::msg#6 ← phi( main/(byte*) print::msg#0 main::@1/(byte*) print::msg#1 main::@2/(const byte*) print::msg#2 ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen#12) ← *((byte*) print::msg#4) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#4 + to:print::@1 +print::@return: scope:[print] from print::@1 + return + to:@return +@2: scope:[] from @1 + call main param-assignment + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +Constant (const byte*) print::msg#0 = msg1#0 +Constant (const byte*) print::msg#1 = main::msg2#0 +Succesful SSA optimization Pass2ConstantIdentification +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from @2 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + call print param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +@1: scope:[] from @begin + to:@2 +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/(const byte*) screen#17 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) + (byte*) print::msg#6 ← phi( main/(const byte*) print::msg#0 main::@1/(const byte*) print::msg#1 main::@2/(const byte*) print::msg#2 ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen#12) ← *((byte*) print::msg#4) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#4 + to:print::@1 +print::@return: scope:[print] from print::@1 + return + to:@return +@2: scope:[] from @1 + call main param-assignment + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +Culled Empty Block (label) main::@3 +Culled Empty Block (label) @1 +Culled Empty Block (label) @3 +Succesful SSA optimization Pass2CullEmptyBlocks +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@2 +main: scope:[main] from @2 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + call print param-assignment + to:main::@return +main::@return: scope:[main] from main::@2 + return + to:@return +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/(const byte*) screen#17 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) + (byte*) print::msg#6 ← phi( main/(const byte*) print::msg#0 main::@1/(const byte*) print::msg#1 main::@2/(const byte*) print::msg#2 ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen#12) ← *((byte*) print::msg#4) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#4 + to:print::@1 +print::@return: scope:[print] from print::@1 + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +Inlining constant with var siblings (const byte*) print::msg#2 +Inlining constant with var siblings (const byte*) print::msg#2 +Inlining constant with var siblings (const byte*) print::msg#2 +Inlining constant with var siblings (const byte*) print::msg#0 +Inlining constant with var siblings (const byte*) print::msg#0 +Inlining constant with var siblings (const byte*) print::msg#0 +Inlining constant with var siblings (const byte*) print::msg#1 +Inlining constant with var siblings (const byte*) print::msg#1 +Inlining constant with var siblings (const byte*) print::msg#1 +Inlining constant with var siblings (const byte*) screen#17 +Inlining constant with var siblings (const byte*) screen#17 +Inlining constant with var siblings (const byte*) screen#17 +Constant inlined print::msg#2 = (const byte[]) main::msg +Constant inlined print::msg#1 = (const byte[]) main::msg2#0 +Constant inlined print::msg#0 = (const byte[]) msg1#0 +Constant inlined screen#17 = ((byte*))(word/signed word) 1024 +Succesful SSA optimization Pass2ConstantInlining +CONTROL FLOW GRAPH +@begin: scope:[] from + to:@2 +main: scope:[main] from @2 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + call print param-assignment + to:main::@return +main::@return: scope:[main] from main::@2 + return + to:@return +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/((byte*))(word/signed word) 1024 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) + (byte*) print::msg#6 ← phi( main/(const byte[]) msg1#0 main::@1/(const byte[]) main::msg2#0 main::@2/(const byte[]) main::msg ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) + (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) + if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 + to:print::@return +print::@2: scope:[print] from print::@1 + *((byte*) screen#12) ← *((byte*) print::msg#4) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#4 + to:print::@1 +print::@return: scope:[print] from print::@1 + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 + +FINAL SYMBOL TABLE +(label) @2 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(const byte[]) main::msg = (string) "message 3 @" +(byte[]) main::msg2 +(const byte[]) main::msg2#0 = (string) "message 2 @" +(byte[]) msg1 +(const byte[]) msg1#0 = (string) "message 1 @" +(void()) print((byte*) print::msg) +(label) print::@1 +(label) print::@2 +(label) print::@return +(byte*) print::msg +(byte*) print::msg#3 +(byte*) print::msg#4 +(byte*) print::msg#6 +(byte*) screen +(byte*) screen#12 +(byte*) screen#18 +(byte*) screen#5 + +Block Sequence Planned @begin @2 @end main main::@1 main::@2 main::@return print print::@1 print::@return print::@2 +Block Sequence Planned @begin @2 @end main main::@1 main::@2 main::@return print print::@1 print::@return print::@2 +CONTROL FLOW GRAPH - PHI LIFTED +@begin: scope:[] from + to:@2 +@2: scope:[] from @begin + call main param-assignment + to:@end +@end: scope:[] from @2 +main: scope:[main] from @2 + call print param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte*~) screen#19 ← (byte*) screen#12 + call print param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte*~) screen#20 ← (byte*) screen#12 + call print param-assignment + to:main::@return +main::@return: scope:[main] from main::@2 + return + to:@return +print: scope:[print] from main main::@1 main::@2 + (byte*) screen#18 ← phi( main/((byte*))(word/signed word) 1024 main::@1/(byte*~) screen#19 main::@2/(byte*~) screen#20 ) + (byte*) print::msg#6 ← phi( main/(const byte[]) msg1#0 main::@1/(const byte[]) main::msg2#0 main::@2/(const byte[]) main::msg ) + (byte*~) print::msg#7 ← (byte*) print::msg#6 + (byte*~) screen#21 ← (byte*) screen#18 + to:print::@1 +print::@1: scope:[print] from print print::@2 + (byte*) screen#12 ← phi( print/(byte*~) screen#21 print::@2/(byte*~) screen#22 ) + (byte*) print::msg#4 ← phi( print/(byte*~) print::msg#7 print::@2/(byte*~) print::msg#8 ) + if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 + to:print::@return +print::@return: scope:[print] from print::@1 + return + to:@return +print::@2: scope:[print] from print::@1 + *((byte*) screen#12) ← *((byte*) print::msg#4) + (byte*) screen#5 ← ++ (byte*) screen#12 + (byte*) print::msg#3 ← ++ (byte*) print::msg#4 + (byte*~) print::msg#8 ← (byte*) print::msg#3 + (byte*~) screen#22 ← (byte*) screen#5 + to:print::@1 + +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to print:5 print:7 print:9 + +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - LIVE RANGES FOUND +@begin: scope:[] from + [0] phi() [ ] + to:@2 +@2: scope:[] from @begin + [1] phi() [ ] + [2] call main param-assignment [ ] + to:@end +@end: scope:[] from @2 + [3] phi() [ ] +main: scope:[main] from @2 + [4] phi() [ ] + [5] call print param-assignment [ screen#12 ] + to:main::@1 +main::@1: scope:[main] from main + [6] (byte*~) screen#19 ← (byte*) screen#12 [ screen#19 ] + [7] call print param-assignment [ screen#12 ] + to:main::@2 +main::@2: scope:[main] from main::@1 + [8] (byte*~) screen#20 ← (byte*) screen#12 [ screen#20 ] + [9] call print param-assignment [ ] + to:main::@return +main::@return: scope:[main] from main::@2 + [10] return [ ] + to:@return +print: scope:[print] from main main::@1 main::@2 + [11] (byte*) screen#18 ← phi( main/((byte*))(word/signed word) 1024 main::@1/(byte*~) screen#19 main::@2/(byte*~) screen#20 ) [ print::msg#6 screen#18 ] + [11] (byte*) print::msg#6 ← phi( main/(const byte[]) msg1#0 main::@1/(const byte[]) main::msg2#0 main::@2/(const byte[]) main::msg ) [ print::msg#6 screen#18 ] + [12] (byte*~) print::msg#7 ← (byte*) print::msg#6 [ screen#18 print::msg#7 ] + [13] (byte*~) screen#21 ← (byte*) screen#18 [ print::msg#7 screen#21 ] + to:print::@1 +print::@1: scope:[print] from print print::@2 + [14] (byte*) screen#12 ← phi( print/(byte*~) screen#21 print::@2/(byte*~) screen#22 ) [ screen#12 print::msg#4 ] + [14] (byte*) print::msg#4 ← phi( print/(byte*~) print::msg#7 print::@2/(byte*~) print::msg#8 ) [ screen#12 print::msg#4 ] + [15] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] + to:print::@return +print::@return: scope:[print] from print::@1 + [16] return [ screen#12 ] + to:@return +print::@2: scope:[print] from print::@1 + [17] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] + [18] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] + [19] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ screen#5 print::msg#3 ] + [20] (byte*~) print::msg#8 ← (byte*) print::msg#3 [ print::msg#8 screen#5 ] + [21] (byte*~) screen#22 ← (byte*) screen#5 [ print::msg#8 screen#22 ] + to:print::@1 + +Created 4 initial phi equivalence classes +Coalesced [6] screen#19 ← screen#12 +Coalesced (already) [8] screen#20 ← screen#12 +Coalesced [12] print::msg#7 ← print::msg#6 +Coalesced (already) [13] screen#21 ← screen#18 +Coalesced [20] print::msg#8 ← print::msg#3 +Coalesced [21] screen#22 ← screen#5 +Coalesced down to 2 phi equivalence classes +Block Sequence Planned @begin @2 @end main main::@1 main::@2 main::@return print print::@1 print::@return print::@2 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of main::@1 +Adding NOP phi() at start of main::@2 +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +CONTROL FLOW GRAPH - BEFORE EFFECTIVE LIVE RANGES +@begin: scope:[] from + [0] phi() [ ] + to:@2 +@2: scope:[] from @begin + [1] phi() [ ] + [2] call main param-assignment [ ] + to:@end +@end: scope:[] from @2 + [3] phi() [ ] +main: scope:[main] from @2 + [4] phi() [ ] + [5] call print param-assignment [ screen#12 ] + to:main::@1 +main::@1: scope:[main] from main + [6] phi() [ screen#12 ] + [7] call print param-assignment [ screen#12 ] + to:main::@2 +main::@2: scope:[main] from main::@1 + [8] phi() [ screen#12 ] + [9] call print param-assignment [ ] + to:main::@return +main::@return: scope:[main] from main::@2 + [10] return [ ] + to:@return +print: scope:[print] from main main::@1 main::@2 + [11] (byte*) screen#18 ← phi( main/((byte*))(word/signed word) 1024 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) [ print::msg#6 screen#18 ] + [11] (byte*) print::msg#6 ← phi( main/(const byte[]) msg1#0 main::@1/(const byte[]) main::msg2#0 main::@2/(const byte[]) main::msg ) [ print::msg#6 screen#18 ] + to:print::@1 +print::@1: scope:[print] from print print::@2 + [12] (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) [ screen#12 print::msg#4 ] + [12] (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) [ screen#12 print::msg#4 ] + [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] + to:print::@return +print::@return: scope:[print] from print::@1 + [14] return [ screen#12 ] + to:@return +print::@2: scope:[print] from print::@1 + [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] + [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] + [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] + to:print::@1 + +CONTROL FLOW GRAPH - PHI MEM COALESCED +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@2 +@2: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @2 + [3] phi() [ ] ( ) +main: scope:[main] from @2 + [4] phi() [ ] ( main:2 [ ] ) + [5] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + to:main::@1 +main::@1: scope:[main] from main + [6] phi() [ screen#12 ] ( main:2 [ screen#12 ] ) + [7] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + to:main::@2 +main::@2: scope:[main] from main::@1 + [8] phi() [ screen#12 ] ( main:2 [ screen#12 ] ) + [9] call print param-assignment [ ] ( main:2 [ ] ) + to:main::@return +main::@return: scope:[main] from main::@2 + [10] return [ ] ( main:2 [ ] ) + to:@return +print: scope:[print] from main main::@1 main::@2 + [11] (byte*) screen#18 ← phi( main/((byte*))(word/signed word) 1024 main::@1/(byte*) screen#12 main::@2/(byte*) screen#12 ) [ print::msg#6 screen#18 ] ( main:2::print:5 [ print::msg#6 screen#18 ] main:2::print:7 [ print::msg#6 screen#18 ] main:2::print:9 [ print::msg#6 screen#18 ] ) + [11] (byte*) print::msg#6 ← phi( main/(const byte[]) msg1#0 main::@1/(const byte[]) main::msg2#0 main::@2/(const byte[]) main::msg ) [ print::msg#6 screen#18 ] ( main:2::print:5 [ print::msg#6 screen#18 ] main:2::print:7 [ print::msg#6 screen#18 ] main:2::print:9 [ print::msg#6 screen#18 ] ) + to:print::@1 +print::@1: scope:[print] from print print::@2 + [12] (byte*) screen#12 ← phi( print/(byte*) screen#18 print::@2/(byte*) screen#5 ) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) + [12] (byte*) print::msg#4 ← phi( print/(byte*) print::msg#6 print::@2/(byte*) print::msg#3 ) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) + [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) + to:print::@return +print::@return: scope:[print] from print::@1 + [14] return [ screen#12 ] ( main:2::print:5 [ screen#12 ] main:2::print:7 [ screen#12 ] main:2::print:9 [ screen#12 ] ) + to:@return +print::@2: scope:[print] from print::@1 + [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) + [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] ( main:2::print:5 [ print::msg#4 screen#5 ] main:2::print:7 [ print::msg#4 screen#5 ] main:2::print:9 [ print::msg#4 screen#5 ] ) + [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] ( main:2::print:5 [ print::msg#3 screen#5 ] main:2::print:7 [ print::msg#3 screen#5 ] main:2::print:9 [ print::msg#3 screen#5 ] ) + to:print::@1 + +DOMINATORS +@begin dominated by @begin +@2 dominated by @2 @begin +@end dominated by @2 @begin @end +main dominated by @2 @begin main +main::@1 dominated by @2 @begin main::@1 main +main::@2 dominated by @2 @begin main::@1 main::@2 main +main::@return dominated by main::@return @2 @begin main::@1 main::@2 main +print dominated by @2 print @begin main +print::@1 dominated by @2 print @begin print::@1 main +print::@return dominated by @2 print @begin print::@1 main print::@return +print::@2 dominated by @2 print @begin print::@2 print::@1 main + +Found back edge: Loop head: print::@1 tails: print::@2 blocks: null +Populated: Loop head: print::@1 tails: print::@2 blocks: print::@2 print::@1 +NATURAL LOOPS +Loop head: print::@1 tails: print::@2 blocks: print::@2 print::@1 + +Found 0 loops in scope [] +Found 0 loops in scope [main] +Found 1 loops in scope [print] + Loop head: print::@1 tails: print::@2 blocks: print::@2 print::@1 +NATURAL LOOPS WITH DEPTH +Loop head: print::@1 tails: print::@2 blocks: print::@2 print::@1 depth: 1 + + +VARIABLE REGISTER WEIGHTS +(void()) main() +(byte[]) main::msg2 +(byte[]) msg1 +(void()) print((byte*) print::msg) +(byte*) print::msg +(byte*) print::msg#3 22.0 +(byte*) print::msg#4 11.5 +(byte*) print::msg#6 2.0 +(byte*) screen +(byte*) screen#12 4.875 +(byte*) screen#18 6.0 +(byte*) screen#5 11.0 + +Initial phi equivalence classes +[ screen#18 screen#12 screen#5 ] +[ print::msg#4 print::msg#6 print::msg#3 ] +Complete equivalence classes +[ screen#18 screen#12 screen#5 ] +[ print::msg#4 print::msg#6 print::msg#3 ] +Allocated zp ZP_PTR_BYTE:2 [ screen#18 screen#12 screen#5 ] +Allocated zp ZP_PTR_BYTE:4 [ print::msg#4 print::msg#6 print::msg#3 ] +INITIAL ASM +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .label screen = 2 + msg1: .text "message 1 @" +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +b2_from_bbegin: + jmp b2 +//SEG4 @2 +b2: +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] +main_from_b2: + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +bend_from_b2: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + //SEG10 [5] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG11 [11] phi from main to print [phi:main->print] + print_from_main: + //SEG12 [11] phi (byte*) screen#18 = ((byte*))(word/signed word) 1024 [phi:main->print#0] -- zpptrby1=cowo1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [11] phi (byte*) print::msg#6 = (const byte[]) msg1#0 [phi:main->print#1] -- zpptrby1=cowo1 + lda #msg1 + sta print.msg+1 + jsr print + //SEG14 [6] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + jmp b1 + //SEG15 main::@1 + b1: + //SEG16 [7] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG17 [11] phi from main::@1 to print [phi:main::@1->print] + print_from_b1: + //SEG18 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@1->print#0] -- register_copy + //SEG19 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg2#0 [phi:main::@1->print#1] -- zpptrby1=cowo1 + lda #msg2 + sta print.msg+1 + jsr print + //SEG20 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG21 main::@2 + b2: + //SEG22 [9] call print param-assignment [ ] ( main:2 [ ] ) + //SEG23 [11] phi from main::@2 to print [phi:main::@2->print] + print_from_b2: + //SEG24 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@2->print#0] -- register_copy + //SEG25 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg [phi:main::@2->print#1] -- zpptrby1=cowo1 + lda #msg + sta print.msg+1 + jsr print + jmp breturn + //SEG26 main::@return + breturn: + //SEG27 [10] return [ ] ( main:2 [ ] ) + rts + msg: .text "message 3 @" + msg2: .text "message 2 @" +} +//SEG28 print +print: { + .label msg = 4 + //SEG29 [12] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] + b1_from_print: + b1_from_b2: + //SEG30 [12] phi (byte*) screen#12 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy + //SEG31 [12] phi (byte*) print::msg#4 = (byte*) print::msg#6 [phi:print/print::@2->print::@1#1] -- register_copy + jmp b1 + //SEG32 print::@1 + b1: + //SEG33 [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1_neq_coby1_then_la1 + ldy #0 + lda (msg),y + cmp #'@' + bne b2 + jmp breturn + //SEG34 print::@return + breturn: + //SEG35 [14] return [ screen#12 ] ( main:2::print:5 [ screen#12 ] main:2::print:7 [ screen#12 ] main:2::print:9 [ screen#12 ] ) + rts + //SEG36 print::@2 + b2: + //SEG37 [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1=_deref_zpptrby2 + ldy #0 + lda (msg),y + ldy #0 + sta (screen),y + //SEG38 [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] ( main:2::print:5 [ print::msg#4 screen#5 ] main:2::print:7 [ print::msg#4 screen#5 ] main:2::print:9 [ print::msg#4 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc screen + bne !+ + inc screen+1 + !: + //SEG39 [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] ( main:2::print:5 [ print::msg#3 screen#5 ] main:2::print:7 [ print::msg#3 screen#5 ] main:2::print:9 [ print::msg#3 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc msg + bne !+ + inc msg+1 + !: + jmp b1_from_b2 +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) always clobbers reg byte a reg byte y +Statement [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) always clobbers reg byte a reg byte y +Potential registers zp ZP_PTR_BYTE:2 [ screen#18 screen#12 screen#5 ] : zp ZP_PTR_BYTE:2 , +Potential registers zp ZP_PTR_BYTE:4 [ print::msg#4 print::msg#6 print::msg#3 ] : zp ZP_PTR_BYTE:4 , + +REGISTER UPLIFT SCOPES +Uplift Scope [print] 35.5: zp ZP_PTR_BYTE:4 [ print::msg#4 print::msg#6 print::msg#3 ] +Uplift Scope [] 21.88: zp ZP_PTR_BYTE:2 [ screen#18 screen#12 screen#5 ] +Uplift Scope [main] + +Uplifting [print] best 730 combination zp ZP_PTR_BYTE:4 [ print::msg#4 print::msg#6 print::msg#3 ] +Uplifting [] best 730 combination zp ZP_PTR_BYTE:2 [ screen#18 screen#12 screen#5 ] +Uplifting [main] best 730 combination +Removing instruction jmp b2 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp breturn +Removing instruction jmp b1 +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .label screen = 2 + msg1: .text "message 1 @" +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +b2_from_bbegin: +//SEG4 @2 +b2: +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] +main_from_b2: + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +bend_from_b2: +//SEG8 @end +bend: +//SEG9 main +main: { + //SEG10 [5] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG11 [11] phi from main to print [phi:main->print] + print_from_main: + //SEG12 [11] phi (byte*) screen#18 = ((byte*))(word/signed word) 1024 [phi:main->print#0] -- zpptrby1=cowo1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [11] phi (byte*) print::msg#6 = (const byte[]) msg1#0 [phi:main->print#1] -- zpptrby1=cowo1 + lda #msg1 + sta print.msg+1 + jsr print + //SEG14 [6] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG15 main::@1 + b1: + //SEG16 [7] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG17 [11] phi from main::@1 to print [phi:main::@1->print] + print_from_b1: + //SEG18 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@1->print#0] -- register_copy + //SEG19 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg2#0 [phi:main::@1->print#1] -- zpptrby1=cowo1 + lda #msg2 + sta print.msg+1 + jsr print + //SEG20 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + //SEG21 main::@2 + b2: + //SEG22 [9] call print param-assignment [ ] ( main:2 [ ] ) + //SEG23 [11] phi from main::@2 to print [phi:main::@2->print] + print_from_b2: + //SEG24 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@2->print#0] -- register_copy + //SEG25 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg [phi:main::@2->print#1] -- zpptrby1=cowo1 + lda #msg + sta print.msg+1 + jsr print + //SEG26 main::@return + breturn: + //SEG27 [10] return [ ] ( main:2 [ ] ) + rts + msg: .text "message 3 @" + msg2: .text "message 2 @" +} +//SEG28 print +print: { + .label msg = 4 + //SEG29 [12] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] + b1_from_print: + b1_from_b2: + //SEG30 [12] phi (byte*) screen#12 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy + //SEG31 [12] phi (byte*) print::msg#4 = (byte*) print::msg#6 [phi:print/print::@2->print::@1#1] -- register_copy + //SEG32 print::@1 + b1: + //SEG33 [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1_neq_coby1_then_la1 + ldy #0 + lda (msg),y + cmp #'@' + bne b2 + //SEG34 print::@return + breturn: + //SEG35 [14] return [ screen#12 ] ( main:2::print:5 [ screen#12 ] main:2::print:7 [ screen#12 ] main:2::print:9 [ screen#12 ] ) + rts + //SEG36 print::@2 + b2: + //SEG37 [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1=_deref_zpptrby2 + ldy #0 + lda (msg),y + ldy #0 + sta (screen),y + //SEG38 [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] ( main:2::print:5 [ print::msg#4 screen#5 ] main:2::print:7 [ print::msg#4 screen#5 ] main:2::print:9 [ print::msg#4 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc screen + bne !+ + inc screen+1 + !: + //SEG39 [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] ( main:2::print:5 [ print::msg#3 screen#5 ] main:2::print:7 [ print::msg#3 screen#5 ] main:2::print:9 [ print::msg#3 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc msg + bne !+ + inc msg+1 + !: + jmp b1_from_b2 +} + +Removing instruction ldy #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .label screen = 2 + msg1: .text "message 1 @" +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +b2_from_bbegin: +//SEG4 @2 +b2: +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] +main_from_b2: + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +bend_from_b2: +//SEG8 @end +bend: +//SEG9 main +main: { + //SEG10 [5] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG11 [11] phi from main to print [phi:main->print] + print_from_main: + //SEG12 [11] phi (byte*) screen#18 = ((byte*))(word/signed word) 1024 [phi:main->print#0] -- zpptrby1=cowo1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [11] phi (byte*) print::msg#6 = (const byte[]) msg1#0 [phi:main->print#1] -- zpptrby1=cowo1 + lda #msg1 + sta print.msg+1 + jsr print + //SEG14 [6] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG15 main::@1 + b1: + //SEG16 [7] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG17 [11] phi from main::@1 to print [phi:main::@1->print] + print_from_b1: + //SEG18 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@1->print#0] -- register_copy + //SEG19 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg2#0 [phi:main::@1->print#1] -- zpptrby1=cowo1 + lda #msg2 + sta print.msg+1 + jsr print + //SEG20 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + //SEG21 main::@2 + b2: + //SEG22 [9] call print param-assignment [ ] ( main:2 [ ] ) + //SEG23 [11] phi from main::@2 to print [phi:main::@2->print] + print_from_b2: + //SEG24 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@2->print#0] -- register_copy + //SEG25 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg [phi:main::@2->print#1] -- zpptrby1=cowo1 + lda #msg + sta print.msg+1 + jsr print + //SEG26 main::@return + breturn: + //SEG27 [10] return [ ] ( main:2 [ ] ) + rts + msg: .text "message 3 @" + msg2: .text "message 2 @" +} +//SEG28 print +print: { + .label msg = 4 + //SEG29 [12] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] + b1_from_print: + b1_from_b2: + //SEG30 [12] phi (byte*) screen#12 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy + //SEG31 [12] phi (byte*) print::msg#4 = (byte*) print::msg#6 [phi:print/print::@2->print::@1#1] -- register_copy + //SEG32 print::@1 + b1: + //SEG33 [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1_neq_coby1_then_la1 + ldy #0 + lda (msg),y + cmp #'@' + bne b2 + //SEG34 print::@return + breturn: + //SEG35 [14] return [ screen#12 ] ( main:2::print:5 [ screen#12 ] main:2::print:7 [ screen#12 ] main:2::print:9 [ screen#12 ] ) + rts + //SEG36 print::@2 + b2: + //SEG37 [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1=_deref_zpptrby2 + ldy #0 + lda (msg),y + sta (screen),y + //SEG38 [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] ( main:2::print:5 [ print::msg#4 screen#5 ] main:2::print:7 [ print::msg#4 screen#5 ] main:2::print:9 [ print::msg#4 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc screen + bne !+ + inc screen+1 + !: + //SEG39 [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] ( main:2::print:5 [ print::msg#3 screen#5 ] main:2::print:7 [ print::msg#3 screen#5 ] main:2::print:9 [ print::msg#3 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc msg + bne !+ + inc msg+1 + !: + jmp b1_from_b2 +} + +Replacing label b1_from_b2 with b1 +Removing instruction bbegin: +Removing instruction b2_from_bbegin: +Removing instruction main_from_b2: +Removing instruction bend_from_b2: +Removing instruction b1_from_main: +Removing instruction print_from_b1: +Removing instruction b2_from_b1: +Removing instruction print_from_b2: +Removing instruction b1_from_print: +Removing instruction b1_from_b2: +Succesful ASM optimization Pass5RedundantLabelElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .label screen = 2 + msg1: .text "message 1 @" +//SEG2 @begin +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +//SEG4 @2 +b2: +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +//SEG8 @end +bend: +//SEG9 main +main: { + //SEG10 [5] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG11 [11] phi from main to print [phi:main->print] + print_from_main: + //SEG12 [11] phi (byte*) screen#18 = ((byte*))(word/signed word) 1024 [phi:main->print#0] -- zpptrby1=cowo1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [11] phi (byte*) print::msg#6 = (const byte[]) msg1#0 [phi:main->print#1] -- zpptrby1=cowo1 + lda #msg1 + sta print.msg+1 + jsr print + //SEG14 [6] phi from main to main::@1 [phi:main->main::@1] + //SEG15 main::@1 + b1: + //SEG16 [7] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG17 [11] phi from main::@1 to print [phi:main::@1->print] + //SEG18 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@1->print#0] -- register_copy + //SEG19 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg2#0 [phi:main::@1->print#1] -- zpptrby1=cowo1 + lda #msg2 + sta print.msg+1 + jsr print + //SEG20 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + //SEG21 main::@2 + b2: + //SEG22 [9] call print param-assignment [ ] ( main:2 [ ] ) + //SEG23 [11] phi from main::@2 to print [phi:main::@2->print] + //SEG24 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@2->print#0] -- register_copy + //SEG25 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg [phi:main::@2->print#1] -- zpptrby1=cowo1 + lda #msg + sta print.msg+1 + jsr print + //SEG26 main::@return + breturn: + //SEG27 [10] return [ ] ( main:2 [ ] ) + rts + msg: .text "message 3 @" + msg2: .text "message 2 @" +} +//SEG28 print +print: { + .label msg = 4 + //SEG29 [12] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] + //SEG30 [12] phi (byte*) screen#12 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy + //SEG31 [12] phi (byte*) print::msg#4 = (byte*) print::msg#6 [phi:print/print::@2->print::@1#1] -- register_copy + //SEG32 print::@1 + b1: + //SEG33 [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1_neq_coby1_then_la1 + ldy #0 + lda (msg),y + cmp #'@' + bne b2 + //SEG34 print::@return + breturn: + //SEG35 [14] return [ screen#12 ] ( main:2::print:5 [ screen#12 ] main:2::print:7 [ screen#12 ] main:2::print:9 [ screen#12 ] ) + rts + //SEG36 print::@2 + b2: + //SEG37 [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1=_deref_zpptrby2 + ldy #0 + lda (msg),y + sta (screen),y + //SEG38 [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] ( main:2::print:5 [ print::msg#4 screen#5 ] main:2::print:7 [ print::msg#4 screen#5 ] main:2::print:9 [ print::msg#4 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc screen + bne !+ + inc screen+1 + !: + //SEG39 [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] ( main:2::print:5 [ print::msg#3 screen#5 ] main:2::print:7 [ print::msg#3 screen#5 ] main:2::print:9 [ print::msg#3 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc msg + bne !+ + inc msg+1 + !: + jmp b1 +} + +Removing instruction b2: +Removing instruction bend: +Removing instruction print_from_main: +Removing instruction b1: +Removing instruction b2: +Removing instruction breturn: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +ASSEMBLER +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .label screen = 2 + msg1: .text "message 1 @" +//SEG2 @begin +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +//SEG4 @2 +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +//SEG8 @end +//SEG9 main +main: { + //SEG10 [5] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG11 [11] phi from main to print [phi:main->print] + //SEG12 [11] phi (byte*) screen#18 = ((byte*))(word/signed word) 1024 [phi:main->print#0] -- zpptrby1=cowo1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [11] phi (byte*) print::msg#6 = (const byte[]) msg1#0 [phi:main->print#1] -- zpptrby1=cowo1 + lda #msg1 + sta print.msg+1 + jsr print + //SEG14 [6] phi from main to main::@1 [phi:main->main::@1] + //SEG15 main::@1 + //SEG16 [7] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG17 [11] phi from main::@1 to print [phi:main::@1->print] + //SEG18 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@1->print#0] -- register_copy + //SEG19 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg2#0 [phi:main::@1->print#1] -- zpptrby1=cowo1 + lda #msg2 + sta print.msg+1 + jsr print + //SEG20 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + //SEG21 main::@2 + //SEG22 [9] call print param-assignment [ ] ( main:2 [ ] ) + //SEG23 [11] phi from main::@2 to print [phi:main::@2->print] + //SEG24 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@2->print#0] -- register_copy + //SEG25 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg [phi:main::@2->print#1] -- zpptrby1=cowo1 + lda #msg + sta print.msg+1 + jsr print + //SEG26 main::@return + //SEG27 [10] return [ ] ( main:2 [ ] ) + rts + msg: .text "message 3 @" + msg2: .text "message 2 @" +} +//SEG28 print +print: { + .label msg = 4 + //SEG29 [12] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] + //SEG30 [12] phi (byte*) screen#12 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy + //SEG31 [12] phi (byte*) print::msg#4 = (byte*) print::msg#6 [phi:print/print::@2->print::@1#1] -- register_copy + //SEG32 print::@1 + b1: + //SEG33 [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1_neq_coby1_then_la1 + ldy #0 + lda (msg),y + cmp #'@' + bne b2 + //SEG34 print::@return + //SEG35 [14] return [ screen#12 ] ( main:2::print:5 [ screen#12 ] main:2::print:7 [ screen#12 ] main:2::print:9 [ screen#12 ] ) + rts + //SEG36 print::@2 + b2: + //SEG37 [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1=_deref_zpptrby2 + ldy #0 + lda (msg),y + sta (screen),y + //SEG38 [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] ( main:2::print:5 [ print::msg#4 screen#5 ] main:2::print:7 [ print::msg#4 screen#5 ] main:2::print:9 [ print::msg#4 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc screen + bne !+ + inc screen+1 + !: + //SEG39 [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] ( main:2::print:5 [ print::msg#3 screen#5 ] main:2::print:7 [ print::msg#3 screen#5 ] main:2::print:9 [ print::msg#3 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc msg + bne !+ + inc msg+1 + !: + jmp b1 +} + +FINAL SYMBOL TABLE +(label) @2 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(const byte[]) main::msg msg = (string) "message 3 @" +(byte[]) main::msg2 +(const byte[]) main::msg2#0 msg2 = (string) "message 2 @" +(byte[]) msg1 +(const byte[]) msg1#0 msg1 = (string) "message 1 @" +(void()) print((byte*) print::msg) +(label) print::@1 +(label) print::@2 +(label) print::@return +(byte*) print::msg +(byte*) print::msg#3 msg zp ZP_PTR_BYTE:4 22.0 +(byte*) print::msg#4 msg zp ZP_PTR_BYTE:4 11.5 +(byte*) print::msg#6 msg zp ZP_PTR_BYTE:4 2.0 +(byte*) screen +(byte*) screen#12 screen zp ZP_PTR_BYTE:2 4.875 +(byte*) screen#18 screen zp ZP_PTR_BYTE:2 6.0 +(byte*) screen#5 screen zp ZP_PTR_BYTE:2 11.0 + +zp ZP_PTR_BYTE:2 [ screen#18 screen#12 screen#5 ] +zp ZP_PTR_BYTE:4 [ print::msg#4 print::msg#6 print::msg#3 ] + +FINAL CODE +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels + .label screen = 2 + msg1: .text "message 1 @" +//SEG2 @begin +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +//SEG4 @2 +//SEG5 [2] call main param-assignment [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +//SEG8 @end +//SEG9 main +main: { + //SEG10 [5] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG11 [11] phi from main to print [phi:main->print] + //SEG12 [11] phi (byte*) screen#18 = ((byte*))(word/signed word) 1024 [phi:main->print#0] -- zpptrby1=cowo1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [11] phi (byte*) print::msg#6 = (const byte[]) msg1#0 [phi:main->print#1] -- zpptrby1=cowo1 + lda #msg1 + sta print.msg+1 + jsr print + //SEG14 [6] phi from main to main::@1 [phi:main->main::@1] + //SEG15 main::@1 + //SEG16 [7] call print param-assignment [ screen#12 ] ( main:2 [ screen#12 ] ) + //SEG17 [11] phi from main::@1 to print [phi:main::@1->print] + //SEG18 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@1->print#0] -- register_copy + //SEG19 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg2#0 [phi:main::@1->print#1] -- zpptrby1=cowo1 + lda #msg2 + sta print.msg+1 + jsr print + //SEG20 [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + //SEG21 main::@2 + //SEG22 [9] call print param-assignment [ ] ( main:2 [ ] ) + //SEG23 [11] phi from main::@2 to print [phi:main::@2->print] + //SEG24 [11] phi (byte*) screen#18 = (byte*) screen#12 [phi:main::@2->print#0] -- register_copy + //SEG25 [11] phi (byte*) print::msg#6 = (const byte[]) main::msg [phi:main::@2->print#1] -- zpptrby1=cowo1 + lda #msg + sta print.msg+1 + jsr print + //SEG26 main::@return + //SEG27 [10] return [ ] ( main:2 [ ] ) + rts + msg: .text "message 3 @" + msg2: .text "message 2 @" +} +//SEG28 print +print: { + .label msg = 4 + //SEG29 [12] phi from print print::@2 to print::@1 [phi:print/print::@2->print::@1] + //SEG30 [12] phi (byte*) screen#12 = (byte*) screen#18 [phi:print/print::@2->print::@1#0] -- register_copy + //SEG31 [12] phi (byte*) print::msg#4 = (byte*) print::msg#6 [phi:print/print::@2->print::@1#1] -- register_copy + //SEG32 print::@1 + b1: + //SEG33 [13] if(*((byte*) print::msg#4)!=(byte) '@') goto print::@2 [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1_neq_coby1_then_la1 + ldy #0 + lda (msg),y + cmp #'@' + bne b2 + //SEG34 print::@return + //SEG35 [14] return [ screen#12 ] ( main:2::print:5 [ screen#12 ] main:2::print:7 [ screen#12 ] main:2::print:9 [ screen#12 ] ) + rts + //SEG36 print::@2 + b2: + //SEG37 [15] *((byte*) screen#12) ← *((byte*) print::msg#4) [ screen#12 print::msg#4 ] ( main:2::print:5 [ screen#12 print::msg#4 ] main:2::print:7 [ screen#12 print::msg#4 ] main:2::print:9 [ screen#12 print::msg#4 ] ) -- _deref_zpptrby1=_deref_zpptrby2 + ldy #0 + lda (msg),y + sta (screen),y + //SEG38 [16] (byte*) screen#5 ← ++ (byte*) screen#12 [ print::msg#4 screen#5 ] ( main:2::print:5 [ print::msg#4 screen#5 ] main:2::print:7 [ print::msg#4 screen#5 ] main:2::print:9 [ print::msg#4 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc screen + bne !+ + inc screen+1 + !: + //SEG39 [17] (byte*) print::msg#3 ← ++ (byte*) print::msg#4 [ print::msg#3 screen#5 ] ( main:2::print:5 [ print::msg#3 screen#5 ] main:2::print:7 [ print::msg#3 screen#5 ] main:2::print:9 [ print::msg#3 screen#5 ] ) -- zpptrby1=_inc_zpptrby1 + inc msg + bne !+ + inc msg+1 + !: + jmp b1 +} + diff --git a/src/main/java/dk/camelot64/kickc/test/ref/inline-string.sym b/src/main/java/dk/camelot64/kickc/test/ref/inline-string.sym new file mode 100644 index 000000000..835fd7d54 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/test/ref/inline-string.sym @@ -0,0 +1,27 @@ +(label) @2 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@return +(const byte[]) main::msg msg = (string) "message 3 @" +(byte[]) main::msg2 +(const byte[]) main::msg2#0 msg2 = (string) "message 2 @" +(byte[]) msg1 +(const byte[]) msg1#0 msg1 = (string) "message 1 @" +(void()) print((byte*) print::msg) +(label) print::@1 +(label) print::@2 +(label) print::@return +(byte*) print::msg +(byte*) print::msg#3 msg zp ZP_PTR_BYTE:4 22.0 +(byte*) print::msg#4 msg zp ZP_PTR_BYTE:4 11.5 +(byte*) print::msg#6 msg zp ZP_PTR_BYTE:4 2.0 +(byte*) screen +(byte*) screen#12 screen zp ZP_PTR_BYTE:2 4.875 +(byte*) screen#18 screen zp ZP_PTR_BYTE:2 6.0 +(byte*) screen#5 screen zp ZP_PTR_BYTE:2 11.0 + +zp ZP_PTR_BYTE:2 [ screen#18 screen#12 screen#5 ] +zp ZP_PTR_BYTE:4 [ print::msg#4 print::msg#6 print::msg#3 ]