diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantRef.java b/src/main/java/dk/camelot64/kickc/model/ConstantRef.java index af7cd50dd..49df3f33f 100644 --- a/src/main/java/dk/camelot64/kickc/model/ConstantRef.java +++ b/src/main/java/dk/camelot64/kickc/model/ConstantRef.java @@ -1,17 +1,8 @@ package dk.camelot64.kickc.model; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - /** A reference to a named Constant (in the symbol table) */ public class ConstantRef extends SymbolRef implements ConstantValue { - @JsonCreator - public ConstantRef( - @JsonProperty("fullName") String fullName) { - super(fullName); - } - public ConstantRef(ConstantVar constantVar) { super(constantVar.getFullName()); } diff --git a/src/main/java/dk/camelot64/kickc/model/Program.java b/src/main/java/dk/camelot64/kickc/model/Program.java index f2e191d53..5b577bf66 100644 --- a/src/main/java/dk/camelot64/kickc/model/Program.java +++ b/src/main/java/dk/camelot64/kickc/model/Program.java @@ -13,7 +13,7 @@ public class Program { private List importPaths; /** Imported files. */ private List imported; - /** The initial statement sequence generated byt the parser. */ + /** The initial statement sequence generated by the parser. */ private StatementSequence statementSequence; /** The main scope. */ private ProgramScope scope; diff --git a/src/main/java/dk/camelot64/kickc/model/VariableRef.java b/src/main/java/dk/camelot64/kickc/model/VariableRef.java index 9f63216f9..1852cb444 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableRef.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableRef.java @@ -1,14 +1,9 @@ package dk.camelot64.kickc.model; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - /** A reference to a variable from the symbol table */ public class VariableRef extends SymbolRef implements RValue, LValue { - @JsonCreator - public VariableRef( - @JsonProperty("fullName") String fullName) { + public VariableRef(String fullName) { super(fullName); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java index e221477c2..55fc5951e 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass2ConstantIdentification.java @@ -2,10 +2,7 @@ package dk.camelot64.kickc.passes; import dk.camelot64.kickc.model.*; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Compiler Pass propagating constants in expressions eliminating constant variables @@ -16,29 +13,6 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { super(program); } - static ConstantValue createUnary(Operator operator, ConstantValue c) { - switch(operator.getOperator()) { - case "-": - case "+": - case "++": - case "--": - case "<": - case ">": - case "((byte))": - case "((signed byte))": - case "((sbyte))": - case "((word))": - case "((signed word))": - case "((byte*))": - return new ConstantUnary(operator, c); - case "*": { // pointer dereference - not constant - return null; - } - default: - throw new RuntimeException("Unhandled Unary Operator " + operator.getOperator()); - } - } - /** * Propagate constants, replacing variables with constants where possible. * @@ -49,8 +23,16 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { Map constants = findConstantVariables(); LinkedHashMap constAliases = new LinkedHashMap<>(); // Update symbol table with the constant value - for(VariableRef constRef : constants.keySet()) { + Set constVars = new LinkedHashSet<>(constants.keySet()); + for(VariableRef constRef : constVars) { Variable variable = getProgram().getScope().getVariable(constRef); + + // Weed out all variables that are affected by the address-of operator + if(isAddressOfUsed(constRef)) { + constants.remove(constRef); + continue; + } + ConstantValue constVal = constants.get(constRef); Scope constScope = variable.getScope(); @@ -205,6 +187,29 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { return null; } + static ConstantValue createUnary(Operator operator, ConstantValue c) { + switch(operator.getOperator()) { + case "-": + case "+": + case "++": + case "--": + case "<": + case ">": + case "((byte))": + case "((signed byte))": + case "((sbyte))": + case "((word))": + case "((signed word))": + case "((byte*))": + return new ConstantUnary(operator, c); + case "*": { // pointer dereference - not constant + return null; + } + default: + throw new RuntimeException("Unhandled Unary Operator " + operator.getOperator()); + } + } + ConstantValue createBinary(ConstantValue c1, Operator operator, ConstantValue c2) { switch(operator.getOperator()) { case "-": @@ -236,4 +241,35 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization { } } + + /** + * Determines if the variable is ever operated on by the address-of operator + * @param var tHe variable to examine + * @return true if the address-of operator is used on the variable + */ + private boolean isAddressOfUsed(VariableRef var) { + for(ControlFlowBlock block : getGraph().getAllBlocks()) { + for(Statement statement : block.getStatements()) { + if(statement instanceof StatementAssignment) { + StatementAssignment assignment = (StatementAssignment) statement; + if(Operator.ADDRESS_OF.equals(assignment.getOperator()) && var.equals(assignment.getrValue2())) { + return true; + } + } + } + } + for(ConstantVar constVar : getScope().getAllConstants(true)) { + ConstantValue constantValue = constVar.getValue(); + if(constantValue instanceof ConstantVarPointer) { + ConstantVarPointer constantVarPointer = (ConstantVarPointer) constantValue; + if(constantVarPointer.getToVar().equals(var)) { + return true; + } + } + } + return false; + } + + + } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index d745ddc14..f435bdd80 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -42,6 +42,11 @@ public class TestPrograms { AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false); } + @Test + public void testAddressOfParam() throws IOException, URISyntaxException { + compileAndCompare("test-address-of-param"); + } + @Test public void testAddressOf() throws IOException, URISyntaxException { compileAndCompare("test-address-of"); diff --git a/src/test/java/dk/camelot64/kickc/test/kc/test-address-of-param.kc b/src/test/java/dk/camelot64/kickc/test/kc/test-address-of-param.kc new file mode 100644 index 000000000..7f497b87f --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/kc/test-address-of-param.kc @@ -0,0 +1,18 @@ + +void main() { + byte* SCREEN = $400; + byte b1 = 0; + byte b2 = 0; + byte b3 = 0; + setByte(&b1, 'c'); + setByte(&b2, 'm'); + setByte(&b3, 'l'); + SCREEN[0] = b1; + SCREEN[1] = b2; + SCREEN[2] = b3; +} + +void setByte(byte* ptr, byte b) { + *ptr = b; +} + diff --git a/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.asm b/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.asm new file mode 100644 index 000000000..4609ee55b --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.asm @@ -0,0 +1,46 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + jsr main +main: { + .label SCREEN = $400 + .label b1 = 4 + .label b2 = 5 + .label b3 = 6 + lda #0 + sta b1 + sta b2 + sta b3 + lda #b1 + sta setByte.ptr+1 + ldx #'c' + jsr setByte + lda #b2 + sta setByte.ptr+1 + ldx #'m' + jsr setByte + lda #b3 + sta setByte.ptr+1 + ldx #'l' + jsr setByte + lda b1 + sta SCREEN+0 + lda b2 + sta SCREEN+1 + lda b3 + sta SCREEN+2 + rts +} +setByte: { + .label ptr = 2 + txa + ldy #0 + sta (ptr),y + rts +} diff --git a/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.cfg b/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.cfg new file mode 100644 index 000000000..afef26761 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.cfg @@ -0,0 +1,39 @@ +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@2 +@2: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @2 + [3] phi() [ ] ( ) +main: scope:[main] from @2 + [4] (byte) main::b1#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 ] ( main:2 [ main::b1#0 ] ) + [5] (byte) main::b2#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 ] ( main:2 [ main::b1#0 main::b2#0 ] ) + [6] (byte) main::b3#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + [7] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:main::@1 +main::@1: scope:[main] from main + [8] phi() [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + [9] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:main::@2 +main::@2: scope:[main] from main::@1 + [10] phi() [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + [11] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:main::@3 +main::@3: scope:[main] from main::@2 + [12] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) main::b1#0 [ main::b2#0 main::b3#0 ] ( main:2 [ main::b2#0 main::b3#0 ] ) + [13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::b2#0 [ main::b3#0 ] ( main:2 [ main::b3#0 ] ) + [14] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::b3#0 [ ] ( main:2 [ ] ) + to:main::@return +main::@return: scope:[main] from main::@3 + [15] return [ ] ( main:2 [ ] ) + to:@return +setByte: scope:[setByte] from main main::@1 main::@2 + [16] (byte*) setByte::ptr#3 ← phi( main/&(byte) main::b1#0 main::@1/&(byte) main::b2#0 main::@2/&(byte) main::b3#0 ) [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] ) + [16] (byte) setByte::b#3 ← phi( main/(byte) 'c' main::@1/(byte) 'm' main::@2/(byte) 'l' ) [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] ) + [17] *((byte*) setByte::ptr#3) ← (byte) setByte::b#3 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:setByte::@return +setByte::@return: scope:[setByte] from setByte + [18] return [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:@return diff --git a/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.log b/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.log new file mode 100644 index 000000000..18fb90ea0 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.log @@ -0,0 +1,802 @@ +PARSING src/test/java/dk/camelot64/kickc/test/kc/test-address-of-param.kc + +void main() { + byte* SCREEN = $400; + byte b1 = 0; + byte b2 = 0; + byte b3 = 0; + setByte(&b1, 'c'); + setByte(&b2, 'm'); + setByte(&b3, 'l'); + SCREEN[0] = b1; + SCREEN[1] = b2; + SCREEN[2] = b3; +} + +void setByte(byte* ptr, byte b) { + *ptr = b; +} + + + +STATEMENTS +proc (void()) main() + (byte*) main::SCREEN ← (word/signed word/dword/signed dword) 1024 + (byte) main::b1 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte) main::b2 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte) main::b3 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte*~) main::$0 ← & (byte) main::b1 + (void~) main::$1 ← call setByte (byte*~) main::$0 (byte) 'c' + (byte*~) main::$2 ← & (byte) main::b2 + (void~) main::$3 ← call setByte (byte*~) main::$2 (byte) 'm' + (byte*~) main::$4 ← & (byte) main::b3 + (void~) main::$5 ← call setByte (byte*~) main::$4 (byte) 'l' + *((byte*) main::SCREEN + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) main::b1 + *((byte*) main::SCREEN + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::b2 + *((byte*) main::SCREEN + (byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::b3 +main::@return: + return +endproc // main() +proc (void()) setByte((byte*) setByte::ptr , (byte) setByte::b) + *((byte*) setByte::ptr) ← (byte) setByte::b +setByte::@return: + return +endproc // setByte() + call main + +SYMBOLS +(void()) main() +(byte*~) main::$0 +(void~) main::$1 +(byte*~) main::$2 +(void~) main::$3 +(byte*~) main::$4 +(void~) main::$5 +(label) main::@return +(byte*) main::SCREEN +(byte) main::b1 +(byte) main::b2 +(byte) main::b3 +(void()) setByte((byte*) setByte::ptr , (byte) setByte::b) +(label) setByte::@return +(byte) setByte::b +(byte*) setByte::ptr + +Promoting word/signed word/dword/signed dword to byte* in main::SCREEN ← ((byte*)) 1024 +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + to:@1 +main: scope:[main] from + (byte*) main::SCREEN ← ((byte*)) (word/signed word/dword/signed dword) 1024 + (byte) main::b1 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte) main::b2 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte) main::b3 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte*~) main::$0 ← & (byte) main::b1 + (void~) main::$1 ← call setByte (byte*~) main::$0 (byte) 'c' + (byte*~) main::$2 ← & (byte) main::b2 + (void~) main::$3 ← call setByte (byte*~) main::$2 (byte) 'm' + (byte*~) main::$4 ← & (byte) main::b3 + (void~) main::$5 ← call setByte (byte*~) main::$4 (byte) 'l' + *((byte*) main::SCREEN + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) main::b1 + *((byte*) main::SCREEN + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::b2 + *((byte*) main::SCREEN + (byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::b3 + to:main::@return +main::@return: scope:[main] from main + return + to:@return +@1: scope:[] from @begin + to:@2 +setByte: scope:[setByte] from + *((byte*) setByte::ptr) ← (byte) setByte::b + to:setByte::@return +setByte::@return: scope:[setByte] from setByte + return + to:@return +@2: scope:[] from @1 + call main + to:@end +@end: scope:[] from @2 + +Eliminating unused variable - keeping the call (void~) main::$1 +Eliminating unused variable - keeping the call (void~) main::$3 +Eliminating unused variable - keeping the call (void~) main::$5 +Removing empty block @1 +PROCEDURE MODIFY VARIABLE ANALYSIS + +Completing Phi functions... +Completing Phi functions... +Completing Phi functions... + +CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + to:@2 +main: scope:[main] from @2 + (byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) 1024 + (byte) main::b1#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte) main::b2#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte) main::b3#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + (byte*~) main::$0 ← & (byte) main::b1#0 + (byte*) setByte::ptr#0 ← (byte*~) main::$0 + (byte) setByte::b#0 ← (byte) 'c' + call setByte param-assignment + to:main::@1 +main::@1: scope:[main] from main + (byte*) main::SCREEN#3 ← phi( main/(byte*) main::SCREEN#0 ) + (byte) main::b1#3 ← phi( main/(byte) main::b1#0 ) + (byte) main::b3#3 ← phi( main/(byte) main::b3#0 ) + (byte) main::b2#1 ← phi( main/(byte) main::b2#0 ) + (byte*~) main::$2 ← & (byte) main::b2#1 + (byte*) setByte::ptr#1 ← (byte*~) main::$2 + (byte) setByte::b#1 ← (byte) 'm' + call setByte param-assignment + to:main::@2 +main::@2: scope:[main] from main::@1 + (byte) main::b2#3 ← phi( main::@1/(byte) main::b2#1 ) + (byte*) main::SCREEN#2 ← phi( main::@1/(byte*) main::SCREEN#3 ) + (byte) main::b1#2 ← phi( main::@1/(byte) main::b1#3 ) + (byte) main::b3#1 ← phi( main::@1/(byte) main::b3#3 ) + (byte*~) main::$4 ← & (byte) main::b3#1 + (byte*) setByte::ptr#2 ← (byte*~) main::$4 + (byte) setByte::b#2 ← (byte) 'l' + call setByte param-assignment + to:main::@3 +main::@3: scope:[main] from main::@2 + (byte) main::b3#2 ← phi( main::@2/(byte) main::b3#1 ) + (byte) main::b2#2 ← phi( main::@2/(byte) main::b2#3 ) + (byte*) main::SCREEN#1 ← phi( main::@2/(byte*) main::SCREEN#2 ) + (byte) main::b1#1 ← phi( main::@2/(byte) main::b1#2 ) + *((byte*) main::SCREEN#1 + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) main::b1#1 + *((byte*) main::SCREEN#1 + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::b2#2 + *((byte*) main::SCREEN#1 + (byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::b3#2 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +setByte: scope:[setByte] from main main::@1 main::@2 + (byte*) setByte::ptr#3 ← phi( main/(byte*) setByte::ptr#0 main::@1/(byte*) setByte::ptr#1 main::@2/(byte*) setByte::ptr#2 ) + (byte) setByte::b#3 ← phi( main/(byte) setByte::b#0 main::@1/(byte) setByte::b#1 main::@2/(byte) setByte::b#2 ) + *((byte*) setByte::ptr#3) ← (byte) setByte::b#3 + to:setByte::@return +setByte::@return: scope:[setByte] from setByte + return + to:@return +@2: scope:[] from @begin + call main param-assignment + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +SYMBOL TABLE SSA +(label) @2 +(label) @3 +(label) @begin +(label) @end +(void()) main() +(byte*~) main::$0 +(byte*~) main::$2 +(byte*~) main::$4 +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(byte*) main::SCREEN +(byte*) main::SCREEN#0 +(byte*) main::SCREEN#1 +(byte*) main::SCREEN#2 +(byte*) main::SCREEN#3 +(byte) main::b1 +(byte) main::b1#0 +(byte) main::b1#1 +(byte) main::b1#2 +(byte) main::b1#3 +(byte) main::b2 +(byte) main::b2#0 +(byte) main::b2#1 +(byte) main::b2#2 +(byte) main::b2#3 +(byte) main::b3 +(byte) main::b3#0 +(byte) main::b3#1 +(byte) main::b3#2 +(byte) main::b3#3 +(void()) setByte((byte*) setByte::ptr , (byte) setByte::b) +(label) setByte::@return +(byte) setByte::b +(byte) setByte::b#0 +(byte) setByte::b#1 +(byte) setByte::b#2 +(byte) setByte::b#3 +(byte*) setByte::ptr +(byte*) setByte::ptr#0 +(byte*) setByte::ptr#1 +(byte*) setByte::ptr#2 +(byte*) setByte::ptr#3 + +OPTIMIZING CONTROL FLOW GRAPH +Culled Empty Block (label) @3 +Succesful SSA optimization Pass2CullEmptyBlocks +Not aliassing across scopes: setByte::b#3 setByte::b#0 +Not aliassing across scopes: setByte::ptr#3 setByte::ptr#0 +Alias (byte*) setByte::ptr#0 = (byte*~) main::$0 +Alias (byte) main::b2#0 = (byte) main::b2#1 (byte) main::b2#3 (byte) main::b2#2 +Alias (byte) main::b3#0 = (byte) main::b3#3 (byte) main::b3#1 (byte) main::b3#2 +Alias (byte) main::b1#0 = (byte) main::b1#3 (byte) main::b1#2 (byte) main::b1#1 +Alias (byte*) main::SCREEN#0 = (byte*) main::SCREEN#3 (byte*) main::SCREEN#2 (byte*) main::SCREEN#1 +Alias (byte*) setByte::ptr#1 = (byte*~) main::$2 +Alias (byte*) setByte::ptr#2 = (byte*~) main::$4 +Succesful SSA optimization Pass2AliasElimination +Not aliassing across scopes: setByte::b#3 setByte::b#0 +Not aliassing across scopes: setByte::ptr#3 setByte::ptr#0 +Constant (const byte*) main::SCREEN#0 = ((byte*))1024 +Constant (const byte*) setByte::ptr#0 = &main::b1#0 +Constant (const byte) setByte::b#0 = 'c' +Constant (const byte*) setByte::ptr#1 = &main::b2#0 +Constant (const byte) setByte::b#1 = 'm' +Constant (const byte*) setByte::ptr#2 = &main::b3#0 +Constant (const byte) setByte::b#2 = 'l' +Succesful SSA optimization Pass2ConstantIdentification +Consolidated array index constant in *(main::SCREEN#0+0) +Consolidated array index constant in *(main::SCREEN#0+1) +Consolidated array index constant in *(main::SCREEN#0+2) +Succesful SSA optimization Pass2ConstantAdditionElimination +OPTIMIZING CONTROL FLOW GRAPH +Inlining constant with var siblings (const byte*) setByte::ptr#0 +Inlining constant with different constant siblings (const byte*) setByte::ptr#0 +Inlining constant with different constant siblings (const byte*) setByte::ptr#0 +Inlining constant with var siblings (const byte) setByte::b#0 +Inlining constant with different constant siblings (const byte) setByte::b#0 +Inlining constant with different constant siblings (const byte) setByte::b#0 +Inlining constant with var siblings (const byte*) setByte::ptr#1 +Inlining constant with different constant siblings (const byte*) setByte::ptr#1 +Inlining constant with different constant siblings (const byte*) setByte::ptr#1 +Inlining constant with var siblings (const byte) setByte::b#1 +Inlining constant with different constant siblings (const byte) setByte::b#1 +Inlining constant with different constant siblings (const byte) setByte::b#1 +Inlining constant with var siblings (const byte*) setByte::ptr#2 +Inlining constant with different constant siblings (const byte*) setByte::ptr#2 +Inlining constant with different constant siblings (const byte*) setByte::ptr#2 +Inlining constant with var siblings (const byte) setByte::b#2 +Inlining constant with different constant siblings (const byte) setByte::b#2 +Inlining constant with different constant siblings (const byte) setByte::b#2 +Constant inlined setByte::ptr#1 = &(byte) main::b2#0 +Constant inlined setByte::ptr#2 = &(byte) main::b3#0 +Constant inlined setByte::ptr#0 = &(byte) main::b1#0 +Constant inlined setByte::b#2 = (byte) 'l' +Constant inlined setByte::b#1 = (byte) 'm' +Constant inlined setByte::b#0 = (byte) 'c' +Succesful SSA optimization Pass2ConstantInlining +Block Sequence Planned @begin @2 @end main main::@1 main::@2 main::@3 main::@return setByte setByte::@return +Block Sequence Planned @begin @2 @end main main::@1 main::@2 main::@3 main::@return setByte setByte::@return +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main::@1 +Adding NOP phi() at start of main::@2 +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to setByte:7 setByte:9 setByte:11 + +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Created 2 initial phi equivalence classes +Coalesced down to 2 phi equivalence classes +Block Sequence Planned @begin @2 @end main main::@1 main::@2 main::@3 main::@return setByte setByte::@return +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @2 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main::@1 +Adding NOP phi() at start of main::@2 +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@2 +@2: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main param-assignment [ ] ( ) + to:@end +@end: scope:[] from @2 + [3] phi() [ ] ( ) +main: scope:[main] from @2 + [4] (byte) main::b1#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 ] ( main:2 [ main::b1#0 ] ) + [5] (byte) main::b2#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 ] ( main:2 [ main::b1#0 main::b2#0 ] ) + [6] (byte) main::b3#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + [7] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:main::@1 +main::@1: scope:[main] from main + [8] phi() [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + [9] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:main::@2 +main::@2: scope:[main] from main::@1 + [10] phi() [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + [11] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:main::@3 +main::@3: scope:[main] from main::@2 + [12] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) main::b1#0 [ main::b2#0 main::b3#0 ] ( main:2 [ main::b2#0 main::b3#0 ] ) + [13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::b2#0 [ main::b3#0 ] ( main:2 [ main::b3#0 ] ) + [14] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::b3#0 [ ] ( main:2 [ ] ) + to:main::@return +main::@return: scope:[main] from main::@3 + [15] return [ ] ( main:2 [ ] ) + to:@return +setByte: scope:[setByte] from main main::@1 main::@2 + [16] (byte*) setByte::ptr#3 ← phi( main/&(byte) main::b1#0 main::@1/&(byte) main::b2#0 main::@2/&(byte) main::b3#0 ) [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] ) + [16] (byte) setByte::b#3 ← phi( main/(byte) 'c' main::@1/(byte) 'm' main::@2/(byte) 'l' ) [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 setByte::b#3 setByte::ptr#3 ] ) + [17] *((byte*) setByte::ptr#3) ← (byte) setByte::b#3 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:setByte::@return +setByte::@return: scope:[setByte] from setByte + [18] return [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) + to:@return + +DOMINATORS +@begin dominated by @begin +@2 dominated by @2 @begin +@end dominated by @2 @begin @end +main dominated by @2 @begin main +main::@1 dominated by @2 @begin main::@1 main +main::@2 dominated by @2 @begin main::@1 main::@2 main +main::@3 dominated by @2 @begin main::@1 main::@2 main main::@3 +main::@return dominated by main::@return @2 @begin main::@1 main::@2 main main::@3 +setByte dominated by @2 setByte @begin main +setByte::@return dominated by @2 setByte @begin setByte::@return main + +NATURAL LOOPS + +NATURAL LOOPS WITH DEPTH +Found 0 loops in scope [] +Found 0 loops in scope [main] +Found 0 loops in scope [setByte] + + +VARIABLE REGISTER WEIGHTS +(void()) main() +(byte*) main::SCREEN +(byte) main::b1 +(byte) main::b1#0 0.36363636363636365 +(byte) main::b2 +(byte) main::b2#0 0.36363636363636365 +(byte) main::b3 +(byte) main::b3#0 0.36363636363636365 +(void()) setByte((byte*) setByte::ptr , (byte) setByte::b) +(byte) setByte::b +(byte) setByte::b#3 2.0 +(byte*) setByte::ptr +(byte*) setByte::ptr#3 2.0 + +Initial phi equivalence classes +[ setByte::b#3 ] +[ setByte::ptr#3 ] +Added variable main::b1#0 to zero page equivalence class [ main::b1#0 ] +Added variable main::b2#0 to zero page equivalence class [ main::b2#0 ] +Added variable main::b3#0 to zero page equivalence class [ main::b3#0 ] +Complete equivalence classes +[ setByte::b#3 ] +[ setByte::ptr#3 ] +[ main::b1#0 ] +[ main::b2#0 ] +[ main::b3#0 ] +Allocated zp ZP_BYTE:2 [ setByte::b#3 ] +Allocated zp ZP_WORD:3 [ setByte::ptr#3 ] +Allocated zp ZP_BYTE:5 [ main::b1#0 ] +Allocated zp ZP_BYTE:6 [ main::b2#0 ] +Allocated zp ZP_BYTE:7 [ main::b3#0 ] + +INITIAL ASM +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +b2_from_bbegin: + jmp b2 +//SEG4 @2 +b2: +//SEG5 [2] call main param-assignment [ ] ( ) + jsr main +//SEG6 [3] phi from @2 to @end [phi:@2->@end] +bend_from_b2: + jmp bend +//SEG7 @end +bend: +//SEG8 main +main: { + .label SCREEN = $400 + .label b1 = 5 + .label b2 = 6 + .label b3 = 7 + //SEG9 [4] (byte) main::b1#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 ] ( main:2 [ main::b1#0 ] ) -- vbuz1=vbuc1 + lda #0 + sta b1 + //SEG10 [5] (byte) main::b2#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 ] ( main:2 [ main::b1#0 main::b2#0 ] ) -- vbuz1=vbuc1 + lda #0 + sta b2 + //SEG11 [6] (byte) main::b3#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) -- vbuz1=vbuc1 + lda #0 + sta b3 + //SEG12 [7] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG13 [16] phi from main to setByte [phi:main->setByte] + setByte_from_main: + //SEG14 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b1#0 [phi:main->setByte#0] -- pbuz1=pbuc1 + lda #b1 + sta setByte.ptr+1 + //SEG15 [16] phi (byte) setByte::b#3 = (byte) 'c' [phi:main->setByte#1] -- vbuz1=vbuc1 + lda #'c' + sta setByte.b + jsr setByte + //SEG16 [8] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + jmp b1 + //SEG17 main::@1 + b1: + //SEG18 [9] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG19 [16] phi from main::@1 to setByte [phi:main::@1->setByte] + setByte_from_b1: + //SEG20 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b2#0 [phi:main::@1->setByte#0] -- pbuz1=pbuc1 + lda #b2 + sta setByte.ptr+1 + //SEG21 [16] phi (byte) setByte::b#3 = (byte) 'm' [phi:main::@1->setByte#1] -- vbuz1=vbuc1 + lda #'m' + sta setByte.b + jsr setByte + //SEG22 [10] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG23 main::@2 + b2: + //SEG24 [11] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG25 [16] phi from main::@2 to setByte [phi:main::@2->setByte] + setByte_from_b2: + //SEG26 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b3#0 [phi:main::@2->setByte#0] -- pbuz1=pbuc1 + lda #b3 + sta setByte.ptr+1 + //SEG27 [16] phi (byte) setByte::b#3 = (byte) 'l' [phi:main::@2->setByte#1] -- vbuz1=vbuc1 + lda #'l' + sta setByte.b + jsr setByte + jmp b3 + //SEG28 main::@3 + b3: + //SEG29 [12] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) main::b1#0 [ main::b2#0 main::b3#0 ] ( main:2 [ main::b2#0 main::b3#0 ] ) -- _deref_pbuc1=vbuz1 + lda b1 + sta SCREEN+0 + //SEG30 [13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::b2#0 [ main::b3#0 ] ( main:2 [ main::b3#0 ] ) -- _deref_pbuc1=vbuz1 + lda b2 + sta SCREEN+1 + //SEG31 [14] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::b3#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuz1 + lda b3 + sta SCREEN+2 + jmp breturn + //SEG32 main::@return + breturn: + //SEG33 [15] return [ ] ( main:2 [ ] ) + rts +} +//SEG34 setByte +setByte: { + .label b = 2 + .label ptr = 3 + //SEG35 [17] *((byte*) setByte::ptr#3) ← (byte) setByte::b#3 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) -- _deref_pbuz1=vbuz2 + lda b + ldy #0 + sta (ptr),y + jmp breturn + //SEG36 setByte::@return + breturn: + //SEG37 [18] return [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) + rts +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [17] *((byte*) setByte::ptr#3) ← (byte) setByte::b#3 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) always clobbers reg byte y +Removing always clobbered register reg byte y as potential for zp ZP_BYTE:5 [ main::b1#0 ] +Removing always clobbered register reg byte y as potential for zp ZP_BYTE:6 [ main::b2#0 ] +Removing always clobbered register reg byte y as potential for zp ZP_BYTE:7 [ main::b3#0 ] +Statement [17] *((byte*) setByte::ptr#3) ← (byte) setByte::b#3 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) always clobbers reg byte y +Potential registers zp ZP_BYTE:2 [ setByte::b#3 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_WORD:3 [ setByte::ptr#3 ] : zp ZP_WORD:3 , +Potential registers zp ZP_BYTE:5 [ main::b1#0 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , +Potential registers zp ZP_BYTE:6 [ main::b2#0 ] : zp ZP_BYTE:6 , reg byte a , reg byte x , +Potential registers zp ZP_BYTE:7 [ main::b3#0 ] : zp ZP_BYTE:7 , reg byte a , reg byte x , + +REGISTER UPLIFT SCOPES +Uplift Scope [setByte] 2: zp ZP_BYTE:2 [ setByte::b#3 ] 2: zp ZP_WORD:3 [ setByte::ptr#3 ] +Uplift Scope [main] 0.36: zp ZP_BYTE:5 [ main::b1#0 ] 0.36: zp ZP_BYTE:6 [ main::b2#0 ] 0.36: zp ZP_BYTE:7 [ main::b3#0 ] +Uplift Scope [] + +Uplifting [setByte] best 139 combination reg byte x [ setByte::b#3 ] zp ZP_WORD:3 [ setByte::ptr#3 ] +Uplifting [main] best 139 combination zp ZP_BYTE:5 [ main::b1#0 ] zp ZP_BYTE:6 [ main::b2#0 ] zp ZP_BYTE:7 [ main::b3#0 ] +Uplifting [] best 139 combination +Attempting to uplift remaining variables inzp ZP_BYTE:5 [ main::b1#0 ] +Uplifting [main] best 139 combination zp ZP_BYTE:5 [ main::b1#0 ] +Attempting to uplift remaining variables inzp ZP_BYTE:6 [ main::b2#0 ] +Uplifting [main] best 139 combination zp ZP_BYTE:6 [ main::b2#0 ] +Attempting to uplift remaining variables inzp ZP_BYTE:7 [ main::b3#0 ] +Uplifting [main] best 139 combination zp ZP_BYTE:7 [ main::b3#0 ] +Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ setByte::ptr#3 ] +Allocated (was zp ZP_BYTE:5) zp ZP_BYTE:4 [ main::b1#0 ] +Allocated (was zp ZP_BYTE:6) zp ZP_BYTE:5 [ main::b2#0 ] +Allocated (was zp ZP_BYTE:7) zp ZP_BYTE:6 [ main::b3#0 ] + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +b2_from_bbegin: + jmp b2 +//SEG4 @2 +b2: +//SEG5 [2] call main param-assignment [ ] ( ) + jsr main +//SEG6 [3] phi from @2 to @end [phi:@2->@end] +bend_from_b2: + jmp bend +//SEG7 @end +bend: +//SEG8 main +main: { + .label SCREEN = $400 + .label b1 = 4 + .label b2 = 5 + .label b3 = 6 + //SEG9 [4] (byte) main::b1#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 ] ( main:2 [ main::b1#0 ] ) -- vbuz1=vbuc1 + lda #0 + sta b1 + //SEG10 [5] (byte) main::b2#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 ] ( main:2 [ main::b1#0 main::b2#0 ] ) -- vbuz1=vbuc1 + lda #0 + sta b2 + //SEG11 [6] (byte) main::b3#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) -- vbuz1=vbuc1 + lda #0 + sta b3 + //SEG12 [7] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG13 [16] phi from main to setByte [phi:main->setByte] + setByte_from_main: + //SEG14 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b1#0 [phi:main->setByte#0] -- pbuz1=pbuc1 + lda #b1 + sta setByte.ptr+1 + //SEG15 [16] phi (byte) setByte::b#3 = (byte) 'c' [phi:main->setByte#1] -- vbuxx=vbuc1 + ldx #'c' + jsr setByte + //SEG16 [8] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + jmp b1 + //SEG17 main::@1 + b1: + //SEG18 [9] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG19 [16] phi from main::@1 to setByte [phi:main::@1->setByte] + setByte_from_b1: + //SEG20 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b2#0 [phi:main::@1->setByte#0] -- pbuz1=pbuc1 + lda #b2 + sta setByte.ptr+1 + //SEG21 [16] phi (byte) setByte::b#3 = (byte) 'm' [phi:main::@1->setByte#1] -- vbuxx=vbuc1 + ldx #'m' + jsr setByte + //SEG22 [10] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + b2_from_b1: + jmp b2 + //SEG23 main::@2 + b2: + //SEG24 [11] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG25 [16] phi from main::@2 to setByte [phi:main::@2->setByte] + setByte_from_b2: + //SEG26 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b3#0 [phi:main::@2->setByte#0] -- pbuz1=pbuc1 + lda #b3 + sta setByte.ptr+1 + //SEG27 [16] phi (byte) setByte::b#3 = (byte) 'l' [phi:main::@2->setByte#1] -- vbuxx=vbuc1 + ldx #'l' + jsr setByte + jmp b3 + //SEG28 main::@3 + b3: + //SEG29 [12] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) main::b1#0 [ main::b2#0 main::b3#0 ] ( main:2 [ main::b2#0 main::b3#0 ] ) -- _deref_pbuc1=vbuz1 + lda b1 + sta SCREEN+0 + //SEG30 [13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::b2#0 [ main::b3#0 ] ( main:2 [ main::b3#0 ] ) -- _deref_pbuc1=vbuz1 + lda b2 + sta SCREEN+1 + //SEG31 [14] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::b3#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuz1 + lda b3 + sta SCREEN+2 + jmp breturn + //SEG32 main::@return + breturn: + //SEG33 [15] return [ ] ( main:2 [ ] ) + rts +} +//SEG34 setByte +setByte: { + .label ptr = 2 + //SEG35 [17] *((byte*) setByte::ptr#3) ← (byte) setByte::b#3 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) -- _deref_pbuz1=vbuxx + txa + ldy #0 + sta (ptr),y + jmp breturn + //SEG36 setByte::@return + breturn: + //SEG37 [18] return [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) + rts +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b2 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Removing instruction jmp breturn +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #0 +Removing instruction lda #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Removing instruction bbegin: +Removing instruction b2_from_bbegin: +Removing instruction bend_from_b2: +Removing instruction b1_from_main: +Removing instruction setByte_from_b1: +Removing instruction b2_from_b1: +Removing instruction setByte_from_b2: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction b2: +Removing instruction bend: +Removing instruction setByte_from_main: +Removing instruction b1: +Removing instruction b2: +Removing instruction b3: +Removing instruction breturn: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @2 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(byte*) main::SCREEN +(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024 +(byte) main::b1 +(byte) main::b1#0 b1 zp ZP_BYTE:4 0.36363636363636365 +(byte) main::b2 +(byte) main::b2#0 b2 zp ZP_BYTE:5 0.36363636363636365 +(byte) main::b3 +(byte) main::b3#0 b3 zp ZP_BYTE:6 0.36363636363636365 +(void()) setByte((byte*) setByte::ptr , (byte) setByte::b) +(label) setByte::@return +(byte) setByte::b +(byte) setByte::b#3 reg byte x 2.0 +(byte*) setByte::ptr +(byte*) setByte::ptr#3 ptr zp ZP_WORD:2 2.0 + +reg byte x [ setByte::b#3 ] +zp ZP_WORD:2 [ setByte::ptr#3 ] +zp ZP_BYTE:4 [ main::b1#0 ] +zp ZP_BYTE:5 [ main::b2#0 ] +zp ZP_BYTE:6 [ main::b3#0 ] + + +FINAL ASSEMBLER +Score: 114 + +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +//SEG4 @2 +//SEG5 [2] call main param-assignment [ ] ( ) + jsr main +//SEG6 [3] phi from @2 to @end [phi:@2->@end] +//SEG7 @end +//SEG8 main +main: { + .label SCREEN = $400 + .label b1 = 4 + .label b2 = 5 + .label b3 = 6 + //SEG9 [4] (byte) main::b1#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 ] ( main:2 [ main::b1#0 ] ) -- vbuz1=vbuc1 + lda #0 + sta b1 + //SEG10 [5] (byte) main::b2#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 ] ( main:2 [ main::b1#0 main::b2#0 ] ) -- vbuz1=vbuc1 + sta b2 + //SEG11 [6] (byte) main::b3#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) -- vbuz1=vbuc1 + sta b3 + //SEG12 [7] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG13 [16] phi from main to setByte [phi:main->setByte] + //SEG14 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b1#0 [phi:main->setByte#0] -- pbuz1=pbuc1 + lda #b1 + sta setByte.ptr+1 + //SEG15 [16] phi (byte) setByte::b#3 = (byte) 'c' [phi:main->setByte#1] -- vbuxx=vbuc1 + ldx #'c' + jsr setByte + //SEG16 [8] phi from main to main::@1 [phi:main->main::@1] + //SEG17 main::@1 + //SEG18 [9] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG19 [16] phi from main::@1 to setByte [phi:main::@1->setByte] + //SEG20 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b2#0 [phi:main::@1->setByte#0] -- pbuz1=pbuc1 + lda #b2 + sta setByte.ptr+1 + //SEG21 [16] phi (byte) setByte::b#3 = (byte) 'm' [phi:main::@1->setByte#1] -- vbuxx=vbuc1 + ldx #'m' + jsr setByte + //SEG22 [10] phi from main::@1 to main::@2 [phi:main::@1->main::@2] + //SEG23 main::@2 + //SEG24 [11] call setByte param-assignment [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2 [ main::b1#0 main::b2#0 main::b3#0 ] ) + //SEG25 [16] phi from main::@2 to setByte [phi:main::@2->setByte] + //SEG26 [16] phi (byte*) setByte::ptr#3 = &(byte) main::b3#0 [phi:main::@2->setByte#0] -- pbuz1=pbuc1 + lda #b3 + sta setByte.ptr+1 + //SEG27 [16] phi (byte) setByte::b#3 = (byte) 'l' [phi:main::@2->setByte#1] -- vbuxx=vbuc1 + ldx #'l' + jsr setByte + //SEG28 main::@3 + //SEG29 [12] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte) main::b1#0 [ main::b2#0 main::b3#0 ] ( main:2 [ main::b2#0 main::b3#0 ] ) -- _deref_pbuc1=vbuz1 + lda b1 + sta SCREEN+0 + //SEG30 [13] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) main::b2#0 [ main::b3#0 ] ( main:2 [ main::b3#0 ] ) -- _deref_pbuc1=vbuz1 + lda b2 + sta SCREEN+1 + //SEG31 [14] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 2) ← (byte) main::b3#0 [ ] ( main:2 [ ] ) -- _deref_pbuc1=vbuz1 + lda b3 + sta SCREEN+2 + //SEG32 main::@return + //SEG33 [15] return [ ] ( main:2 [ ] ) + rts +} +//SEG34 setByte +setByte: { + .label ptr = 2 + //SEG35 [17] *((byte*) setByte::ptr#3) ← (byte) setByte::b#3 [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) -- _deref_pbuz1=vbuxx + txa + ldy #0 + sta (ptr),y + //SEG36 setByte::@return + //SEG37 [18] return [ main::b1#0 main::b2#0 main::b3#0 ] ( main:2::setByte:7 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:9 [ main::b1#0 main::b2#0 main::b3#0 ] main:2::setByte:11 [ main::b1#0 main::b2#0 main::b3#0 ] ) + rts +} + diff --git a/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.sym b/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.sym new file mode 100644 index 000000000..93f7b5853 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/test-address-of-param.sym @@ -0,0 +1,28 @@ +(label) @2 +(label) @begin +(label) @end +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(byte*) main::SCREEN +(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) 1024 +(byte) main::b1 +(byte) main::b1#0 b1 zp ZP_BYTE:4 0.36363636363636365 +(byte) main::b2 +(byte) main::b2#0 b2 zp ZP_BYTE:5 0.36363636363636365 +(byte) main::b3 +(byte) main::b3#0 b3 zp ZP_BYTE:6 0.36363636363636365 +(void()) setByte((byte*) setByte::ptr , (byte) setByte::b) +(label) setByte::@return +(byte) setByte::b +(byte) setByte::b#3 reg byte x 2.0 +(byte*) setByte::ptr +(byte*) setByte::ptr#3 ptr zp ZP_WORD:2 2.0 + +reg byte x [ setByte::b#3 ] +zp ZP_WORD:2 [ setByte::ptr#3 ] +zp ZP_BYTE:4 [ main::b1#0 ] +zp ZP_BYTE:5 [ main::b2#0 ] +zp ZP_BYTE:6 [ main::b3#0 ]