diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java index 3b643b110..9b0362173 100644 --- a/src/main/java/dk/camelot64/kickc/Compiler.java +++ b/src/main/java/dk/camelot64/kickc/Compiler.java @@ -151,7 +151,6 @@ public class Compiler { new Pass1GenerateControlFlowGraph(program).execute(); new Pass1ResolveForwardReferences(program).execute(); new Pass1UnwindBlockScopes(program).execute(); - new Pass1TypeInference(program).execute(); if(getLog().isVerbosePass1CreateSsa()) { @@ -375,6 +374,7 @@ public class Compiler { // Phi mem coalesce removes as many variables introduced by phi lifting as possible - as long as their live ranges do not overlap new Pass3PhiMemCoalesce(program).step(); new Pass2CullEmptyBlocks(program).step(); + new PassNRenumberLabels(program).execute(); new PassNBlockSequencePlanner(program).step(); new Pass3AddNopBeforeCallOns(program).generate(); new PassNStatementIndices(program).execute(); diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesisRule.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesisRule.java index bc81b00ce..ffe8075a8 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesisRule.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplateSynthesisRule.java @@ -476,18 +476,26 @@ class AsmFragmentTemplateSynthesisRule { // Rewrite (Z1),y to AA synths.add(new AsmFragmentTemplateSynthesisRule("(.*)pb(.)z1_derefidx_vbuyy(.*)_then_(.*)", twoZ1+"|"+rvalAa, "lda ({z1}),y\n" , "$1vb$2aa$3_then_$4", null, mapZ)); - // Rewrite (Z1),y to save and reload YY from $FF - synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuyy=(.*)", twoZ1, "sty $ff\n" , "vb$1aa=$2", "ldy $ff\nsta ({z1}),y", mapZ)); + // Rewrite left-size (Z1),y to use AA and a STA (Z1),y + synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuyy=(.*)", twoC1, null, "vb$1aa=$2", "sta {c1},y", mapC, "yy")); + synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuyy=(.*c1.*)", null, null, "vb$1aa=$2", "sta {c1},y", null, "yy")); // Rewrite C1,y to save and reload YY from $FF synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuyy=(.*)", twoC1, "sty $ff\n" , "vb$1aa=$2", "ldy $ff\nsta {c1},y", mapC)); - synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx=(.*)", twoC1, "stx $ff\n" , "vb$1aa=$2", "ldx $ff\nsta {c1},x", mapC)); + // Rewrite (Z1),y to save and reload YY from $FF + synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuyy=(.*)", twoZ1, "sty $ff\n" , "vb$1aa=$2", "ldy $ff\nsta ({z1}),y", mapZ)); - // Rewrite (Z1),a to save A to $FF and reload it into YY - synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuaa=(.*)", twoZ1, "sta $ff" , "vb$1aa=$2", "ldy $ff\nsta ({z1}),y", mapZ)); - // Rewrite (Z1),x to save A to $FF and reload it into YY + // Rewrite left-size (Z1),x to use AA and a STA (Z1),x + synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx=(.*)", twoC1, null, "vb$1aa=$2", "sta {c1},x", mapC, "xx")); + synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx=(.*c1.*)", null, null, "vb$1aa=$2", "sta {c1},x", null, "xx")); + // Rewrite C1,x to save and reload XX from $FF + synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx=(.*)", twoC1, "stx $ff\n" , "vb$1aa=$2", "ldx $ff\nsta {c1},x", mapC)); + // Rewrite (Z1),x to save Y to $FF and reload it into YY synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuxx=(.*)", twoZ1, "stx $ff" , "vb$1aa=$2", "ldy $ff\nsta ({z1}),y", mapZ)); + // Rewrite (Z1),a to use TAY prefix synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuaa=(.*)", twoZ1+"|"+rvalYy, "tay" , "vb$1aa=$2", "sta ({z1}),y", mapZ, "yy")); + // Rewrite (Z1),a to save A to $FF and reload it into YY + synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuaa=(.*)", twoZ1, "sta $ff" , "vb$1aa=$2", "ldy $ff\nsta ({z1}),y", mapZ)); /* Removed awaiting optimization // Rewrite any zeropage pointer as an unsigned word zeropage values @@ -518,8 +526,6 @@ class AsmFragmentTemplateSynthesisRule { // OLD STYLE REWRITES - written when only one rule could be taken synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuz1=(.*)", twoZ1+"|"+twoC1, null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x", mapZC)); - synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuyy=(.*)", twoC1, null, "vb$1aa=$2", "sta {c1},y", mapC, "yy")); - synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)c1_derefidx_vbuxx=(.*)", twoC1, null, "vb$1aa=$2", "sta {c1},x", mapC, "xx")); synths.add(new AsmFragmentTemplateSynthesisRule("pb(.)z1_derefidx_vbuz2=(.*)", twoZ1+"|"+twoZ2, null, "vb$1aa=$2", "ldy {z2}\n" + "sta ({z1}),y", mapZ2)); // Convert array indexing with A register to X/Y register by prefixing tax/tay (..._derefidx_vbuaa... -> ..._derefidx_vbuxx... /... _derefidx_vbuyy... ) diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java index bbadebdd5..a6499b3d9 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValue.java @@ -634,6 +634,26 @@ public abstract class ProgramValue { } } + public static class PhiValuePredecessor extends ProgramValue { + private final StatementPhiBlock.PhiVariable phiVariable; + private final int i; + + PhiValuePredecessor(StatementPhiBlock.PhiVariable phiVariable, int i) { + this.phiVariable = phiVariable; + this.i = i; + } + + @Override + public Value get() { + return phiVariable.getValues().get(i).getPredecessor(); + } + + @Override + public void set(Value value) { + phiVariable.getValues().get(i).setPredecessor((LabelRef) value); + } + } + /** * LValue as part of an assignment statement (or a call). */ diff --git a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java index fff65cc8f..cbfe5bc53 100644 --- a/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java +++ b/src/main/java/dk/camelot64/kickc/model/iterator/ProgramValueIterator.java @@ -118,6 +118,7 @@ public class ProgramValueIterator { for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { int size = phiVariable.getValues().size(); for(int i = 0; i < size; i++) { + execute(new ProgramValue.PhiValuePredecessor(phiVariable, i), handler, statement, statementsIt, block); execute(new ProgramValue.PhiValue(phiVariable, i), handler, statement, statementsIt, block); } execute(new ProgramValue.PhiVariable(phiVariable), handler, statement, statementsIt, block); diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java index 379c56f76..78982f4b9 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java @@ -362,6 +362,14 @@ public abstract class Scope implements Symbol { return symbols.values(); } + /** + * Set the value of the counter used to number intermediate labels + * @param intermediateLabelCount The new counter value + */ + public void setIntermediateLabelCount(int intermediateLabelCount) { + this.intermediateLabelCount = intermediateLabelCount; + } + @Override public boolean equals(Object o) { if(this == o) { diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNRenumberLabels.java b/src/main/java/dk/camelot64/kickc/passes/PassNRenumberLabels.java new file mode 100644 index 000000000..ff538f911 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/passes/PassNRenumberLabels.java @@ -0,0 +1,74 @@ +package dk.camelot64.kickc.passes; + +import dk.camelot64.kickc.model.Program; +import dk.camelot64.kickc.model.iterator.ProgramValueIterator; +import dk.camelot64.kickc.model.symbols.Label; +import dk.camelot64.kickc.model.symbols.Scope; +import dk.camelot64.kickc.model.symbols.Symbol; +import dk.camelot64.kickc.model.values.LabelRef; +import dk.camelot64.kickc.model.values.Value; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Renumber all labels in the program + */ +public class PassNRenumberLabels extends Pass2SsaOptimization { + + public PassNRenumberLabels(Program program) { + super(program); + } + + @Override + public boolean step() { + Map renamed = new LinkedHashMap<>(); + renumberLabels(getScope(), renamed); + for(Scope scope : getScope().getAllScopes(true)) { + renumberLabels(scope, renamed); + } + ProgramValueIterator.execute(getGraph(), (programValue, currentStmt, stmtIt, currentBlock) -> { + Value value = programValue.get(); + if(value instanceof LabelRef) { + LabelRef newLabelRef = renamed.get(value); + if(newLabelRef!=null) { + programValue.set(newLabelRef); + } + } + } + ); + return false; + } + + private void renumberLabels(Scope scope, Map renamed) { + int labelIdx = 1; + List