diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1PrintfIntrinsicRewrite.java b/src/main/java/dk/camelot64/kickc/passes/Pass1PrintfIntrinsicRewrite.java index 44445f841..268650169 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1PrintfIntrinsicRewrite.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1PrintfIntrinsicRewrite.java @@ -24,10 +24,21 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization { 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 chars. */ + public static final String PRINTF_SCHAR = "printf_schar"; + /** The printf routine used to print unsigned chars. */ + public static final String PRINTF_UCHAR = "printf_uchar"; /** 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"; + /** The printf routine used to print signed long integers. */ + public static final String PRINTF_SLONG = "printf_slong"; + /** The printf routine used to print unsigned long integers. */ + public static final String PRINTF_ULONG = "printf_ulong"; + public static final String DECIMAL = "DECIMAL"; + public static final String HEXADECIMAL = "HEXADECIMAL"; + public static final String OCTAL = "OCTAL"; public Pass1PrintfIntrinsicRewrite(Program program) { super(program); @@ -78,17 +89,13 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization { final String paramField = matcher.group(1); if(paramField != null) throw new CompileError("printf parameter field not supported", printfCall); - 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 @@ -96,7 +103,6 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization { printfConstantString(prefix, printfCall, stmtIt, formatEncoding); formatIdx = end; - if(typeField.equals("s")) { // A formatted string //struct printf_format_string { @@ -116,14 +122,43 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization { // 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; + boolean signed; + switch(typeField) { + case "d": + case "i": + radix = getScope().getLocalConstant(DECIMAL).getRef(); + signed = true; + break; + case "u": + radix = getScope().getLocalConstant(DECIMAL).getRef(); + signed = false; + break; + case "x": + radix = getScope().getLocalConstant(HEXADECIMAL).getRef(); + signed = false; + break; + case "X": + throw new CompileError("printf hexadecimal upper case not supported", printfCall); + case "o": + radix = getScope().getLocalConstant(OCTAL).getRef(); + signed = false; + break; + default: + throw new CompileError("printf type field not supported", printfCall); + } + + if(lengthField == null) { + // Integer (16bit) + printf_number_procedure = signed ? PRINTF_SINT : PRINTF_UINT; + } else if(lengthField.equals("hh")) { + // TODO: Handle 8-bits in a better way - since KickC does not do integer promotion! + // Integer (8bit) + printf_number_procedure = signed ? PRINTF_SCHAR : PRINTF_UCHAR; + } else if(lengthField.equals("l")) { + // Integer (32bit) + printf_number_procedure = signed ? PRINTF_SLONG : PRINTF_ULONG; } else { - throw new CompileError("printf type field not supported", printfCall); + throw new CompileError("printf length field not supported", printfCall); } // Format specifying how to format a printed number diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 16825a862..598d26917 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -41,7 +41,12 @@ public class TestPrograms { } @Test - public void testPintf10() throws IOException, URISyntaxException { + public void testPrintf11() throws IOException, URISyntaxException { + compileAndCompare("printf-11.c"); + } + + @Test + public void testPrintf10() throws IOException, URISyntaxException { compileAndCompare("printf-10.c"); } diff --git a/src/test/kc/printf-10.c b/src/test/kc/printf-10.c index 17ba49714..e125686db 100644 --- a/src/test/kc/printf-10.c +++ b/src/test/kc/printf-10.c @@ -26,37 +26,9 @@ void printf_string(char* str, struct printf_format_string format) { printf_str(str); } -// 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[(uvalue)>>4]; + *screen++ = printf_hextab[(>uvalue)&0xf]; + *screen++ = printf_hextab[(>4]; + *screen++ = printf_hextab[($400 @@ -16,39 +15,21 @@ main: { lda #>str sta.z printf_str.str+1 jsr printf_str - // printf("Hello, I am %s. who are you?", "Jesper") + // printf("Hello, I am %s. who are you?", name) jsr printf_string - // printf("Hello, I am %s. who are you?", "Jesper") - 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 + lda #>str1 sta.z printf_str.str+1 jsr printf_str // } rts + name: .text "Jesper" + .byte 0 str: .text "Hello, I am " .byte 0 - str1: .text "Jesper" - .byte 0 - str2: .text ". who are you?" - .byte 0 - str3: .text "I am " - .byte 0 - str4: .text " years old" + str1: .text ". who are you?" .byte 0 } // printf_str(byte* zp(4) str) @@ -78,58 +59,15 @@ 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.str1 + lda #>main.name 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 5eb99f837..97a96504c 100644 --- a/src/test/ref/printf-10.cfg +++ b/src/test/ref/printf-10.cfg @@ -20,62 +20,35 @@ 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::@5 - [16] return +main::@return: scope:[main] from main::@2 + [10] return to:@return (void()) printf_str((byte*) printf_str::str) -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 ) +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 ) to:printf_str::@1 printf_str::@1: scope:[printf_str] from printf_str 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 + [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 to:printf_str::@return printf_str::@return: scope:[printf_str] from printf_str::@1 - [20] return + [14] return to:@return printf_str::@2: scope:[printf_str] from printf_str::@1 - [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 + [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 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 - [33] phi() - [34] call printf_str + [18] phi() + [19] call printf_str to:printf_string::@return printf_string::@return: scope:[printf_string] from printf_string - [35] return + [20] return to:@return diff --git a/src/test/ref/printf-10.log b/src/test/ref/printf-10.log index 5faaa3b4b..bb6f25fe7 100644 --- a/src/test/ref/printf-10.log +++ b/src/test/ref/printf-10.log @@ -1,198 +1,120 @@ -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 } +Added struct type cast to parameter value list call printf_string (byte*) main::name (struct printf_format_string){ (byte) 0, (byte) 0 } 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 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 +Converted call struct value parameter to member unwinding call printf_string (byte*) main::name (byte) 0 (byte) 0 Warning! Adding boolean cast to non-boolean condition *((byte*) printf_str::str) Identified constant variable (byte) idx -Identified constant variable (word) main::age +Identified constant variable (byte*) main::name 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:@4 + to:@3 (void()) printf_str((byte*) printf_str::str) -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 ) +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 ) to:printf_str::@1 printf_str::@1: scope:[printf_str] from printf_str printf_str::@2 - (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) + (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) 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#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 + (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 to:printf_str::@1 printf_str::@return: scope:[printf_str] from printf_str::@1 - (byte*) screen#19 ← phi( printf_str::@1/(byte*) screen#32 ) - (byte*) screen#2 ← (byte*) screen#19 + (byte*) screen#11 ← phi( printf_str::@1/(byte*) screen#19 ) + (byte*) screen#2 ← (byte*) screen#11 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#33 ← phi( main::@1/(byte*) screen#10 ) + (byte*) screen#20 ← phi( main::@1/(byte*) screen#5 ) (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#20 ← phi( printf_string/(byte*) screen#2 ) - (byte*) screen#3 ← (byte*) screen#20 + (byte*) screen#12 ← phi( printf_string/(byte*) screen#2 ) + (byte*) screen#3 ← (byte*) screen#12 to:printf_string::@return printf_string::@return: scope:[printf_string] from printf_string::@1 - (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 + (byte*) screen#13 ← phi( printf_string::@1/(byte*) screen#3 ) + (byte*) screen#4 ← (byte*) screen#13 return to:@return (void()) main() -main: scope:[main] from @4 - (byte*) screen#34 ← phi( @4/(byte*) screen#35 ) +main: scope:[main] from @3 + (byte*) screen#21 ← phi( @3/(byte*) screen#22 ) (byte*) printf_str::str#2 ← (const byte*) main::str call printf_str to:main::@1 main::@1: scope:[main] from main - (byte*) screen#24 ← phi( main/(byte*) screen#2 ) - (byte*) screen#10 ← (byte*) screen#24 - (byte*) printf_string::str#0 ← (const byte*) main::str1 + (byte*) screen#14 ← phi( main/(byte*) screen#2 ) + (byte*) screen#5 ← (byte*) screen#14 + (byte*) printf_string::str#0 ← (const byte*) main::name (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#25 ← phi( main::@1/(byte*) screen#4 ) - (byte*) screen#11 ← (byte*) screen#25 - (byte*) printf_str::str#3 ← (const byte*) main::str2 + (byte*) screen#15 ← phi( main::@1/(byte*) screen#4 ) + (byte*) screen#6 ← (byte*) screen#15 + (byte*) printf_str::str#3 ← (const byte*) main::str1 call printf_str to:main::@3 main::@3: scope:[main] from main::@2 - (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 + (byte*) screen#16 ← phi( main::@2/(byte*) screen#2 ) + (byte*) screen#7 ← (byte*) screen#16 to:main::@return -main::@return: scope:[main] from main::@6 - (byte*) screen#30 ← phi( main::@6/(byte*) screen#15 ) - (byte*) screen#16 ← (byte*) screen#30 +main::@return: scope:[main] from main::@3 + (byte*) screen#17 ← phi( main::@3/(byte*) screen#7 ) + (byte*) screen#8 ← (byte*) screen#17 return to:@return -@4: scope:[] from @begin - (byte*) screen#35 ← phi( @begin/(byte*) screen#0 ) +@3: scope:[] from @begin + (byte*) screen#22 ← phi( @begin/(byte*) screen#0 ) call main - to:@5 -@5: scope:[] from @4 - (byte*) screen#31 ← phi( @4/(byte*) screen#16 ) - (byte*) screen#17 ← (byte*) screen#31 + to:@4 +@4: scope:[] from @3 + (byte*) screen#18 ← phi( @3/(byte*) screen#8 ) + (byte*) screen#9 ← (byte*) screen#18 to:@end -@end: scope:[] from @5 +@end: scope:[] from @4 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 word) main::age = (word) $2e +(const byte*) main::name = (byte*) "Jesper" (const byte*) main::str[(byte) $d] = (byte*) "Hello, I am " -(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 +(const byte*) main::str1[(byte) $f] = (byte*) ". who are you?" (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 @@ -206,8 +128,6 @@ 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 @@ -219,30 +139,6 @@ 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 @@ -261,20 +157,7 @@ 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 @@ -282,177 +165,86 @@ 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#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 +Adding number conversion cast (unumber) 0 in (bool~) printf_str::$0 ← (number) 0 != *((byte*) printf_str::str#4) 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 -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 +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 Successful SSA optimization Pass2AliasElimination Identical Phi Values (byte*) printf_string::str#1 (byte*) printf_string::str#0 -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 +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 Successful SSA optimization Pass2IdenticalPhiElimination -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 +Simple Condition (bool~) printf_str::$0 [4] if((byte) 0!=*((byte*) printf_str::str#4)) 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::str1 +Constant (const byte*) printf_string::str#0 = main::name 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::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 +Constant (const byte*) printf_str::str#3 = main::str1 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_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_string::str#0 = (const byte*) main::name Constant inlined printf_str::str#2 = (const byte*) main::str -Constant inlined printf_str::str#1 = (const byte*) main::str1 -Constant inlined printf_str::str#4 = (const byte*) main::str3 +Constant inlined printf_str::str#1 = (const byte*) main::name Constant inlined screen#0 = (byte*) 1024 -Constant inlined printf_str::str#3 = (const byte*) main::str2 +Constant inlined printf_str::str#3 = (const byte*) main::str1 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 - [33] phi() - [34] call printf_str + [18] phi() + [19] call printf_str to:printf_string::@return printf_string::@return: scope:[printf_string] from printf_string - [35] return + [20] 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#6 10251.25 -(byte*) printf_str::str#8 1001.0 +(byte*) printf_str::str#4 10251.25 +(byte*) printf_str::str#6 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#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 +(byte*) screen#10 2828.7272727272725 +(byte*) screen#23 1113.0 Initial phi equivalence classes -[ 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 ] +[ screen#23 screen#10 screen#1 ] +[ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] Complete equivalence classes -[ 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 ] +[ 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 ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -604,9 +343,6 @@ 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] @@ -625,16 +361,15 @@ __bend_from___b1: __bend: // main main: { - .label age = $2e // [5] call printf_str - // [17] phi from main to printf_str [phi:main->printf_str] + // [11] phi from main to printf_str [phi:main->printf_str] printf_str_from_main: - // [17] phi (byte*) screen#36 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 + // [11] phi (byte*) screen#23 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 - // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 lda #str @@ -646,7 +381,7 @@ main: { // main::@1 __b1: // [7] call printf_string - // [33] phi from main::@1 to printf_string [phi:main::@1->printf_string] + // [18] 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] @@ -655,81 +390,40 @@ main: { // main::@2 __b2: // [9] call printf_str - // [17] phi from main::@2 to printf_str [phi:main::@2->printf_str] + // [11] phi from main::@2 to printf_str [phi:main::@2->printf_str] printf_str_from___b2: - // [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 #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 #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 + lda #>str1 sta.z printf_str.str+1 jsr printf_str jmp __breturn // main::@return __breturn: - // [16] return + // [10] return rts + name: .text "Jesper" + .byte 0 str: .text "Hello, I am " .byte 0 - str1: .text "Jesper" - .byte 0 - str2: .text ". who are you?" - .byte 0 - str3: .text "I am " - .byte 0 - str4: .text " years old" + str1: .text ". who are you?" .byte 0 } // printf_str // printf_str(byte* zp(4) str) printf_str: { .label str = 4 - // [18] phi from printf_str printf_str::@2 to printf_str::@1 [phi:printf_str/printf_str::@2->printf_str::@1] + // [12] 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: - // [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 + // [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 jmp __b1 // printf_str::@1 __b1: - // [19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + // [13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (str),y cmp #0 @@ -737,146 +431,67 @@ printf_str: { jmp __breturn // printf_str::@return __breturn: - // [20] return + // [14] return rts // printf_str::@2 __b2: - // [21] *((byte*) screen#18) ← *((byte*) printf_str::str#6) -- _deref_pbuz1=_deref_pbuz2 + // [15] *((byte*) screen#10) ← *((byte*) printf_str::str#4) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (str),y ldy #0 sta (screen),y - // [22] (byte*) screen#1 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz1 + // [16] (byte*) screen#1 ← ++ (byte*) screen#10 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: - // [23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6 -- pbuz1=_inc_pbuz1 + // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4 -- 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] + // [19] call printf_str + // [11] phi from printf_string to printf_str [phi:printf_string->printf_str] printf_str_from_printf_string: - // [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 #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 #main.str1 + lda #>main.name sta.z printf_str.str+1 jsr printf_str jmp __breturn // printf_string::@return __breturn: - // [35] return + // [20] return rts } // File Data - printf_hextab: .text "0123456789abcdef" REGISTER UPLIFT POTENTIAL REGISTERS -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 , +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 , REGISTER UPLIFT SCOPES -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_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_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 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 +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 ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -906,16 +521,15 @@ __bend_from___b1: __bend: // main main: { - .label age = $2e // [5] call printf_str - // [17] phi from main to printf_str [phi:main->printf_str] + // [11] phi from main to printf_str [phi:main->printf_str] printf_str_from_main: - // [17] phi (byte*) screen#36 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 + // [11] phi (byte*) screen#23 = (byte*) 1024 [phi:main->printf_str#0] -- pbuz1=pbuc1 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 - // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 lda #str @@ -927,7 +541,7 @@ main: { // main::@1 __b1: // [7] call printf_string - // [33] phi from main::@1 to printf_string [phi:main::@1->printf_string] + // [18] 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] @@ -936,81 +550,40 @@ main: { // main::@2 __b2: // [9] call printf_str - // [17] phi from main::@2 to printf_str [phi:main::@2->printf_str] + // [11] phi from main::@2 to printf_str [phi:main::@2->printf_str] printf_str_from___b2: - // [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 #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 #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 + lda #>str1 sta.z printf_str.str+1 jsr printf_str jmp __breturn // main::@return __breturn: - // [16] return + // [10] return rts + name: .text "Jesper" + .byte 0 str: .text "Hello, I am " .byte 0 - str1: .text "Jesper" - .byte 0 - str2: .text ". who are you?" - .byte 0 - str3: .text "I am " - .byte 0 - str4: .text " years old" + str1: .text ". who are you?" .byte 0 } // printf_str // printf_str(byte* zp(4) str) printf_str: { .label str = 4 - // [18] phi from printf_str printf_str::@2 to printf_str::@1 [phi:printf_str/printf_str::@2->printf_str::@1] + // [12] 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: - // [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 + // [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 jmp __b1 // printf_str::@1 __b1: - // [19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + // [13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (str),y cmp #0 @@ -1018,109 +591,58 @@ printf_str: { jmp __breturn // printf_str::@return __breturn: - // [20] return + // [14] return rts // printf_str::@2 __b2: - // [21] *((byte*) screen#18) ← *((byte*) printf_str::str#6) -- _deref_pbuz1=_deref_pbuz2 + // [15] *((byte*) screen#10) ← *((byte*) printf_str::str#4) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (str),y ldy #0 sta (screen),y - // [22] (byte*) screen#1 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz1 + // [16] (byte*) screen#1 ← ++ (byte*) screen#10 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: - // [23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6 -- pbuz1=_inc_pbuz1 + // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4 -- 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] + // [19] call printf_str + // [11] phi from printf_string to printf_str [phi:printf_string->printf_str] printf_str_from_printf_string: - // [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 #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 #main.str1 + lda #>main.name sta.z printf_str.str+1 jsr printf_str jmp __breturn // printf_string::@return __breturn: - // [35] return + // [20] 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 @@ -1133,11 +655,6 @@ 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 @@ -1145,10 +662,6 @@ 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: @@ -1164,69 +677,40 @@ 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 word) main::age = (word) $2e +(const byte*) main::name = (byte*) "Jesper" (const byte*) main::str[(byte) $d] = (byte*) "Hello, I am " -(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 +(const byte*) main::str1[(byte) $f] = (byte*) ". who are you?" (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#6 str zp[2]:4 10251.25 -(byte*) printf_str::str#8 str zp[2]:4 1001.0 +(byte*) printf_str::str#4 str zp[2]:4 10251.25 +(byte*) printf_str::str#6 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#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 +(byte*) screen#10 screen zp[2]:2 2828.7272727272725 +(byte*) screen#23 screen zp[2]:2 1113.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 ] +zp[2]:2 [ screen#23 screen#10 screen#1 ] +zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] FINAL ASSEMBLER -Score: 757 +Score: 617 // File Comments // Tests printf function call rewriting @@ -1246,16 +730,15 @@ Score: 757 // @end // main main: { - .label age = $2e - // printf("Hello, I am %s. who are you?", "Jesper") + // printf("Hello, I am %s. who are you?", name) // [5] call printf_str - // [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 + // [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 lda #<$400 sta.z screen lda #>$400 sta.z screen+1 - // [17] phi (byte*) printf_str::str#8 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + // [11] phi (byte*) printf_str::str#6 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 lda #str @@ -1263,177 +746,90 @@ 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?", "Jesper") + // printf("Hello, I am %s. who are you?", name) // [7] call printf_string - // [33] phi from main::@1 to printf_string [phi:main::@1->printf_string] + // [18] 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?", "Jesper") + // printf("Hello, I am %s. who are you?", name) // [9] call printf_str - // [17] phi from main::@2 to printf_str [phi:main::@2->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 #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 #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 + lda #>str1 sta.z printf_str.str+1 jsr printf_str // main::@return // } - // [16] return + // [10] return rts + name: .text "Jesper" + .byte 0 str: .text "Hello, I am " .byte 0 - str1: .text "Jesper" - .byte 0 - str2: .text ". who are you?" - .byte 0 - str3: .text "I am " - .byte 0 - str4: .text " years old" + str1: .text ". who are you?" .byte 0 } // printf_str // printf_str(byte* zp(4) str) printf_str: { .label str = 4 - // [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 + // [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 // printf_str::@1 __b1: // while(*str) - // [19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + // [13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 ldy #0 lda (str),y cmp #0 bne __b2 // printf_str::@return // } - // [20] return + // [14] return rts // printf_str::@2 __b2: // *screen++ = *str++ - // [21] *((byte*) screen#18) ← *((byte*) printf_str::str#6) -- _deref_pbuz1=_deref_pbuz2 + // [15] *((byte*) screen#10) ← *((byte*) printf_str::str#4) -- _deref_pbuz1=_deref_pbuz2 ldy #0 lda (str),y sta (screen),y // *screen++ = *str++; - // [22] (byte*) screen#1 ← ++ (byte*) screen#18 -- pbuz1=_inc_pbuz1 + // [16] (byte*) screen#1 ← ++ (byte*) screen#10 -- pbuz1=_inc_pbuz1 inc.z screen bne !+ inc.z screen+1 !: - // [23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6 -- pbuz1=_inc_pbuz1 + // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4 -- 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] - // [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 #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 #main.str1 + lda #>main.name sta.z printf_str.str+1 jsr printf_str // printf_string::@return // } - // [35] return + // [20] 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 57a088a94..e4604c5a5 100644 --- a/src/test/ref/printf-10.sym +++ b/src/test/ref/printf-10.sym @@ -1,62 +1,33 @@ (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 word) main::age = (word) $2e +(const byte*) main::name = (byte*) "Jesper" (const byte*) main::str[(byte) $d] = (byte*) "Hello, I am " -(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 +(const byte*) main::str1[(byte) $f] = (byte*) ". who are you?" (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#6 str zp[2]:4 10251.25 -(byte*) printf_str::str#8 str zp[2]:4 1001.0 +(byte*) printf_str::str#4 str zp[2]:4 10251.25 +(byte*) printf_str::str#6 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#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 +(byte*) screen#10 screen zp[2]:2 2828.7272727272725 +(byte*) screen#23 screen zp[2]:2 1113.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 ] +zp[2]:2 [ screen#23 screen#10 screen#1 ] +zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ] diff --git a/src/test/ref/printf-11.asm b/src/test/ref/printf-11.asm new file mode 100644 index 000000000..a0c4e6854 --- /dev/null +++ b/src/test/ref/printf-11.asm @@ -0,0 +1,103 @@ +// Tests printf function call rewriting +// A simple number - with the printf-sub funtions in the same file. +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .label screen = 4 +main: { + .label pct = $156 + // printf("Commodore is %x cool", pct) + lda #<$400 + sta.z screen + lda #>$400 + sta.z screen+1 + lda #str + sta.z printf_str.str+1 + jsr printf_str + // printf("Commodore is %x cool", pct) + jsr printf_uint + // printf("Commodore is %x cool", pct) + lda #str1 + sta.z printf_str.str+1 + jsr printf_str + // } + rts + str: .text "Commodore is " + .byte 0 + str1: .text " cool" + .byte 0 +} +// printf_str(byte* zp(2) str) +printf_str: { + .label str = 2 + __b1: + // while(*str) + ldy #0 + lda (str),y + cmp #0 + bne __b2 + // } + rts + __b2: + // *screen++ = *str++ + ldy #0 + lda (str),y + sta (screen),y + // *screen++ = *str++; + inc.z screen + bne !+ + inc.z screen+1 + !: + inc.z str + bne !+ + inc.z str+1 + !: + 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+((>main.pct)&$f) + 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[((const word) main::pct&(byte) $f) + [21] (byte*) screen#4 ← ++ (byte*) screen#3 + [22] *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct>>(byte) 4) + [23] (byte*) screen#5 ← ++ (byte*) screen#4 + [24] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct&(byte) $f) + [25] (byte*) screen#16 ← ++ (byte*) screen#5 + to:printf_uint::@return +printf_uint::@return: scope:[printf_uint] from printf_uint + [26] return + to:@return diff --git a/src/test/ref/printf-11.log b/src/test/ref/printf-11.log new file mode 100644 index 000000000..edabd3ee4 --- /dev/null +++ b/src/test/ref/printf-11.log @@ -0,0 +1,1075 @@ +Added struct type cast to parameter value list call printf_uint (word) main::pct (struct printf_format_number){ (byte) 0, (byte) 0, (byte) 0, (byte) 0, (const byte) HEXADECIMAL } +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_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_uint (word) main::pct (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::pct +Eliminating unused variable with no statement (void~) main::$0 +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 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + (byte*) screen#0 ← (byte*)(number) $400 + to:@3 + +(void()) printf_str((byte*) printf_str::str) +printf_str: scope:[printf_str] from main main::@2 + (byte*) screen#25 ← phi( main/(byte*) screen#23 main::@2/(byte*) screen#9 ) + (byte*) printf_str::str#5 ← phi( main/(byte*) printf_str::str#1 main::@2/(byte*) printf_str::str#2 ) + to:printf_str::@1 +printf_str::@1: scope:[printf_str] from printf_str printf_str::@2 + (byte*) screen#22 ← phi( printf_str/(byte*) screen#25 printf_str::@2/(byte*) screen#1 ) + (byte*) printf_str::str#3 ← phi( printf_str/(byte*) printf_str::str#5 printf_str::@2/(byte*) printf_str::str#0 ) + (bool~) printf_str::$0 ← (number) 0 != *((byte*) printf_str::str#3) + 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#13 ← phi( printf_str::@1/(byte*) screen#22 ) + (byte*) printf_str::str#4 ← phi( printf_str::@1/(byte*) printf_str::str#3 ) + *((byte*) screen#13) ← *((byte*) printf_str::str#4) + (byte*) screen#1 ← ++ (byte*) screen#13 + (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4 + to:printf_str::@1 +printf_str::@return: scope:[printf_str] from printf_str::@1 + (byte*) screen#14 ← phi( printf_str::@1/(byte*) screen#22 ) + (byte*) screen#2 ← (byte*) screen#14 + 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::@1 + (byte*) screen#15 ← phi( main::@1/(byte*) screen#8 ) + (word) printf_uint::uvalue#1 ← phi( main::@1/(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#15) ← *((const to_nomodify byte*) printf_hextab + (byte~) printf_uint::$1) + (byte*) screen#3 ← ++ (byte*) screen#15 + (byte~) printf_uint::$2 ← > (word) printf_uint::uvalue#1 + (number~) printf_uint::$3 ← (byte~) printf_uint::$2 & (number) $f + *((byte*) screen#3) ← *((const to_nomodify byte*) printf_hextab + (number~) printf_uint::$3) + (byte*) screen#4 ← ++ (byte*) screen#3 + (byte~) printf_uint::$4 ← < (word) printf_uint::uvalue#1 + (byte~) printf_uint::$5 ← (byte~) printf_uint::$4 >> (number) 4 + *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab + (byte~) printf_uint::$5) + (byte*) screen#5 ← ++ (byte*) screen#4 + (byte~) printf_uint::$6 ← < (word) printf_uint::uvalue#1 + (number~) printf_uint::$7 ← (byte~) printf_uint::$6 & (number) $f + *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab + (number~) printf_uint::$7) + (byte*) screen#6 ← ++ (byte*) screen#5 + to:printf_uint::@return +printf_uint::@return: scope:[printf_uint] from printf_uint + (byte*) screen#16 ← phi( printf_uint/(byte*) screen#6 ) + (byte*) screen#7 ← (byte*) screen#16 + return + to:@return + +(void()) main() +main: scope:[main] from @3 + (byte*) screen#23 ← phi( @3/(byte*) screen#24 ) + (byte*) printf_str::str#1 ← (const byte*) main::str + call printf_str + to:main::@1 +main::@1: scope:[main] from main + (byte*) screen#17 ← phi( main/(byte*) screen#2 ) + (byte*) screen#8 ← (byte*) screen#17 + (word) printf_uint::uvalue#0 ← (const word) main::pct + (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::@2 +main::@2: scope:[main] from main::@1 + (byte*) screen#18 ← phi( main::@1/(byte*) screen#7 ) + (byte*) screen#9 ← (byte*) screen#18 + (byte*) printf_str::str#2 ← (const byte*) main::str1 + call printf_str + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte*) screen#19 ← phi( main::@2/(byte*) screen#2 ) + (byte*) screen#10 ← (byte*) screen#19 + to:main::@return +main::@return: scope:[main] from main::@3 + (byte*) screen#20 ← phi( main::@3/(byte*) screen#10 ) + (byte*) screen#11 ← (byte*) screen#20 + return + to:@return +@3: scope:[] from @begin + (byte*) screen#24 ← phi( @begin/(byte*) screen#0 ) + call main + to:@4 +@4: scope:[] from @3 + (byte*) screen#21 ← phi( @3/(byte*) screen#11 ) + (byte*) screen#12 ← (byte*) screen#21 + to:@end +@end: scope:[] from @4 + +SYMBOL TABLE SSA +(label) @3 +(label) @4 +(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::@return +(const word) main::pct = (word) $156 +(const byte*) main::str[(byte) $e] = (byte*) "Commodore is " +(const byte*) main::str1[(byte) 6] = (byte*) " cool" +(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 +(const to_nomodify byte*) printf_hextab[] = (byte*) "0123456789abcdef"z +(void()) printf_str((byte*) printf_str::str) +(bool~) printf_str::$0 +(label) printf_str::@1 +(label) printf_str::@2 +(label) printf_str::@return +(byte*) printf_str::str +(byte*) printf_str::str#0 +(byte*) printf_str::str#1 +(byte*) printf_str::str#2 +(byte*) printf_str::str#3 +(byte*) printf_str::str#4 +(byte*) printf_str::str#5 +(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 +(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#19 +(byte*) screen#2 +(byte*) screen#20 +(byte*) screen#21 +(byte*) screen#22 +(byte*) screen#23 +(byte*) screen#24 +(byte*) screen#25 +(byte*) screen#3 +(byte*) screen#4 +(byte*) screen#5 +(byte*) screen#6 +(byte*) screen#7 +(byte*) screen#8 +(byte*) screen#9 + +Adding number conversion cast (unumber) 0 in (bool~) printf_str::$0 ← (number) 0 != *((byte*) printf_str::str#3) +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 +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#3 = printf_str::str#4 +Alias screen#13 = screen#22 screen#14 screen#2 +Alias screen#16 = screen#6 screen#7 +Alias screen#17 = screen#8 +Alias screen#18 = screen#9 +Alias screen#10 = screen#19 screen#20 screen#11 +Alias screen#0 = screen#24 +Alias screen#12 = screen#21 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values (word) printf_uint::uvalue#1 (word) printf_uint::uvalue#0 +Identical Phi Values (byte*) screen#15 (byte*) screen#17 +Identical Phi Values (byte*) screen#23 (byte*) screen#0 +Identical Phi Values (byte*) screen#17 (byte*) screen#13 +Identical Phi Values (byte*) screen#18 (byte*) screen#16 +Identical Phi Values (byte*) screen#10 (byte*) screen#13 +Identical Phi Values (byte*) screen#12 (byte*) screen#10 +Successful SSA optimization Pass2IdenticalPhiElimination +Identified duplicate assignment right side [17] (byte~) printf_uint::$2 ← > (word) printf_uint::uvalue#0 +Identified duplicate assignment right side [25] (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#3)) goto printf_str::@2 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant (const byte*) screen#0 = (byte*) 1024 +Constant (const byte*) printf_str::str#1 = main::str +Constant (const word) printf_uint::uvalue#0 = main::pct +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#2 = main::str1 +Successful SSA optimization Pass2ConstantIdentification +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 [7] (byte~) printf_uint::$2 ← > (const word) printf_uint::uvalue#0 +Constant right-side identified [14] (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 = > (byte) 4 +Constant right-side identified [10] (byte~) printf_uint::$3 ← (const byte) printf_uint::$2 & (byte) $f +Constant right-side identified [13] (byte~) printf_uint::$5 ← (const byte) printf_uint::$6 >> (byte) 4 +Constant right-side identified [16] (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 +Successful SSA optimization PassNSimplifyConstantZero +Simplifying expression containing zero printf_hextab in [8] *((byte*) screen#13) ← *((const to_nomodify byte*) printf_hextab + (const byte) printf_uint::$1) +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused constant (const byte) printf_uint::$1 +Successful SSA optimization PassNEliminateUnusedVars +Inlining constant with var siblings (const byte*) printf_str::str#1 +Inlining constant with var siblings (const byte*) printf_str::str#2 +Inlining constant with var siblings (const byte*) screen#0 +Constant inlined printf_uint::$3 = >(const word) main::pct&(byte) $f +Constant inlined printf_uint::uvalue#0 = (const word) main::pct +Constant inlined printf_uint::$2 = >(const word) main::pct +Constant inlined printf_uint::$5 = <(const word) main::pct>>(byte) 4 +Constant inlined printf_uint::$7 = <(const word) main::pct&(byte) $f +Constant inlined printf_uint::$6 = <(const word) main::pct +Constant inlined printf_str::str#2 = (const byte*) main::str1 +Constant inlined printf_str::str#1 = (const byte*) main::str +Constant inlined screen#0 = (byte*) 1024 +Successful SSA optimization Pass2ConstantInlining +Consolidated array index constant in *(printf_hextab+>main::pct&$f) +Consolidated array index constant in *(printf_hextab+>4) +Consolidated array index constant in *(printf_hextab+(const word) main::pct&(byte) $f) + [21] (byte*) screen#4 ← ++ (byte*) screen#3 + [22] *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct>>(byte) 4) + [23] (byte*) screen#5 ← ++ (byte*) screen#4 + [24] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct&(byte) $f) + [25] (byte*) screen#16 ← ++ (byte*) screen#5 + to:printf_uint::@return +printf_uint::@return: scope:[printf_uint] from printf_uint + [26] 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 +(void()) printf_str((byte*) printf_str::str) +(byte*) printf_str::str +(byte*) printf_str::str#0 2002.0 +(byte*) printf_str::str#3 1026.25 +(byte*) printf_str::str#5 101.0 +(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 1001.0 +(byte*) screen#13 472.28571428571433 +(byte*) screen#16 28.0 +(byte*) screen#25 112.0 +(byte*) screen#3 151.5 +(byte*) screen#4 151.5 +(byte*) screen#5 151.5 + +Initial phi equivalence classes +[ printf_str::str#3 printf_str::str#5 printf_str::str#0 ] +[ screen#13 screen#25 screen#16 screen#1 ] +Added variable screen#3 to live range equivalence class [ screen#3 ] +Added variable screen#4 to live range equivalence class [ screen#4 ] +Added variable screen#5 to live range equivalence class [ screen#5 ] +Complete equivalence classes +[ printf_str::str#3 printf_str::str#5 printf_str::str#0 ] +[ screen#13 screen#25 screen#16 screen#1 ] +[ screen#3 ] +[ screen#4 ] +[ screen#5 ] +Allocated zp[2]:2 [ printf_str::str#3 printf_str::str#5 printf_str::str#0 ] +Allocated zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 ] +Allocated zp[2]:6 [ screen#3 ] +Allocated zp[2]:8 [ screen#4 ] +Allocated zp[2]:10 [ screen#5 ] + +INITIAL ASM +Target platform is c64basic / MOS6502X + // File Comments +// Tests printf function call rewriting +// A simple number - with the printf-sub funtions in the same file. + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label screen = 4 + .label screen_1 = 6 + .label screen_2 = 8 + .label screen_3 = $a + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from___b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .label pct = $156 + // [5] call printf_str + // [11] phi from main to printf_str [phi:main->printf_str] + printf_str_from_main: + // [11] phi (byte*) screen#25 = (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#5 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + lda #str + sta.z printf_str.str+1 + jsr printf_str + // [6] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + jmp __b1 + // main::@1 + __b1: + // [7] call printf_uint + jsr printf_uint + // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + __b2_from___b1: + jmp __b2 + // main::@2 + __b2: + // [9] call printf_str + // [11] phi from main::@2 to printf_str [phi:main::@2->printf_str] + printf_str_from___b2: + // [11] phi (byte*) screen#25 = (byte*) screen#16 [phi:main::@2->printf_str#0] -- register_copy + // [11] phi (byte*) printf_str::str#5 = (const byte*) main::str1 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 + lda #str1 + sta.z printf_str.str+1 + jsr printf_str + jmp __breturn + // main::@return + __breturn: + // [10] return + rts + str: .text "Commodore is " + .byte 0 + str1: .text " cool" + .byte 0 +} + // printf_str +// printf_str(byte* zp(2) str) +printf_str: { + .label str = 2 + // [12] 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#13 = (byte*) screen#25 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy + // [12] phi (byte*) printf_str::str#3 = (byte*) printf_str::str#5 [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#3)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + ldy #0 + lda (str),y + cmp #0 + bne __b2 + jmp __breturn + // printf_str::@return + __breturn: + // [14] return + rts + // printf_str::@2 + __b2: + // [15] *((byte*) screen#13) ← *((byte*) printf_str::str#3) -- _deref_pbuz1=_deref_pbuz2 + ldy #0 + lda (str),y + ldy #0 + sta (screen),y + // [16] (byte*) screen#1 ← ++ (byte*) screen#13 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#3 -- 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: { + // [18] *((byte*) screen#13) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen),y + // [19] (byte*) screen#3 ← ++ (byte*) screen#13 -- pbuz1=_inc_pbuz2 + lda.z screen + clc + adc #1 + sta.z screen_1 + lda.z screen+1 + adc #0 + sta.z screen_1+1 + // [20] *((byte*) screen#3) ← *((const to_nomodify byte*) printf_hextab+>(const word) main::pct&(byte) $f) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>main.pct)&$f) + ldy #0 + sta (screen_1),y + // [21] (byte*) screen#4 ← ++ (byte*) screen#3 -- 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 + // [22] *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct>>(byte) 4) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>4) + ldy #0 + sta (screen_2),y + // [23] (byte*) screen#5 ← ++ (byte*) screen#4 -- 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 + // [24] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct&(byte) $f) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+(((const word) main::pct&(byte) $f) [ screen#3 ] ( main:2::printf_uint:7 [ screen#3 ] { } ) always clobbers reg byte a reg byte y +Statement [21] (byte*) screen#4 ← ++ (byte*) screen#3 [ screen#4 ] ( main:2::printf_uint:7 [ screen#4 ] { } ) always clobbers reg byte a +Statement [22] *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct>>(byte) 4) [ screen#4 ] ( main:2::printf_uint:7 [ screen#4 ] { } ) always clobbers reg byte a reg byte y +Statement [23] (byte*) screen#5 ← ++ (byte*) screen#4 [ screen#5 ] ( main:2::printf_uint:7 [ screen#5 ] { } ) always clobbers reg byte a +Statement [24] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct&(byte) $f) [ screen#5 ] ( main:2::printf_uint:7 [ screen#5 ] { } ) always clobbers reg byte a reg byte y +Statement [25] (byte*) screen#16 ← ++ (byte*) screen#5 [ screen#16 ] ( main:2::printf_uint:7 [ screen#16 ] { } ) always clobbers reg byte a +Potential registers zp[2]:2 [ printf_str::str#3 printf_str::str#5 printf_str::str#0 ] : zp[2]:2 , +Potential registers zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 ] : zp[2]:4 , +Potential registers zp[2]:6 [ screen#3 ] : zp[2]:6 , +Potential registers zp[2]:8 [ screen#4 ] : zp[2]:8 , +Potential registers zp[2]:10 [ screen#5 ] : zp[2]:10 , + +REGISTER UPLIFT SCOPES +Uplift Scope [printf_str] 3,129.25: zp[2]:2 [ printf_str::str#3 printf_str::str#5 printf_str::str#0 ] +Uplift Scope [] 1,613.29: zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 ] 151.5: zp[2]:6 [ screen#3 ] 151.5: zp[2]:8 [ screen#4 ] 151.5: zp[2]:10 [ screen#5 ] +Uplift Scope [RADIX] +Uplift Scope [printf_format_number] +Uplift Scope [printf_uint] +Uplift Scope [main] + +Uplifting [printf_str] best 825 combination zp[2]:2 [ printf_str::str#3 printf_str::str#5 printf_str::str#0 ] +Uplifting [] best 825 combination zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 ] zp[2]:6 [ screen#3 ] zp[2]:8 [ screen#4 ] zp[2]:10 [ screen#5 ] +Uplifting [RADIX] best 825 combination +Uplifting [printf_format_number] best 825 combination +Uplifting [printf_uint] best 825 combination +Uplifting [main] best 825 combination +Coalescing zero page register [ zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 ] ] with [ zp[2]:6 [ screen#3 ] ] - score: 1 +Coalescing zero page register [ zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 screen#3 ] ] with [ zp[2]:10 [ screen#5 ] ] - score: 1 +Coalescing zero page register [ zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 screen#3 screen#5 ] ] with [ zp[2]:8 [ screen#4 ] ] - score: 2 + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Tests printf function call rewriting +// A simple number - with the printf-sub funtions in the same file. + // Upstart +.pc = $801 "Basic" +:BasicUpstart(__bbegin) +.pc = $80d "Program" + // Global Constants & labels + .label screen = 4 + // @begin +__bbegin: + // [1] phi from @begin to @1 [phi:@begin->@1] +__b1_from___bbegin: + jmp __b1 + // @1 +__b1: + // [2] call main + // [4] phi from @1 to main [phi:@1->main] +main_from___b1: + jsr main + // [3] phi from @1 to @end [phi:@1->@end] +__bend_from___b1: + jmp __bend + // @end +__bend: + // main +main: { + .label pct = $156 + // [5] call printf_str + // [11] phi from main to printf_str [phi:main->printf_str] + printf_str_from_main: + // [11] phi (byte*) screen#25 = (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#5 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + lda #str + sta.z printf_str.str+1 + jsr printf_str + // [6] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + jmp __b1 + // main::@1 + __b1: + // [7] call printf_uint + jsr printf_uint + // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + __b2_from___b1: + jmp __b2 + // main::@2 + __b2: + // [9] call printf_str + // [11] phi from main::@2 to printf_str [phi:main::@2->printf_str] + printf_str_from___b2: + // [11] phi (byte*) screen#25 = (byte*) screen#16 [phi:main::@2->printf_str#0] -- register_copy + // [11] phi (byte*) printf_str::str#5 = (const byte*) main::str1 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 + lda #str1 + sta.z printf_str.str+1 + jsr printf_str + jmp __breturn + // main::@return + __breturn: + // [10] return + rts + str: .text "Commodore is " + .byte 0 + str1: .text " cool" + .byte 0 +} + // printf_str +// printf_str(byte* zp(2) str) +printf_str: { + .label str = 2 + // [12] 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#13 = (byte*) screen#25 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy + // [12] phi (byte*) printf_str::str#3 = (byte*) printf_str::str#5 [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#3)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + ldy #0 + lda (str),y + cmp #0 + bne __b2 + jmp __breturn + // printf_str::@return + __breturn: + // [14] return + rts + // printf_str::@2 + __b2: + // [15] *((byte*) screen#13) ← *((byte*) printf_str::str#3) -- _deref_pbuz1=_deref_pbuz2 + ldy #0 + lda (str),y + ldy #0 + sta (screen),y + // [16] (byte*) screen#1 ← ++ (byte*) screen#13 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#3 -- 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: { + // [18] *((byte*) screen#13) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen),y + // [19] (byte*) screen#3 ← ++ (byte*) screen#13 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [20] *((byte*) screen#3) ← *((const to_nomodify byte*) printf_hextab+>(const word) main::pct&(byte) $f) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>main.pct)&$f) + ldy #0 + sta (screen),y + // [21] (byte*) screen#4 ← ++ (byte*) screen#3 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [22] *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct>>(byte) 4) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>4) + ldy #0 + sta (screen),y + // [23] (byte*) screen#5 ← ++ (byte*) screen#4 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [24] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct&(byte) $f) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((@1] + // @1 + // [2] call main + // [4] phi from @1 to main [phi:@1->main] + // [3] phi from @1 to @end [phi:@1->@end] + // @end + // main +main: { + .label pct = $156 + // printf("Commodore is %x cool", pct) + // [5] call printf_str + // [11] phi from main to printf_str [phi:main->printf_str] + // [11] phi (byte*) screen#25 = (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#5 = (const byte*) main::str [phi:main->printf_str#1] -- pbuz1=pbuc1 + lda #str + sta.z printf_str.str+1 + jsr printf_str + // [6] phi from main to main::@1 [phi:main->main::@1] + // main::@1 + // printf("Commodore is %x cool", pct) + // [7] call printf_uint + jsr printf_uint + // [8] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + // main::@2 + // printf("Commodore is %x cool", pct) + // [9] call printf_str + // [11] phi from main::@2 to printf_str [phi:main::@2->printf_str] + // [11] phi (byte*) screen#25 = (byte*) screen#16 [phi:main::@2->printf_str#0] -- register_copy + // [11] phi (byte*) printf_str::str#5 = (const byte*) main::str1 [phi:main::@2->printf_str#1] -- pbuz1=pbuc1 + lda #str1 + sta.z printf_str.str+1 + jsr printf_str + // main::@return + // } + // [10] return + rts + str: .text "Commodore is " + .byte 0 + str1: .text " cool" + .byte 0 +} + // printf_str +// printf_str(byte* zp(2) str) +printf_str: { + .label str = 2 + // [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#13 = (byte*) screen#25 [phi:printf_str/printf_str::@2->printf_str::@1#0] -- register_copy + // [12] phi (byte*) printf_str::str#3 = (byte*) printf_str::str#5 [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#3)) goto printf_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 + ldy #0 + lda (str),y + cmp #0 + bne __b2 + // printf_str::@return + // } + // [14] return + rts + // printf_str::@2 + __b2: + // *screen++ = *str++ + // [15] *((byte*) screen#13) ← *((byte*) printf_str::str#3) -- _deref_pbuz1=_deref_pbuz2 + ldy #0 + lda (str),y + sta (screen),y + // *screen++ = *str++; + // [16] (byte*) screen#1 ← ++ (byte*) screen#13 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // [17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#3 -- 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] + // [18] *((byte*) screen#13) ← *((const to_nomodify byte*) printf_hextab) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>uvalue)>>4]; + // [19] (byte*) screen#3 ← ++ (byte*) screen#13 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(>uvalue)&0xf] + // [20] *((byte*) screen#3) ← *((const to_nomodify byte*) printf_hextab+>(const word) main::pct&(byte) $f) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>main.pct)&$f) + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>uvalue)&0xf]; + // [21] (byte*) screen#4 ← ++ (byte*) screen#3 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(>4] + // [22] *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct>>(byte) 4) -- _deref_pbuz1=_deref_pbuc1 + lda printf_hextab+((>4) + ldy #0 + sta (screen),y + // *screen++ = printf_hextab[(>4]; + // [23] (byte*) screen#5 ← ++ (byte*) screen#4 -- pbuz1=_inc_pbuz1 + inc.z screen + bne !+ + inc.z screen+1 + !: + // *screen++ = printf_hextab[(