diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1PrintfIntrinsicRewrite.java b/src/main/java/dk/camelot64/kickc/passes/Pass1PrintfIntrinsicRewrite.java index 5ae90cdf4..44445f841 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1PrintfIntrinsicRewrite.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1PrintfIntrinsicRewrite.java @@ -22,6 +22,12 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization { /** The printf procedure name. */ public static final String INTRINSIC_PRINTF_NAME = "printf"; + /** The printf routine used to print formatted strings. */ + public static final String PRINTF_STRING = "printf_string"; + /** The printf routine used to print signed integers. */ + public static final String PRINTF_SINT = "printf_sint"; + /** The printf routine used to print unsigned integers. */ + public static final String PRINTF_UINT = "printf_uint"; public Pass1PrintfIntrinsicRewrite(Program program) { super(program); @@ -48,7 +54,7 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization { // Remove the call to printf() stmtIt.remove(); - // Printf Placeholder Format String + // Printf Placeholder Format String - source: https://en.wikipedia.org/wiki/Printf_format_string // "%" start // ([1-9][0-9]* "$")? parameter (gives the # of the parameter to use) // [-+ 0'#]* flags (different flags affecting the formatting "-": left-align, "0": zero-prepend, "+": always sign) @@ -68,31 +74,78 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization { } final int start = matcher.start(); final int end = matcher.end(); - final String param = matcher.group(1); - final String flags = matcher.group(2); - final String width = matcher.group(3); - final String length = matcher.group(4); - final String type = matcher.group(5); - if(param!=null) + final String paramField = matcher.group(1); + if(paramField != null) throw new CompileError("printf parameter field not supported", printfCall); - // First grab the non-matching part + final String flagsField = matcher.group(2); + long leftJustify = (flagsField != null && flagsField.contains("-")) ? 1 : 0; + long signAlways = (flagsField != null && flagsField.contains("+")) ? 1 : 0; + long zeroPadding = (flagsField != null && flagsField.contains("0")) ? 1 : 0; + + final String widthField = matcher.group(3); + long width = (widthField == null) ? 0 : Integer.parseInt(widthField); + + final String lengthField = matcher.group(4); + + final String typeField = matcher.group(5); + + // First output the non-matching part before the pattern String prefix = formatString.substring(formatIdx, start); printfConstantString(prefix, printfCall, stmtIt, formatEncoding); - formatIdx = end; - if(type.equals("s")) { - // A string - long w = (width==null)?0:Integer.parseInt(width); - long leftJustify = (flags!=null && flags.contains("-"))?1:0; - final ValueList format_string_struct = new ValueList(Arrays.asList(new ConstantInteger(w, SymbolType.BYTE), new ConstantInteger(leftJustify, SymbolType.BYTE))); - final StatementCall call_printf_str = new StatementCall(null, "printf_string", Arrays.asList(parameters.get(paramIdx), format_string_struct), printfCall.getSource(), Comment.NO_COMMENTS); + + + if(typeField.equals("s")) { + // A formatted string + //struct printf_format_string { + // char min_length; // The minimal number of chars to output (used for padding with spaces or 0). + // char justify_left; // Justify left instead of right, which is the default. + //}; + final ValueList format_string_struct = + new ValueList(Arrays.asList( + new ConstantInteger(width, SymbolType.BYTE), + new ConstantInteger(leftJustify, SymbolType.BYTE) + )); + final StatementCall call_printf_str = new StatementCall(null, PRINTF_STRING, Arrays.asList(parameters.get(paramIdx), format_string_struct), printfCall.getSource(), Comment.NO_COMMENTS); + call_printf_str.setProcedure(getScope().getLocalProcedure(call_printf_str.getProcedureName()).getRef()); + stmtIt.add(call_printf_str); + paramIdx++; + } else if("diuxXo".contains(typeField)) { + // A formatted integer + SymbolVariableRef radix; + String printf_number_procedure; + if(typeField.equals("d")) { + radix = getScope().getLocalConstant("DECIMAL").getRef(); + printf_number_procedure = PRINTF_SINT; + } else if(typeField.equals("x")) { + radix = getScope().getLocalConstant("HEXADECIMAL").getRef(); + printf_number_procedure = PRINTF_UINT; + } else { + throw new CompileError("printf type field not supported", printfCall); + } + + // Format specifying how to format a printed number + // struct printf_format_number { + // char min_length; // The minimal number of chars to output (used for padding with spaces or 0) + // char justify_left; // Justify left instead of right, which is the default. + // char sign_always; // Always show a sign for a number, even if is is positive. (Default is to only show sign for negative numbers) + // char zero_padding; // Pad the number with zeros to get the min width + // enum RADIX radix; // The number radix to use for formatting + // }; + final ValueList format_number_struct = + new ValueList(Arrays.asList( + new ConstantInteger(width, SymbolType.BYTE), + new ConstantInteger(leftJustify, SymbolType.BYTE), + new ConstantInteger(signAlways, SymbolType.BYTE), + new ConstantInteger(zeroPadding, SymbolType.BYTE), + radix + )); + final StatementCall call_printf_str = new StatementCall(null, printf_number_procedure, Arrays.asList(parameters.get(paramIdx), format_number_struct), printfCall.getSource(), Comment.NO_COMMENTS); call_printf_str.setProcedure(getScope().getLocalProcedure(call_printf_str.getProcedureName()).getRef()); stmtIt.add(call_printf_str); paramIdx++; - } else if(type.equals("d")) { - System.out.println("decimal"); } } // Grab the rest @@ -106,6 +159,7 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization { /** * Add a printf_str() that prints a constant string. + * * @param prefix The string to print * @param printfCall The original printf call * @param stmtIt The statement iterator to add to diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index be7589867..16825a862 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -42,7 +42,7 @@ public class TestPrograms { @Test public void testPintf10() throws IOException, URISyntaxException { - compileAndCompare("printf-10.c", log()); + compileAndCompare("printf-10.c"); } @Test diff --git a/src/test/kc/printf-10.c b/src/test/kc/printf-10.c index 84e71b21e..17ba49714 100644 --- a/src/test/kc/printf-10.c +++ b/src/test/kc/printf-10.c @@ -26,8 +26,37 @@ void printf_string(char* str, struct printf_format_string format) { printf_str(str); } -void main() { - char name[] = "Jesper"; - printf("Hello, I am %s. who are you?", name); +// The different supported radix +enum RADIX { BINARY=2, OCTAL=8, DECIMAL=10, HEXADECIMAL=16 }; + +// Format specifying how to format a printed number +struct printf_format_number { + // The minimal number of chars to output (used for padding with spaces or 0) + char min_length; + // Justify left instead of right, which is the default. + char justify_left; + // Always show a sign for a number, even if is is positive. (Default is to only show sign for negative numbers) + char sign_always; + // Pad the number with zeros to get the min width + char zero_padding; + // The number radix to use for formatting + enum RADIX radix; +}; + +const char printf_hextab[] = "0123456789abcdef"z; + +// Print an unsigned int using a specific format +// Always prints hexadecimals - ignores min_length and flags +void printf_uint(unsigned int uvalue, struct printf_format_number format) { + *screen++ = printf_hextab[(>uvalue)>>4]; + *screen++ = printf_hextab[(>uvalue)&0xf]; + *screen++ = printf_hextab[(>4]; + *screen++ = printf_hextab[($400 @@ -15,21 +16,39 @@ main: { lda #>str sta.z printf_str.str+1 jsr printf_str - // printf("Hello, I am %s. who are you?", name) + // printf("Hello, I am %s. who are you?", "Jesper") jsr printf_string - // printf("Hello, I am %s. who are you?", name) - lda #str1 + lda #>str2 + sta.z printf_str.str+1 + jsr printf_str + // printf("I am %x years old", age) + lda #str3 + sta.z printf_str.str+1 + jsr printf_str + // printf("I am %x years old", age) + jsr printf_uint + // printf("I am %x years old", age) + lda #str4 sta.z printf_str.str+1 jsr printf_str // } rts - name: .text "Jesper" - .byte 0 str: .text "Hello, I am " .byte 0 - str1: .text ". who are you?" + str1: .text "Jesper" + .byte 0 + str2: .text ". who are you?" + .byte 0 + str3: .text "I am " + .byte 0 + str4: .text " years old" .byte 0 } // printf_str(byte* zp(4) str) @@ -59,15 +78,58 @@ printf_str: { !: jmp __b1 } +// Print an unsigned int using a specific format +// Always prints hexadecimals - ignores min_length and flags +printf_uint: { + // *screen++ = printf_hextab[(>uvalue)>>4] + lda printf_hextab + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>uvalue)>>4]; + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(>uvalue)&0xf] + lda printf_hextab + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>uvalue)&0xf]; + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(>4] + lda printf_hextab+((>4) + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>4]; + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(main.name + lda #>main.str1 sta.z printf_str.str+1 jsr printf_str // } rts } + printf_hextab: .text "0123456789abcdef" diff --git a/src/test/ref/printf-10.cfg b/src/test/ref/printf-10.cfg index 97a96504c..5eb99f837 100644 --- a/src/test/ref/printf-10.cfg +++ b/src/test/ref/printf-10.cfg @@ -20,35 +20,62 @@ main::@1: scope:[main] from main main::@2: scope:[main] from main::@1 [8] phi() [9] call printf_str + to:main::@3 +main::@3: scope:[main] from main::@2 + [10] phi() + [11] call printf_str + to:main::@4 +main::@4: scope:[main] from main::@3 + [12] phi() + [13] call printf_uint + to:main::@5 +main::@5: scope:[main] from main::@4 + [14] phi() + [15] call printf_str to:main::@return -main::@return: scope:[main] from main::@2 - [10] return +main::@return: scope:[main] from main::@5 + [16] return to:@return (void()) printf_str((byte*) printf_str::str) -printf_str: scope:[printf_str] from main main::@2 printf_string - [11] (byte*) screen#23 ← phi( main/(byte*) 1024 main::@2/(byte*) screen#10 printf_string/(byte*) screen#10 ) - [11] (byte*) printf_str::str#6 ← phi( main/(const byte*) main::str main::@2/(const byte*) main::str1 printf_string/(const byte*) main::name ) +printf_str: scope:[printf_str] from main main::@2 main::@3 main::@5 printf_string + [17] (byte*) screen#36 ← phi( main/(byte*) 1024 main::@2/(byte*) screen#18 main::@3/(byte*) screen#18 main::@5/(byte*) screen#23 printf_string/(byte*) screen#18 ) + [17] (byte*) printf_str::str#8 ← phi( main/(const byte*) main::str main::@2/(const byte*) main::str2 main::@3/(const byte*) main::str3 main::@5/(const byte*) main::str4 printf_string/(const byte*) main::str1 ) to:printf_str::@1 printf_str::@1: scope:[printf_str] from printf_str printf_str::@2 - [12] (byte*) screen#10 ← phi( printf_str/(byte*) screen#23 printf_str::@2/(byte*) screen#1 ) - [12] (byte*) printf_str::str#4 ← phi( printf_str/(byte*) printf_str::str#6 printf_str::@2/(byte*) printf_str::str#0 ) - [13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 + [18] (byte*) screen#18 ← phi( printf_str/(byte*) screen#36 printf_str::@2/(byte*) screen#1 ) + [18] (byte*) printf_str::str#6 ← phi( printf_str/(byte*) printf_str::str#8 printf_str::@2/(byte*) printf_str::str#0 ) + [19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 to:printf_str::@return printf_str::@return: scope:[printf_str] from printf_str::@1 - [14] return + [20] return to:@return printf_str::@2: scope:[printf_str] from printf_str::@1 - [15] *((byte*) screen#10) ← *((byte*) printf_str::str#4) - [16] (byte*) screen#1 ← ++ (byte*) screen#10 - [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4 + [21] *((byte*) screen#18) ← *((byte*) printf_str::str#6) + [22] (byte*) screen#1 ← ++ (byte*) screen#18 + [23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6 to:printf_str::@1 +(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix) +printf_uint: scope:[printf_uint] from main::@4 + [24] *((byte*) screen#18) ← *((const to_nomodify byte*) printf_hextab) + [25] (byte*) screen#5 ← ++ (byte*) screen#18 + [26] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab) + [27] (byte*) screen#6 ← ++ (byte*) screen#5 + [28] *((byte*) screen#6) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age>>(byte) 4) + [29] (byte*) screen#7 ← ++ (byte*) screen#6 + [30] *((byte*) screen#7) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age&(byte) $f) + [31] (byte*) screen#23 ← ++ (byte*) screen#7 + to:printf_uint::@return +printf_uint::@return: scope:[printf_uint] from printf_uint + [32] return + to:@return + (void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left) printf_string: scope:[printf_string] from main::@1 - [18] phi() - [19] call printf_str + [33] phi() + [34] call printf_str to:printf_string::@return printf_string::@return: scope:[printf_string] from printf_string - [20] return + [35] return to:@return diff --git a/src/test/ref/printf-10.log b/src/test/ref/printf-10.log index d5a611be3..5faaa3b4b 100644 --- a/src/test/ref/printf-10.log +++ b/src/test/ref/printf-10.log @@ -1,119 +1,198 @@ -Added struct type cast to parameter value list call printf_string (const byte*) main::name (struct printf_format_string){ (byte) 0, (byte) 0 } +Added struct type cast to parameter value list call printf_string (byte*) "Jesper" (struct printf_format_string){ (byte) 0, (byte) 0 } +Added struct type cast to parameter value list call printf_uint (word) main::age (struct printf_format_number){ (byte) 0, (byte) 0, (byte) 0, (byte) 0, (const byte) HEXADECIMAL } Created struct value member variable (byte) printf_string::format_min_length Created struct value member variable (byte) printf_string::format_justify_left Converted struct value to member variables (struct printf_format_string) printf_string::format +Created struct value member variable (byte) printf_uint::format_min_length +Created struct value member variable (byte) printf_uint::format_justify_left +Created struct value member variable (byte) printf_uint::format_sign_always +Created struct value member variable (byte) printf_uint::format_zero_padding +Created struct value member variable (byte) printf_uint::format_radix +Converted struct value to member variables (struct printf_format_number) printf_uint::format Converted procedure struct value parameter to member unwinding (void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left) -Converted call struct value parameter to member unwinding call printf_string (const byte*) main::name (byte) 0 (byte) 0 +Converted procedure struct value parameter to member unwinding (void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix) +Converted call struct value parameter to member unwinding call printf_string (byte*) "Jesper" (byte) 0 (byte) 0 +Converted call struct value parameter to member unwinding call printf_uint (word) main::age (byte) 0 (byte) 0 (byte) 0 (byte) 0 (const byte) HEXADECIMAL Warning! Adding boolean cast to non-boolean condition *((byte*) printf_str::str) Identified constant variable (byte) idx +Identified constant variable (word) main::age Eliminating unused variable with no statement (void~) main::$0 +Eliminating unused variable with no statement (void~) main::$1 Culled Empty Block (label) printf_str::@4 Culled Empty Block (label) printf_str::@3 Culled Empty Block (label) printf_str::@5 Culled Empty Block (label) printf_str::@6 Culled Empty Block (label) @1 Culled Empty Block (label) @2 +Culled Empty Block (label) @3 CONTROL FLOW GRAPH SSA @begin: scope:[] from (byte*) screen#0 ← (byte*)(number) $400 - to:@3 + to:@4 (void()) printf_str((byte*) printf_str::str) -printf_str: scope:[printf_str] from main main::@2 printf_string - (byte*) screen#23 ← phi( main/(byte*) screen#21 main::@2/(byte*) screen#6 printf_string/(byte*) screen#20 ) - (byte*) printf_str::str#6 ← phi( main/(byte*) printf_str::str#2 main::@2/(byte*) printf_str::str#3 printf_string/(byte*) printf_str::str#1 ) +printf_str: scope:[printf_str] from main main::@2 main::@3 main::@5 printf_string + (byte*) screen#36 ← phi( main/(byte*) screen#34 main::@2/(byte*) screen#11 main::@3/(byte*) screen#12 main::@5/(byte*) screen#14 printf_string/(byte*) screen#33 ) + (byte*) printf_str::str#8 ← phi( main/(byte*) printf_str::str#2 main::@2/(byte*) printf_str::str#3 main::@3/(byte*) printf_str::str#4 main::@5/(byte*) printf_str::str#5 printf_string/(byte*) printf_str::str#1 ) to:printf_str::@1 printf_str::@1: scope:[printf_str] from printf_str printf_str::@2 - (byte*) screen#19 ← phi( printf_str/(byte*) screen#23 printf_str::@2/(byte*) screen#1 ) - (byte*) printf_str::str#4 ← phi( printf_str/(byte*) printf_str::str#6 printf_str::@2/(byte*) printf_str::str#0 ) - (bool~) printf_str::$0 ← (number) 0 != *((byte*) printf_str::str#4) + (byte*) screen#32 ← phi( printf_str/(byte*) screen#36 printf_str::@2/(byte*) screen#1 ) + (byte*) printf_str::str#6 ← phi( printf_str/(byte*) printf_str::str#8 printf_str::@2/(byte*) printf_str::str#0 ) + (bool~) printf_str::$0 ← (number) 0 != *((byte*) printf_str::str#6) if((bool~) printf_str::$0) goto printf_str::@2 to:printf_str::@return printf_str::@2: scope:[printf_str] from printf_str::@1 - (byte*) screen#10 ← phi( printf_str::@1/(byte*) screen#19 ) - (byte*) printf_str::str#5 ← phi( printf_str::@1/(byte*) printf_str::str#4 ) - *((byte*) screen#10) ← *((byte*) printf_str::str#5) - (byte*) screen#1 ← ++ (byte*) screen#10 - (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#5 + (byte*) screen#18 ← phi( printf_str::@1/(byte*) screen#32 ) + (byte*) printf_str::str#7 ← phi( printf_str::@1/(byte*) printf_str::str#6 ) + *((byte*) screen#18) ← *((byte*) printf_str::str#7) + (byte*) screen#1 ← ++ (byte*) screen#18 + (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#7 to:printf_str::@1 printf_str::@return: scope:[printf_str] from printf_str::@1 - (byte*) screen#11 ← phi( printf_str::@1/(byte*) screen#19 ) - (byte*) screen#2 ← (byte*) screen#11 + (byte*) screen#19 ← phi( printf_str::@1/(byte*) screen#32 ) + (byte*) screen#2 ← (byte*) screen#19 return to:@return (void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left) printf_string: scope:[printf_string] from main::@1 - (byte*) screen#20 ← phi( main::@1/(byte*) screen#5 ) + (byte*) screen#33 ← phi( main::@1/(byte*) screen#10 ) (byte*) printf_string::str#1 ← phi( main::@1/(byte*) printf_string::str#0 ) (byte*) printf_str::str#1 ← (byte*) printf_string::str#1 call printf_str to:printf_string::@1 printf_string::@1: scope:[printf_string] from printf_string - (byte*) screen#12 ← phi( printf_string/(byte*) screen#2 ) - (byte*) screen#3 ← (byte*) screen#12 + (byte*) screen#20 ← phi( printf_string/(byte*) screen#2 ) + (byte*) screen#3 ← (byte*) screen#20 to:printf_string::@return printf_string::@return: scope:[printf_string] from printf_string::@1 - (byte*) screen#13 ← phi( printf_string::@1/(byte*) screen#3 ) - (byte*) screen#4 ← (byte*) screen#13 + (byte*) screen#21 ← phi( printf_string::@1/(byte*) screen#3 ) + (byte*) screen#4 ← (byte*) screen#21 + return + to:@return + +(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix) +printf_uint: scope:[printf_uint] from main::@4 + (byte*) screen#22 ← phi( main::@4/(byte*) screen#13 ) + (word) printf_uint::uvalue#1 ← phi( main::@4/(word) printf_uint::uvalue#0 ) + (byte~) printf_uint::$0 ← > (word) printf_uint::uvalue#1 + (byte~) printf_uint::$1 ← (byte~) printf_uint::$0 >> (number) 4 + *((byte*) screen#22) ← *((const to_nomodify byte*) printf_hextab + (byte~) printf_uint::$1) + (byte*) screen#5 ← ++ (byte*) screen#22 + (byte~) printf_uint::$2 ← > (word) printf_uint::uvalue#1 + (number~) printf_uint::$3 ← (byte~) printf_uint::$2 & (number) $f + *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab + (number~) printf_uint::$3) + (byte*) screen#6 ← ++ (byte*) screen#5 + (byte~) printf_uint::$4 ← < (word) printf_uint::uvalue#1 + (byte~) printf_uint::$5 ← (byte~) printf_uint::$4 >> (number) 4 + *((byte*) screen#6) ← *((const to_nomodify byte*) printf_hextab + (byte~) printf_uint::$5) + (byte*) screen#7 ← ++ (byte*) screen#6 + (byte~) printf_uint::$6 ← < (word) printf_uint::uvalue#1 + (number~) printf_uint::$7 ← (byte~) printf_uint::$6 & (number) $f + *((byte*) screen#7) ← *((const to_nomodify byte*) printf_hextab + (number~) printf_uint::$7) + (byte*) screen#8 ← ++ (byte*) screen#7 + to:printf_uint::@return +printf_uint::@return: scope:[printf_uint] from printf_uint + (byte*) screen#23 ← phi( printf_uint/(byte*) screen#8 ) + (byte*) screen#9 ← (byte*) screen#23 return to:@return (void()) main() -main: scope:[main] from @3 - (byte*) screen#21 ← phi( @3/(byte*) screen#22 ) +main: scope:[main] from @4 + (byte*) screen#34 ← phi( @4/(byte*) screen#35 ) (byte*) printf_str::str#2 ← (const byte*) main::str call printf_str to:main::@1 main::@1: scope:[main] from main - (byte*) screen#14 ← phi( main/(byte*) screen#2 ) - (byte*) screen#5 ← (byte*) screen#14 - (byte*) printf_string::str#0 ← (const byte*) main::name + (byte*) screen#24 ← phi( main/(byte*) screen#2 ) + (byte*) screen#10 ← (byte*) screen#24 + (byte*) printf_string::str#0 ← (const byte*) main::str1 (byte) printf_string::format_min_length#0 ← (byte) 0 (byte) printf_string::format_justify_left#0 ← (byte) 0 call printf_string to:main::@2 main::@2: scope:[main] from main::@1 - (byte*) screen#15 ← phi( main::@1/(byte*) screen#4 ) - (byte*) screen#6 ← (byte*) screen#15 - (byte*) printf_str::str#3 ← (const byte*) main::str1 + (byte*) screen#25 ← phi( main::@1/(byte*) screen#4 ) + (byte*) screen#11 ← (byte*) screen#25 + (byte*) printf_str::str#3 ← (const byte*) main::str2 call printf_str to:main::@3 main::@3: scope:[main] from main::@2 - (byte*) screen#16 ← phi( main::@2/(byte*) screen#2 ) - (byte*) screen#7 ← (byte*) screen#16 + (byte*) screen#26 ← phi( main::@2/(byte*) screen#2 ) + (byte*) screen#12 ← (byte*) screen#26 + (byte*) printf_str::str#4 ← (const byte*) main::str3 + call printf_str + to:main::@4 +main::@4: scope:[main] from main::@3 + (byte*) screen#27 ← phi( main::@3/(byte*) screen#2 ) + (byte*) screen#13 ← (byte*) screen#27 + (word) printf_uint::uvalue#0 ← (const word) main::age + (byte) printf_uint::format_min_length#0 ← (byte) 0 + (byte) printf_uint::format_justify_left#0 ← (byte) 0 + (byte) printf_uint::format_sign_always#0 ← (byte) 0 + (byte) printf_uint::format_zero_padding#0 ← (byte) 0 + (byte) printf_uint::format_radix#0 ← (const byte) HEXADECIMAL + call printf_uint + to:main::@5 +main::@5: scope:[main] from main::@4 + (byte*) screen#28 ← phi( main::@4/(byte*) screen#9 ) + (byte*) screen#14 ← (byte*) screen#28 + (byte*) printf_str::str#5 ← (const byte*) main::str4 + call printf_str + to:main::@6 +main::@6: scope:[main] from main::@5 + (byte*) screen#29 ← phi( main::@5/(byte*) screen#2 ) + (byte*) screen#15 ← (byte*) screen#29 to:main::@return -main::@return: scope:[main] from main::@3 - (byte*) screen#17 ← phi( main::@3/(byte*) screen#7 ) - (byte*) screen#8 ← (byte*) screen#17 +main::@return: scope:[main] from main::@6 + (byte*) screen#30 ← phi( main::@6/(byte*) screen#15 ) + (byte*) screen#16 ← (byte*) screen#30 return to:@return -@3: scope:[] from @begin - (byte*) screen#22 ← phi( @begin/(byte*) screen#0 ) +@4: scope:[] from @begin + (byte*) screen#35 ← phi( @begin/(byte*) screen#0 ) call main - to:@4 -@4: scope:[] from @3 - (byte*) screen#18 ← phi( @3/(byte*) screen#8 ) - (byte*) screen#9 ← (byte*) screen#18 + to:@5 +@5: scope:[] from @4 + (byte*) screen#31 ← phi( @4/(byte*) screen#16 ) + (byte*) screen#17 ← (byte*) screen#31 to:@end -@end: scope:[] from @4 +@end: scope:[] from @5 SYMBOL TABLE SSA -(label) @3 (label) @4 +(label) @5 (label) @begin (label) @end +(const byte) HEXADECIMAL = (number) $10 +(const byte) RADIX::BINARY = (number) 2 +(const byte) RADIX::DECIMAL = (number) $a +(const byte) RADIX::HEXADECIMAL = (number) $10 +(const byte) RADIX::OCTAL = (number) 8 (void()) main() (label) main::@1 (label) main::@2 (label) main::@3 +(label) main::@4 +(label) main::@5 +(label) main::@6 (label) main::@return -(const byte*) main::name[] = (byte*) "Jesper" +(const word) main::age = (word) $2e (const byte*) main::str[(byte) $d] = (byte*) "Hello, I am " -(const byte*) main::str1[(byte) $f] = (byte*) ". who are you?" +(const byte*) main::str1[(byte) 7] = (byte*) "Jesper" +(const byte*) main::str2[(byte) $f] = (byte*) ". who are you?" +(const byte*) main::str3[(byte) 6] = (byte*) "I am " +(const byte*) main::str4[(byte) $b] = (byte*) " years old" +(byte) printf_format_number::justify_left +(byte) printf_format_number::min_length +(byte) printf_format_number::radix +(byte) printf_format_number::sign_always +(byte) printf_format_number::zero_padding (byte) printf_format_string::justify_left (byte) printf_format_string::min_length +(const to_nomodify byte*) printf_hextab[] = (byte*) "0123456789abcdef"z (void()) printf_str((byte*) printf_str::str) (bool~) printf_str::$0 (label) printf_str::@1 @@ -127,6 +206,8 @@ SYMBOL TABLE SSA (byte*) printf_str::str#4 (byte*) printf_str::str#5 (byte*) printf_str::str#6 +(byte*) printf_str::str#7 +(byte*) printf_str::str#8 (void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left) (label) printf_string::@1 (label) printf_string::@return @@ -138,6 +219,30 @@ SYMBOL TABLE SSA (byte*) printf_string::str (byte*) printf_string::str#0 (byte*) printf_string::str#1 +(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix) +(byte~) printf_uint::$0 +(byte~) printf_uint::$1 +(byte~) printf_uint::$2 +(number~) printf_uint::$3 +(byte~) printf_uint::$4 +(byte~) printf_uint::$5 +(byte~) printf_uint::$6 +(number~) printf_uint::$7 +(label) printf_uint::@return +(struct printf_format_number) printf_uint::format +(byte) printf_uint::format_justify_left +(byte) printf_uint::format_justify_left#0 +(byte) printf_uint::format_min_length +(byte) printf_uint::format_min_length#0 +(byte) printf_uint::format_radix +(byte) printf_uint::format_radix#0 +(byte) printf_uint::format_sign_always +(byte) printf_uint::format_sign_always#0 +(byte) printf_uint::format_zero_padding +(byte) printf_uint::format_zero_padding#0 +(word) printf_uint::uvalue +(word) printf_uint::uvalue#0 +(word) printf_uint::uvalue#1 (byte*) screen (byte*) screen#0 (byte*) screen#1 @@ -156,7 +261,20 @@ SYMBOL TABLE SSA (byte*) screen#21 (byte*) screen#22 (byte*) screen#23 +(byte*) screen#24 +(byte*) screen#25 +(byte*) screen#26 +(byte*) screen#27 +(byte*) screen#28 +(byte*) screen#29 (byte*) screen#3 +(byte*) screen#30 +(byte*) screen#31 +(byte*) screen#32 +(byte*) screen#33 +(byte*) screen#34 +(byte*) screen#35 +(byte*) screen#36 (byte*) screen#4 (byte*) screen#5 (byte*) screen#6 @@ -164,86 +282,177 @@ SYMBOL TABLE SSA (byte*) screen#8 (byte*) screen#9 -Adding number conversion cast (unumber) 0 in (bool~) printf_str::$0 ← (number) 0 != *((byte*) printf_str::str#4) +Adding number conversion cast (unumber) 0 in (bool~) printf_str::$0 ← (number) 0 != *((byte*) printf_str::str#6) +Adding number conversion cast (unumber) 4 in (byte~) printf_uint::$1 ← (byte~) printf_uint::$0 >> (number) 4 +Adding number conversion cast (unumber) $f in (number~) printf_uint::$3 ← (byte~) printf_uint::$2 & (number) $f +Adding number conversion cast (unumber) printf_uint::$3 in (number~) printf_uint::$3 ← (byte~) printf_uint::$2 & (unumber)(number) $f +Adding number conversion cast (unumber) 4 in (byte~) printf_uint::$5 ← (byte~) printf_uint::$4 >> (number) 4 +Adding number conversion cast (unumber) $f in (number~) printf_uint::$7 ← (byte~) printf_uint::$6 & (number) $f +Adding number conversion cast (unumber) printf_uint::$7 in (number~) printf_uint::$7 ← (byte~) printf_uint::$6 & (unumber)(number) $f Successful SSA optimization PassNAddNumberTypeConversions Simplifying constant pointer cast (byte*) 1024 Simplifying constant integer cast 0 +Simplifying constant integer cast 4 +Simplifying constant integer cast $f +Simplifying constant integer cast 4 +Simplifying constant integer cast $f Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 4 +Finalized unsigned number type (byte) $f +Finalized unsigned number type (byte) 4 +Finalized unsigned number type (byte) $f Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias printf_str::str#4 = printf_str::str#5 -Alias screen#10 = screen#19 screen#11 screen#2 -Alias screen#12 = screen#3 screen#13 screen#4 -Alias screen#14 = screen#5 -Alias screen#15 = screen#6 -Alias screen#16 = screen#7 screen#17 screen#8 -Alias screen#0 = screen#22 -Alias screen#18 = screen#9 +Inferred type updated to byte in (unumber~) printf_uint::$3 ← (byte~) printf_uint::$2 & (byte) $f +Inferred type updated to byte in (unumber~) printf_uint::$7 ← (byte~) printf_uint::$6 & (byte) $f +Alias printf_str::str#6 = printf_str::str#7 +Alias screen#18 = screen#32 screen#19 screen#2 +Alias screen#20 = screen#3 screen#21 screen#4 +Alias screen#23 = screen#8 screen#9 +Alias screen#10 = screen#24 +Alias screen#11 = screen#25 +Alias screen#12 = screen#26 +Alias screen#13 = screen#27 +Alias screen#14 = screen#28 +Alias screen#15 = screen#29 screen#30 screen#16 +Alias screen#0 = screen#35 +Alias screen#17 = screen#31 Successful SSA optimization Pass2AliasElimination Identical Phi Values (byte*) printf_string::str#1 (byte*) printf_string::str#0 -Identical Phi Values (byte*) screen#20 (byte*) screen#14 -Identical Phi Values (byte*) screen#12 (byte*) screen#10 -Identical Phi Values (byte*) screen#21 (byte*) screen#0 -Identical Phi Values (byte*) screen#14 (byte*) screen#10 -Identical Phi Values (byte*) screen#15 (byte*) screen#12 -Identical Phi Values (byte*) screen#16 (byte*) screen#10 -Identical Phi Values (byte*) screen#18 (byte*) screen#16 +Identical Phi Values (byte*) screen#33 (byte*) screen#10 +Identical Phi Values (byte*) screen#20 (byte*) screen#18 +Identical Phi Values (word) printf_uint::uvalue#1 (word) printf_uint::uvalue#0 +Identical Phi Values (byte*) screen#22 (byte*) screen#13 +Identical Phi Values (byte*) screen#34 (byte*) screen#0 +Identical Phi Values (byte*) screen#10 (byte*) screen#18 +Identical Phi Values (byte*) screen#11 (byte*) screen#20 +Identical Phi Values (byte*) screen#12 (byte*) screen#18 +Identical Phi Values (byte*) screen#13 (byte*) screen#18 +Identical Phi Values (byte*) screen#14 (byte*) screen#23 +Identical Phi Values (byte*) screen#15 (byte*) screen#18 +Identical Phi Values (byte*) screen#17 (byte*) screen#15 Successful SSA optimization Pass2IdenticalPhiElimination -Simple Condition (bool~) printf_str::$0 [4] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 +Identified duplicate assignment right side [25] (byte~) printf_uint::$2 ← > (word) printf_uint::uvalue#0 +Identified duplicate assignment right side [33] (byte~) printf_uint::$6 ← < (word) printf_uint::uvalue#0 +Successful SSA optimization Pass2DuplicateRValueIdentification +Simple Condition (bool~) printf_str::$0 [4] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 Successful SSA optimization Pass2ConditionalJumpSimplification Constant (const byte*) screen#0 = (byte*) 1024 Constant (const byte*) printf_str::str#2 = main::str -Constant (const byte*) printf_string::str#0 = main::name +Constant (const byte*) printf_string::str#0 = main::str1 Constant (const byte) printf_string::format_min_length#0 = 0 Constant (const byte) printf_string::format_justify_left#0 = 0 -Constant (const byte*) printf_str::str#3 = main::str1 +Constant (const byte*) printf_str::str#3 = main::str2 +Constant (const byte*) printf_str::str#4 = main::str3 +Constant (const word) printf_uint::uvalue#0 = main::age +Constant (const byte) printf_uint::format_min_length#0 = 0 +Constant (const byte) printf_uint::format_justify_left#0 = 0 +Constant (const byte) printf_uint::format_sign_always#0 = 0 +Constant (const byte) printf_uint::format_zero_padding#0 = 0 +Constant (const byte) printf_uint::format_radix#0 = HEXADECIMAL +Constant (const byte*) printf_str::str#5 = main::str4 Successful SSA optimization Pass2ConstantIdentification Constant (const byte*) printf_str::str#1 = printf_string::str#0 Successful SSA optimization Pass2ConstantIdentification Eliminating unused constant (const byte) printf_string::format_min_length#0 Eliminating unused constant (const byte) printf_string::format_justify_left#0 +Eliminating unused constant (const byte) printf_uint::format_min_length#0 +Eliminating unused constant (const byte) printf_uint::format_justify_left#0 +Eliminating unused constant (const byte) printf_uint::format_sign_always#0 +Eliminating unused constant (const byte) printf_uint::format_zero_padding#0 +Eliminating unused constant (const byte) printf_uint::format_radix#0 +Successful SSA optimization PassNEliminateUnusedVars +Eliminating unused constant (const byte) HEXADECIMAL +Successful SSA optimization PassNEliminateUnusedVars +Alias printf_uint::$2 = printf_uint::$0 +Alias printf_uint::$6 = printf_uint::$4 +Successful SSA optimization Pass2AliasElimination +Constant right-side identified [9] (byte~) printf_uint::$2 ← > (const word) printf_uint::uvalue#0 +Constant right-side identified [16] (byte~) printf_uint::$6 ← < (const word) printf_uint::uvalue#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) printf_uint::$2 = >printf_uint::uvalue#0 +Constant (const byte) printf_uint::$6 = (const word) printf_uint::uvalue#0 in +Successful SSA optimization PassNSimplifyConstantZero +Constant right-side identified [9] (byte~) printf_uint::$1 ← (const byte) printf_uint::$2 >> (byte) 4 +Constant right-side identified [12] (byte~) printf_uint::$3 ← (const byte) printf_uint::$2 & (byte) $f +Constant right-side identified [15] (byte~) printf_uint::$5 ← (const byte) printf_uint::$6 >> (byte) 4 +Constant right-side identified [18] (byte~) printf_uint::$7 ← (const byte) printf_uint::$6 & (byte) $f +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte) printf_uint::$1 = printf_uint::$2>>4 +Constant (const byte) printf_uint::$3 = printf_uint::$2&$f +Constant (const byte) printf_uint::$5 = printf_uint::$6>>4 +Constant (const byte) printf_uint::$7 = printf_uint::$6&$f +Successful SSA optimization Pass2ConstantIdentification +Simplifying constant evaluating to zero (const byte) printf_uint::$2>>(byte) 4 in +Simplifying constant evaluating to zero (const byte) printf_uint::$2&(byte) $f in +Successful SSA optimization PassNSimplifyConstantZero +Simplifying expression containing zero printf_hextab in [10] *((byte*) screen#18) ← *((const to_nomodify byte*) printf_hextab + (const byte) printf_uint::$1) +Simplifying expression containing zero printf_hextab in [13] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab + (const byte) printf_uint::$3) +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused constant (const byte) printf_uint::$2 +Eliminating unused constant (const byte) printf_uint::$1 +Eliminating unused constant (const byte) printf_uint::$3 Successful SSA optimization PassNEliminateUnusedVars Inlining constant with var siblings (const byte*) printf_str::str#2 Inlining constant with var siblings (const byte*) printf_str::str#3 +Inlining constant with var siblings (const byte*) printf_str::str#4 +Inlining constant with var siblings (const byte*) printf_str::str#5 Inlining constant with var siblings (const byte*) printf_str::str#1 Inlining constant with var siblings (const byte*) screen#0 -Constant inlined printf_string::str#0 = (const byte*) main::name +Constant inlined printf_str::str#5 = (const byte*) main::str4 +Constant inlined printf_string::str#0 = (const byte*) main::str1 +Constant inlined printf_uint::uvalue#0 = (const word) main::age +Constant inlined printf_uint::$5 = <(const word) main::age>>(byte) 4 +Constant inlined printf_uint::$7 = <(const word) main::age&(byte) $f +Constant inlined printf_uint::$6 = <(const word) main::age Constant inlined printf_str::str#2 = (const byte*) main::str -Constant inlined printf_str::str#1 = (const byte*) main::name +Constant inlined printf_str::str#1 = (const byte*) main::str1 +Constant inlined printf_str::str#4 = (const byte*) main::str3 Constant inlined screen#0 = (byte*) 1024 -Constant inlined printf_str::str#3 = (const byte*) main::str1 +Constant inlined printf_str::str#3 = (const byte*) main::str2 Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(printf_hextab+>4) +Consolidated array index constant in *(printf_hextab+>(byte) 4) + [29] (byte*) screen#7 ← ++ (byte*) screen#6 + [30] *((byte*) screen#7) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age&(byte) $f) + [31] (byte*) screen#23 ← ++ (byte*) screen#7 + to:printf_uint::@return +printf_uint::@return: scope:[printf_uint] from printf_uint + [32] return + to:@return + (void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left) printf_string: scope:[printf_string] from main::@1 - [18] phi() - [19] call printf_str + [33] phi() + [34] call printf_str to:printf_string::@return printf_string::@return: scope:[printf_string] from printf_string - [20] return + [35] return to:@return VARIABLE REGISTER WEIGHTS (void()) main() +(byte) printf_format_number::justify_left +(byte) printf_format_number::min_length +(byte) printf_format_number::radix +(byte) printf_format_number::sign_always +(byte) printf_format_number::zero_padding (byte) printf_format_string::justify_left (byte) printf_format_string::min_length (void()) printf_str((byte*) printf_str::str) (byte*) printf_str::str (byte*) printf_str::str#0 20002.0 -(byte*) printf_str::str#4 10251.25 -(byte*) printf_str::str#6 1001.0 +(byte*) printf_str::str#6 10251.25 +(byte*) printf_str::str#8 1001.0 (void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left) (struct printf_format_string) printf_string::format (byte) printf_string::format_justify_left (byte) printf_string::format_min_length (byte*) printf_string::str +(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix) +(struct printf_format_number) printf_uint::format +(byte) printf_uint::format_justify_left +(byte) printf_uint::format_min_length +(byte) printf_uint::format_radix +(byte) printf_uint::format_sign_always +(byte) printf_uint::format_zero_padding +(word) printf_uint::uvalue (byte*) screen (byte*) screen#1 10001.0 -(byte*) screen#10 2828.7272727272725 -(byte*) screen#23 1113.0 +(byte*) screen#18 1958.0625 +(byte*) screen#23 28.0 +(byte*) screen#36 1135.0 +(byte*) screen#5 151.5 +(byte*) screen#6 151.5 +(byte*) screen#7 151.5 Initial phi equivalence classes -[ screen#23 screen#10 screen#1 ] -[ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] +[ screen#36 screen#18 screen#23 screen#1 ] +[ printf_str::str#6 printf_str::str#8 printf_str::str#0 ] +Added variable screen#5 to live range equivalence class [ screen#5 ] +Added variable screen#6 to live range equivalence class [ screen#6 ] +Added variable screen#7 to live range equivalence class [ screen#7 ] Complete equivalence classes -[ screen#23 screen#10 screen#1 ] -[ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] -Allocated zp[2]:2 [ screen#23 screen#10 screen#1 ] -Allocated zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] +[ screen#36 screen#18 screen#23 screen#1 ] +[ printf_str::str#6 printf_str::str#8 printf_str::str#0 ] +[ screen#5 ] +[ screen#6 ] +[ screen#7 ] +Allocated zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 ] +Allocated zp[2]:4 [ printf_str::str#6 printf_str::str#8 printf_str::str#0 ] +Allocated zp[2]:6 [ screen#5 ] +Allocated zp[2]:8 [ screen#6 ] +Allocated zp[2]:10 [ screen#7 ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -342,6 +604,9 @@ Target platform is c64basic / MOS6502X .pc = $80d "Program" // Global Constants & labels .label screen = 2 + .label screen_1 = 6 + .label screen_2 = 8 + .label screen_3 = $a // @begin __bbegin: // [1] phi from @begin to @1 [phi:@begin->@1] @@ -360,15 +625,16 @@ __bend_from___b1: __bend: // main main: { + .label age = $2e // [5] call printf_str - // [11] phi from main to printf_str [phi:main->printf_str] + // [17] phi from main to printf_str [phi:main->printf_str] printf_str_from_main: - // [11] phi (byte*) screen#23 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 + // [17] phi (byte*) screen#36 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 lda #str @@ -380,7 +646,7 @@ main: { // main::@1 __b1: // [7] call printf_string - // [18] phi from main::@1 to printf_string [phi:main::@1->printf_string] + // [33] phi from main::@1 to printf_string [phi:main::@1->printf_string] printf_string_from___b1: jsr printf_string // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] @@ -389,40 +655,81 @@ main: { // main::@2 __b2: // [9] call printf_str - // [11] phi from main::@2 to printf_str [phi:main::@2->printf_str] + // [17] phi from main::@2 to printf_str [phi:main::@2->printf_str] printf_str_from___b2: - // [11] phi (byte*) screen#23 = (byte*) screen#10 [phi:main::@2->printf_str#0] -- register_copy - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str1 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 - lda #printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str2 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 + lda #str1 + lda #>str2 + sta.z printf_str.str+1 + jsr printf_str + // [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + __b3_from___b2: + jmp __b3 + // main::@3 + __b3: + // [11] call printf_str + // [17] phi from main::@3 to printf_str [phi:main::@3->printf_str] + printf_str_from___b3: + // [17] phi (byte*) screen#36 = (byte*) screen#18 [phi:main::@3->printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str3 [phi:main::@3->printf_str#1] -- pbuz1=pbuc1 + lda #str3 + sta.z printf_str.str+1 + jsr printf_str + // [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4] + __b4_from___b3: + jmp __b4 + // main::@4 + __b4: + // [13] call printf_uint + jsr printf_uint + // [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + __b5_from___b4: + jmp __b5 + // main::@5 + __b5: + // [15] call printf_str + // [17] phi from main::@5 to printf_str [phi:main::@5->printf_str] + printf_str_from___b5: + // [17] phi (byte*) screen#36 = (byte*) screen#23 [phi:main::@5->printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str4 [phi:main::@5->printf_str#1] -- pbuz1=pbuc1 + lda #str4 sta.z printf_str.str+1 jsr printf_str jmp __breturn // main::@return __breturn: - // [10] return + // [16] return rts - name: .text "Jesper" - .byte 0 str: .text "Hello, I am " .byte 0 - str1: .text ". who are you?" + str1: .text "Jesper" + .byte 0 + str2: .text ". who are you?" + .byte 0 + str3: .text "I am " + .byte 0 + str4: .text " years old" .byte 0 } // printf_str // printf_str(byte* zp(4) str) printf_str: { .label str = 4 - // [12] phi from printf_str printf_str::@2 to printf_str::@1 [phi:printf_str/printf_str::@2->printf_str::@1] + // [18] phi from printf_str printf_str::@2 to printf_str::@1 [phi:printf_str/printf_str::@2->printf_str::@1] __b1_from_printf_str: __b1_from___b2: - // [12] phi (byte*) screen#10 = (byte*) screen#23 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy - // [12] phi (byte*) printf_str::str#4 = (byte*) printf_str::str#6 [phi:printf_str/printf_str::@2->printf_str::@1#1] -- register_copy + // [18] phi (byte*) screen#18 = (byte*) screen#36 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy + // [18] phi (byte*) printf_str::str#6 = (byte*) printf_str::str#8 [phi:printf_str/printf_str::@2->printf_str::@1#1] -- register_copy jmp __b1 // printf_str::@1 __b1: - // [13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + // [19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (str),y cmp #0 @@ -430,67 +737,146 @@ printf_str: { jmp __breturn // printf_str::@return __breturn: - // [14] return + // [20] return rts // printf_str::@2 __b2: - // [15] *((byte*) screen#10) ← *((byte*) printf_str::str#4) -- _deref_pbuz1=_deref_pbuz2 + // [21] *((byte*) screen#18) ← *((byte*) printf_str::str#6) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (str),y ldy #0 sta (screen),y - // [16] (byte*) screen#1 ← ++ (byte*) screen#10 -- pbuz1=_inc_pbuz1 + // [22] (byte*) screen#1 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: - // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4 -- pbuz1=_inc_pbuz1 + // [23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6 -- pbuz1=_inc_pbuz1 inc.z str bne !+ inc.z str+1 !: jmp __b1_from___b2 +} + // printf_uint +// Print an unsigned int using a specific format +// Always prints hexadecimals - ignores min_length and flags +printf_uint: { + // [24] *((byte*) screen#18) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen),y + // [25] (byte*) screen#5 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz2 + lda.z screen + clc + adc #1 + sta.z screen_1 + lda.z screen+1 + adc #0 + sta.z screen_1+1 + // [26] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen_1),y + // [27] (byte*) screen#6 ← ++ (byte*) screen#5 -- pbuz1=_inc_pbuz2 + lda.z screen_1 + clc + adc #1 + sta.z screen_2 + lda.z screen_1+1 + adc #0 + sta.z screen_2+1 + // [28] *((byte*) screen#6) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age>>(byte) 4) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>4) + ldy #0 + sta (screen_2),y + // [29] (byte*) screen#7 ← ++ (byte*) screen#6 -- pbuz1=_inc_pbuz2 + lda.z screen_2 + clc + adc #1 + sta.z screen_3 + lda.z screen_2+1 + adc #0 + sta.z screen_3+1 + // [30] *((byte*) screen#7) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age&(byte) $f) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((printf_str] + // [34] call printf_str + // [17] phi from printf_string to printf_str [phi:printf_string->printf_str] printf_str_from_printf_string: - // [11] phi (byte*) screen#23 = (byte*) screen#10 [phi:printf_string->printf_str#0] -- register_copy - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::name [phi:printf_string->printf_str#1] -- pbuz1=pbuc1 - lda #printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str1 [phi:printf_string->printf_str#1] -- pbuz1=pbuc1 + lda #main.name + lda #>main.str1 sta.z printf_str.str+1 jsr printf_str jmp __breturn // printf_string::@return __breturn: - // [20] return + // [35] return rts } // File Data + printf_hextab: .text "0123456789abcdef" REGISTER UPLIFT POTENTIAL REGISTERS -Statement [13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 [ screen#10 printf_str::str#4 ] ( main:2::printf_str:5 [ screen#10 printf_str::str#4 ] { } main:2::printf_str:9 [ screen#10 printf_str::str#4 ] { { screen#10 = screen#23 } } main:2::printf_string:7::printf_str:19 [ screen#10 printf_str::str#4 ] { { screen#10 = screen#23 } } ) always clobbers reg byte a reg byte y -Statement [15] *((byte*) screen#10) ← *((byte*) printf_str::str#4) [ screen#10 printf_str::str#4 ] ( main:2::printf_str:5 [ screen#10 printf_str::str#4 ] { } main:2::printf_str:9 [ screen#10 printf_str::str#4 ] { { screen#10 = screen#23 } } main:2::printf_string:7::printf_str:19 [ screen#10 printf_str::str#4 ] { { screen#10 = screen#23 } } ) always clobbers reg byte a reg byte y -Potential registers zp[2]:2 [ screen#23 screen#10 screen#1 ] : zp[2]:2 , -Potential registers zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] : zp[2]:4 , +Statement [19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 [ screen#18 printf_str::str#6 ] ( main:2::printf_str:5 [ screen#18 printf_str::str#6 ] { } main:2::printf_str:9 [ screen#18 printf_str::str#6 ] { { screen#18 = screen#36 } } main:2::printf_str:11 [ screen#18 printf_str::str#6 ] { { screen#18 = screen#36 } } main:2::printf_str:15 [ screen#18 printf_str::str#6 ] { { screen#23 = screen#36 } } main:2::printf_string:7::printf_str:34 [ screen#18 printf_str::str#6 ] { { screen#18 = screen#36 } } ) always clobbers reg byte a reg byte y +Statement [21] *((byte*) screen#18) ← *((byte*) printf_str::str#6) [ screen#18 printf_str::str#6 ] ( main:2::printf_str:5 [ screen#18 printf_str::str#6 ] { } main:2::printf_str:9 [ screen#18 printf_str::str#6 ] { { screen#18 = screen#36 } } main:2::printf_str:11 [ screen#18 printf_str::str#6 ] { { screen#18 = screen#36 } } main:2::printf_str:15 [ screen#18 printf_str::str#6 ] { { screen#23 = screen#36 } } main:2::printf_string:7::printf_str:34 [ screen#18 printf_str::str#6 ] { { screen#18 = screen#36 } } ) always clobbers reg byte a reg byte y +Statement [24] *((byte*) screen#18) ← *((const to_nomodify byte*) printf_hextab) [ screen#18 ] ( main:2::printf_uint:13 [ screen#18 ] { } ) always clobbers reg byte a reg byte y +Statement [25] (byte*) screen#5 ← ++ (byte*) screen#18 [ screen#5 ] ( main:2::printf_uint:13 [ screen#5 ] { } ) always clobbers reg byte a +Statement [26] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab) [ screen#5 ] ( main:2::printf_uint:13 [ screen#5 ] { } ) always clobbers reg byte a reg byte y +Statement [27] (byte*) screen#6 ← ++ (byte*) screen#5 [ screen#6 ] ( main:2::printf_uint:13 [ screen#6 ] { } ) always clobbers reg byte a +Statement [28] *((byte*) screen#6) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age>>(byte) 4) [ screen#6 ] ( main:2::printf_uint:13 [ screen#6 ] { } ) always clobbers reg byte a reg byte y +Statement [29] (byte*) screen#7 ← ++ (byte*) screen#6 [ screen#7 ] ( main:2::printf_uint:13 [ screen#7 ] { } ) always clobbers reg byte a +Statement [30] *((byte*) screen#7) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age&(byte) $f) [ screen#7 ] ( main:2::printf_uint:13 [ screen#7 ] { } ) always clobbers reg byte a reg byte y +Statement [31] (byte*) screen#23 ← ++ (byte*) screen#7 [ screen#23 ] ( main:2::printf_uint:13 [ screen#23 ] { } ) always clobbers reg byte a +Potential registers zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 ] : zp[2]:2 , +Potential registers zp[2]:4 [ printf_str::str#6 printf_str::str#8 printf_str::str#0 ] : zp[2]:4 , +Potential registers zp[2]:6 [ screen#5 ] : zp[2]:6 , +Potential registers zp[2]:8 [ screen#6 ] : zp[2]:8 , +Potential registers zp[2]:10 [ screen#7 ] : zp[2]:10 , REGISTER UPLIFT SCOPES -Uplift Scope [printf_str] 31,254.25: zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] -Uplift Scope [] 13,942.73: zp[2]:2 [ screen#23 screen#10 screen#1 ] +Uplift Scope [printf_str] 31,254.25: zp[2]:4 [ printf_str::str#6 printf_str::str#8 printf_str::str#0 ] +Uplift Scope [] 13,122.06: zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 ] 151.5: zp[2]:6 [ screen#5 ] 151.5: zp[2]:8 [ screen#6 ] 151.5: zp[2]:10 [ screen#7 ] Uplift Scope [printf_format_string] Uplift Scope [printf_string] +Uplift Scope [RADIX] +Uplift Scope [printf_format_number] +Uplift Scope [printf_uint] Uplift Scope [main] -Uplifting [printf_str] best 721 combination zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] -Uplifting [] best 721 combination zp[2]:2 [ screen#23 screen#10 screen#1 ] -Uplifting [printf_format_string] best 721 combination -Uplifting [printf_string] best 721 combination -Uplifting [main] best 721 combination +Uplifting [printf_str] best 897 combination zp[2]:4 [ printf_str::str#6 printf_str::str#8 printf_str::str#0 ] +Uplifting [] best 897 combination zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 ] zp[2]:6 [ screen#5 ] zp[2]:8 [ screen#6 ] zp[2]:10 [ screen#7 ] +Uplifting [printf_format_string] best 897 combination +Uplifting [printf_string] best 897 combination +Uplifting [RADIX] best 897 combination +Uplifting [printf_format_number] best 897 combination +Uplifting [printf_uint] best 897 combination +Uplifting [main] best 897 combination +Coalescing zero page register [ zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 ] ] with [ zp[2]:6 [ screen#5 ] ] - score: 1 +Coalescing zero page register [ zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 screen#5 ] ] with [ zp[2]:10 [ screen#7 ] ] - score: 1 +Coalescing zero page register [ zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 screen#5 screen#7 ] ] with [ zp[2]:8 [ screen#6 ] ] - score: 2 ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -520,15 +906,16 @@ __bend_from___b1: __bend: // main main: { + .label age = $2e // [5] call printf_str - // [11] phi from main to printf_str [phi:main->printf_str] + // [17] phi from main to printf_str [phi:main->printf_str] printf_str_from_main: - // [11] phi (byte*) screen#23 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 + // [17] phi (byte*) screen#36 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 lda #str @@ -540,7 +927,7 @@ main: { // main::@1 __b1: // [7] call printf_string - // [18] phi from main::@1 to printf_string [phi:main::@1->printf_string] + // [33] phi from main::@1 to printf_string [phi:main::@1->printf_string] printf_string_from___b1: jsr printf_string // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] @@ -549,40 +936,81 @@ main: { // main::@2 __b2: // [9] call printf_str - // [11] phi from main::@2 to printf_str [phi:main::@2->printf_str] + // [17] phi from main::@2 to printf_str [phi:main::@2->printf_str] printf_str_from___b2: - // [11] phi (byte*) screen#23 = (byte*) screen#10 [phi:main::@2->printf_str#0] -- register_copy - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str1 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 - lda #printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str2 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 + lda #str1 + lda #>str2 + sta.z printf_str.str+1 + jsr printf_str + // [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + __b3_from___b2: + jmp __b3 + // main::@3 + __b3: + // [11] call printf_str + // [17] phi from main::@3 to printf_str [phi:main::@3->printf_str] + printf_str_from___b3: + // [17] phi (byte*) screen#36 = (byte*) screen#18 [phi:main::@3->printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str3 [phi:main::@3->printf_str#1] -- pbuz1=pbuc1 + lda #str3 + sta.z printf_str.str+1 + jsr printf_str + // [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4] + __b4_from___b3: + jmp __b4 + // main::@4 + __b4: + // [13] call printf_uint + jsr printf_uint + // [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + __b5_from___b4: + jmp __b5 + // main::@5 + __b5: + // [15] call printf_str + // [17] phi from main::@5 to printf_str [phi:main::@5->printf_str] + printf_str_from___b5: + // [17] phi (byte*) screen#36 = (byte*) screen#23 [phi:main::@5->printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str4 [phi:main::@5->printf_str#1] -- pbuz1=pbuc1 + lda #str4 sta.z printf_str.str+1 jsr printf_str jmp __breturn // main::@return __breturn: - // [10] return + // [16] return rts - name: .text "Jesper" - .byte 0 str: .text "Hello, I am " .byte 0 - str1: .text ". who are you?" + str1: .text "Jesper" + .byte 0 + str2: .text ". who are you?" + .byte 0 + str3: .text "I am " + .byte 0 + str4: .text " years old" .byte 0 } // printf_str // printf_str(byte* zp(4) str) printf_str: { .label str = 4 - // [12] phi from printf_str printf_str::@2 to printf_str::@1 [phi:printf_str/printf_str::@2->printf_str::@1] + // [18] phi from printf_str printf_str::@2 to printf_str::@1 [phi:printf_str/printf_str::@2->printf_str::@1] __b1_from_printf_str: __b1_from___b2: - // [12] phi (byte*) screen#10 = (byte*) screen#23 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy - // [12] phi (byte*) printf_str::str#4 = (byte*) printf_str::str#6 [phi:printf_str/printf_str::@2->printf_str::@1#1] -- register_copy + // [18] phi (byte*) screen#18 = (byte*) screen#36 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy + // [18] phi (byte*) printf_str::str#6 = (byte*) printf_str::str#8 [phi:printf_str/printf_str::@2->printf_str::@1#1] -- register_copy jmp __b1 // printf_str::@1 __b1: - // [13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + // [19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (str),y cmp #0 @@ -590,58 +1018,109 @@ printf_str: { jmp __breturn // printf_str::@return __breturn: - // [14] return + // [20] return rts // printf_str::@2 __b2: - // [15] *((byte*) screen#10) ← *((byte*) printf_str::str#4) -- _deref_pbuz1=_deref_pbuz2 + // [21] *((byte*) screen#18) ← *((byte*) printf_str::str#6) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (str),y ldy #0 sta (screen),y - // [16] (byte*) screen#1 ← ++ (byte*) screen#10 -- pbuz1=_inc_pbuz1 + // [22] (byte*) screen#1 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: - // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4 -- pbuz1=_inc_pbuz1 + // [23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6 -- pbuz1=_inc_pbuz1 inc.z str bne !+ inc.z str+1 !: jmp __b1_from___b2 +} + // printf_uint +// Print an unsigned int using a specific format +// Always prints hexadecimals - ignores min_length and flags +printf_uint: { + // [24] *((byte*) screen#18) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen),y + // [25] (byte*) screen#5 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [26] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen),y + // [27] (byte*) screen#6 ← ++ (byte*) screen#5 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [28] *((byte*) screen#6) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age>>(byte) 4) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>4) + ldy #0 + sta (screen),y + // [29] (byte*) screen#7 ← ++ (byte*) screen#6 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [30] *((byte*) screen#7) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age&(byte) $f) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((printf_str] + // [34] call printf_str + // [17] phi from printf_string to printf_str [phi:printf_string->printf_str] printf_str_from_printf_string: - // [11] phi (byte*) screen#23 = (byte*) screen#10 [phi:printf_string->printf_str#0] -- register_copy - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::name [phi:printf_string->printf_str#1] -- pbuz1=pbuc1 - lda #printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str1 [phi:printf_string->printf_str#1] -- pbuz1=pbuc1 + lda #main.name + lda #>main.str1 sta.z printf_str.str+1 jsr printf_str jmp __breturn // printf_string::@return __breturn: - // [20] return + // [35] return rts } // File Data + printf_hextab: .text "0123456789abcdef" ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 Removing instruction jmp __bend Removing instruction jmp __b1 Removing instruction jmp __b2 +Removing instruction jmp __b3 +Removing instruction jmp __b4 +Removing instruction jmp __b5 Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn +Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Removing instruction ldy #0 Succesful ASM optimization Pass5UnnecesaryLoadElimination @@ -654,6 +1133,11 @@ Removing instruction __b1_from_main: Removing instruction printf_string_from___b1: Removing instruction __b2_from___b1: Removing instruction printf_str_from___b2: +Removing instruction __b3_from___b2: +Removing instruction printf_str_from___b3: +Removing instruction __b4_from___b3: +Removing instruction __b5_from___b4: +Removing instruction printf_str_from___b5: Removing instruction __b1_from_printf_str: Removing instruction __b1_from___b2: Succesful ASM optimization Pass5RedundantLabelElimination @@ -661,6 +1145,10 @@ Removing instruction __bend: Removing instruction printf_str_from_main: Removing instruction __b1: Removing instruction __b2: +Removing instruction __b3: +Removing instruction __b4: +Removing instruction __b5: +Removing instruction __breturn: Removing instruction __breturn: Removing instruction __breturn: Removing instruction printf_str_from_printf_string: @@ -676,40 +1164,69 @@ FINAL SYMBOL TABLE (label) @1 (label) @begin (label) @end +(const byte) RADIX::BINARY = (number) 2 +(const byte) RADIX::DECIMAL = (number) $a +(const byte) RADIX::HEXADECIMAL = (number) $10 +(const byte) RADIX::OCTAL = (number) 8 (void()) main() (label) main::@1 (label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 (label) main::@return -(const byte*) main::name[] = (byte*) "Jesper" +(const word) main::age = (word) $2e (const byte*) main::str[(byte) $d] = (byte*) "Hello, I am " -(const byte*) main::str1[(byte) $f] = (byte*) ". who are you?" +(const byte*) main::str1[(byte) 7] = (byte*) "Jesper" +(const byte*) main::str2[(byte) $f] = (byte*) ". who are you?" +(const byte*) main::str3[(byte) 6] = (byte*) "I am " +(const byte*) main::str4[(byte) $b] = (byte*) " years old" +(byte) printf_format_number::justify_left +(byte) printf_format_number::min_length +(byte) printf_format_number::radix +(byte) printf_format_number::sign_always +(byte) printf_format_number::zero_padding (byte) printf_format_string::justify_left (byte) printf_format_string::min_length +(const to_nomodify byte*) printf_hextab[] = (byte*) "0123456789abcdef"z (void()) printf_str((byte*) printf_str::str) (label) printf_str::@1 (label) printf_str::@2 (label) printf_str::@return (byte*) printf_str::str (byte*) printf_str::str#0 str zp[2]:4 20002.0 -(byte*) printf_str::str#4 str zp[2]:4 10251.25 -(byte*) printf_str::str#6 str zp[2]:4 1001.0 +(byte*) printf_str::str#6 str zp[2]:4 10251.25 +(byte*) printf_str::str#8 str zp[2]:4 1001.0 (void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left) (label) printf_string::@return (struct printf_format_string) printf_string::format (byte) printf_string::format_justify_left (byte) printf_string::format_min_length (byte*) printf_string::str +(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix) +(label) printf_uint::@return +(struct printf_format_number) printf_uint::format +(byte) printf_uint::format_justify_left +(byte) printf_uint::format_min_length +(byte) printf_uint::format_radix +(byte) printf_uint::format_sign_always +(byte) printf_uint::format_zero_padding +(word) printf_uint::uvalue (byte*) screen (byte*) screen#1 screen zp[2]:2 10001.0 -(byte*) screen#10 screen zp[2]:2 2828.7272727272725 -(byte*) screen#23 screen zp[2]:2 1113.0 +(byte*) screen#18 screen zp[2]:2 1958.0625 +(byte*) screen#23 screen zp[2]:2 28.0 +(byte*) screen#36 screen zp[2]:2 1135.0 +(byte*) screen#5 screen zp[2]:2 151.5 +(byte*) screen#6 screen zp[2]:2 151.5 +(byte*) screen#7 screen zp[2]:2 151.5 -zp[2]:2 [ screen#23 screen#10 screen#1 ] -zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] +zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 screen#5 screen#7 screen#6 ] +zp[2]:4 [ printf_str::str#6 printf_str::str#8 printf_str::str#0 ] FINAL ASSEMBLER -Score: 617 +Score: 757 // File Comments // Tests printf function call rewriting @@ -729,15 +1246,16 @@ Score: 617 // @end // main main: { - // printf("Hello, I am %s. who are you?", name) + .label age = $2e + // printf("Hello, I am %s. who are you?", "Jesper") // [5] call printf_str - // [11] phi from main to printf_str [phi:main->printf_str] - // [11] phi (byte*) screen#23 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 + // [17] phi from main to printf_str [phi:main->printf_str] + // [17] phi (byte*) screen#36 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 lda #str @@ -745,90 +1263,177 @@ main: { jsr printf_str // [6] phi from main to main::@1 [phi:main->main::@1] // main::@1 - // printf("Hello, I am %s. who are you?", name) + // printf("Hello, I am %s. who are you?", "Jesper") // [7] call printf_string - // [18] phi from main::@1 to printf_string [phi:main::@1->printf_string] + // [33] phi from main::@1 to printf_string [phi:main::@1->printf_string] jsr printf_string // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] // main::@2 - // printf("Hello, I am %s. who are you?", name) + // printf("Hello, I am %s. who are you?", "Jesper") // [9] call printf_str - // [11] phi from main::@2 to printf_str [phi:main::@2->printf_str] - // [11] phi (byte*) screen#23 = (byte*) screen#10 [phi:main::@2->printf_str#0] -- register_copy - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str1 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 - lda #printf_str] + // [17] phi (byte*) screen#36 = (byte*) screen#18 [phi:main::@2->printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str2 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 + lda #str1 + lda #>str2 + sta.z printf_str.str+1 + jsr printf_str + // [10] phi from main::@2 to main::@3 [phi:main::@2->main::@3] + // main::@3 + // printf("I am %x years old", age) + // [11] call printf_str + // [17] phi from main::@3 to printf_str [phi:main::@3->printf_str] + // [17] phi (byte*) screen#36 = (byte*) screen#18 [phi:main::@3->printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str3 [phi:main::@3->printf_str#1] -- pbuz1=pbuc1 + lda #str3 + sta.z printf_str.str+1 + jsr printf_str + // [12] phi from main::@3 to main::@4 [phi:main::@3->main::@4] + // main::@4 + // printf("I am %x years old", age) + // [13] call printf_uint + jsr printf_uint + // [14] phi from main::@4 to main::@5 [phi:main::@4->main::@5] + // main::@5 + // printf("I am %x years old", age) + // [15] call printf_str + // [17] phi from main::@5 to printf_str [phi:main::@5->printf_str] + // [17] phi (byte*) screen#36 = (byte*) screen#23 [phi:main::@5->printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str4 [phi:main::@5->printf_str#1] -- pbuz1=pbuc1 + lda #str4 sta.z printf_str.str+1 jsr printf_str // main::@return // } - // [10] return + // [16] return rts - name: .text "Jesper" - .byte 0 str: .text "Hello, I am " .byte 0 - str1: .text ". who are you?" + str1: .text "Jesper" + .byte 0 + str2: .text ". who are you?" + .byte 0 + str3: .text "I am " + .byte 0 + str4: .text " years old" .byte 0 } // printf_str // printf_str(byte* zp(4) str) printf_str: { .label str = 4 - // [12] phi from printf_str printf_str::@2 to printf_str::@1 [phi:printf_str/printf_str::@2->printf_str::@1] - // [12] phi (byte*) screen#10 = (byte*) screen#23 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy - // [12] phi (byte*) printf_str::str#4 = (byte*) printf_str::str#6 [phi:printf_str/printf_str::@2->printf_str::@1#1] -- register_copy + // [18] phi from printf_str printf_str::@2 to printf_str::@1 [phi:printf_str/printf_str::@2->printf_str::@1] + // [18] phi (byte*) screen#18 = (byte*) screen#36 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy + // [18] phi (byte*) printf_str::str#6 = (byte*) printf_str::str#8 [phi:printf_str/printf_str::@2->printf_str::@1#1] -- register_copy // printf_str::@1 __b1: // while(*str) - // [13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + // [19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (str),y cmp #0 bne __b2 // printf_str::@return // } - // [14] return + // [20] return rts // printf_str::@2 __b2: // *screen++ = *str++ - // [15] *((byte*) screen#10) ← *((byte*) printf_str::str#4) -- _deref_pbuz1=_deref_pbuz2 + // [21] *((byte*) screen#18) ← *((byte*) printf_str::str#6) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (str),y sta (screen),y // *screen++ = *str++; - // [16] (byte*) screen#1 ← ++ (byte*) screen#10 -- pbuz1=_inc_pbuz1 + // [22] (byte*) screen#1 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: - // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4 -- pbuz1=_inc_pbuz1 + // [23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6 -- pbuz1=_inc_pbuz1 inc.z str bne !+ inc.z str+1 !: jmp __b1 +} + // printf_uint +// Print an unsigned int using a specific format +// Always prints hexadecimals - ignores min_length and flags +printf_uint: { + // *screen++ = printf_hextab[(>uvalue)>>4] + // [24] *((byte*) screen#18) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>uvalue)>>4]; + // [25] (byte*) screen#5 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(>uvalue)&0xf] + // [26] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>uvalue)&0xf]; + // [27] (byte*) screen#6 ← ++ (byte*) screen#5 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(>4] + // [28] *((byte*) screen#6) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age>>(byte) 4) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>4) + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>4]; + // [29] (byte*) screen#7 ← ++ (byte*) screen#6 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(printf_str] - // [11] phi (byte*) screen#23 = (byte*) screen#10 [phi:printf_string->printf_str#0] -- register_copy - // [11] phi (byte*) printf_str::str#6 = (const byte*) main::name [phi:printf_string->printf_str#1] -- pbuz1=pbuc1 - lda #printf_str] + // [17] phi (byte*) screen#36 = (byte*) screen#18 [phi:printf_string->printf_str#0] -- register_copy + // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str1 [phi:printf_string->printf_str#1] -- pbuz1=pbuc1 + lda #main.name + lda #>main.str1 sta.z printf_str.str+1 jsr printf_str // printf_string::@return // } - // [20] return + // [35] return rts } // File Data + printf_hextab: .text "0123456789abcdef" diff --git a/src/test/ref/printf-10.sym b/src/test/ref/printf-10.sym index 703ad3ec6..57a088a94 100644 --- a/src/test/ref/printf-10.sym +++ b/src/test/ref/printf-10.sym @@ -1,33 +1,62 @@ (label) @1 (label) @begin (label) @end +(const byte) RADIX::BINARY = (number) 2 +(const byte) RADIX::DECIMAL = (number) $a +(const byte) RADIX::HEXADECIMAL = (number) $10 +(const byte) RADIX::OCTAL = (number) 8 (void()) main() (label) main::@1 (label) main::@2 +(label) main::@3 +(label) main::@4 +(label) main::@5 (label) main::@return -(const byte*) main::name[] = (byte*) "Jesper" +(const word) main::age = (word) $2e (const byte*) main::str[(byte) $d] = (byte*) "Hello, I am " -(const byte*) main::str1[(byte) $f] = (byte*) ". who are you?" +(const byte*) main::str1[(byte) 7] = (byte*) "Jesper" +(const byte*) main::str2[(byte) $f] = (byte*) ". who are you?" +(const byte*) main::str3[(byte) 6] = (byte*) "I am " +(const byte*) main::str4[(byte) $b] = (byte*) " years old" +(byte) printf_format_number::justify_left +(byte) printf_format_number::min_length +(byte) printf_format_number::radix +(byte) printf_format_number::sign_always +(byte) printf_format_number::zero_padding (byte) printf_format_string::justify_left (byte) printf_format_string::min_length +(const to_nomodify byte*) printf_hextab[] = (byte*) "0123456789abcdef"z (void()) printf_str((byte*) printf_str::str) (label) printf_str::@1 (label) printf_str::@2 (label) printf_str::@return (byte*) printf_str::str (byte*) printf_str::str#0 str zp[2]:4 20002.0 -(byte*) printf_str::str#4 str zp[2]:4 10251.25 -(byte*) printf_str::str#6 str zp[2]:4 1001.0 +(byte*) printf_str::str#6 str zp[2]:4 10251.25 +(byte*) printf_str::str#8 str zp[2]:4 1001.0 (void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left) (label) printf_string::@return (struct printf_format_string) printf_string::format (byte) printf_string::format_justify_left (byte) printf_string::format_min_length (byte*) printf_string::str +(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix) +(label) printf_uint::@return +(struct printf_format_number) printf_uint::format +(byte) printf_uint::format_justify_left +(byte) printf_uint::format_min_length +(byte) printf_uint::format_radix +(byte) printf_uint::format_sign_always +(byte) printf_uint::format_zero_padding +(word) printf_uint::uvalue (byte*) screen (byte*) screen#1 screen zp[2]:2 10001.0 -(byte*) screen#10 screen zp[2]:2 2828.7272727272725 -(byte*) screen#23 screen zp[2]:2 1113.0 +(byte*) screen#18 screen zp[2]:2 1958.0625 +(byte*) screen#23 screen zp[2]:2 28.0 +(byte*) screen#36 screen zp[2]:2 1135.0 +(byte*) screen#5 screen zp[2]:2 151.5 +(byte*) screen#6 screen zp[2]:2 151.5 +(byte*) screen#7 screen zp[2]:2 151.5 -zp[2]:2 [ screen#23 screen#10 screen#1 ] -zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] +zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 screen#5 screen#7 screen#6 ] +zp[2]:4 [ printf_str::str#6 printf_str::str#8 printf_str::str#0 ]