diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index fe73f8f6e..72b9b41d5 100644
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -5,6 +5,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/dk/camelot64/kickc/Compiler.java b/src/main/java/dk/camelot64/kickc/Compiler.java
index 5d94d6a1a..37438931e 100644
--- a/src/main/java/dk/camelot64/kickc/Compiler.java
+++ b/src/main/java/dk/camelot64/kickc/Compiler.java
@@ -22,34 +22,6 @@ public class Compiler {
this.program = new Program();
}
- public CompileLog getLog() {
- return program.getLog();
- }
-
- public void addImportPath(String path) {
- program.getImportPaths().add(path);
- }
-
- public Program compile(String fileName) throws IOException {
- try {
- Pass0GenerateStatementSequence pass0GenerateStatementSequence = new Pass0GenerateStatementSequence(program);
- loadAndParseFile(fileName, program, pass0GenerateStatementSequence);
- StatementSequence sequence = pass0GenerateStatementSequence.getSequence();
- sequence.addStatement(new StatementCall(null, "main", new ArrayList<>()));
- program.setStatementSequence(sequence);
- pass1GenerateSSA();
- pass2OptimizeSSA();
- pass3Analysis();
- pass4RegisterAllocation();
- pass5GenerateAndOptimizeAsm();
- return program;
- } catch(Exception e) {
- System.out.println("EXCEPTION DURING COMPILE " + e.getMessage());
- System.out.println(getLog().toString());
- throw e;
- }
- }
-
public static void loadAndParseFile(String fileName, Program program, Pass0GenerateStatementSequence pass0GenerateStatementSequence) {
try {
File file = loadFile(fileName, program);
@@ -100,6 +72,34 @@ public class Compiler {
throw new CompileError("File not found " + fileName);
}
+ public CompileLog getLog() {
+ return program.getLog();
+ }
+
+ public void addImportPath(String path) {
+ program.getImportPaths().add(path);
+ }
+
+ public Program compile(String fileName) throws IOException {
+ try {
+ Pass0GenerateStatementSequence pass0GenerateStatementSequence = new Pass0GenerateStatementSequence(program);
+ loadAndParseFile(fileName, program, pass0GenerateStatementSequence);
+ StatementSequence sequence = pass0GenerateStatementSequence.getSequence();
+ sequence.addStatement(new StatementCall(null, "main", new ArrayList<>()));
+ program.setStatementSequence(sequence);
+ pass1GenerateSSA();
+ pass2OptimizeSSA();
+ pass3Analysis();
+ pass4RegisterAllocation();
+ pass5GenerateAndOptimizeAsm();
+ return program;
+ } catch(Exception e) {
+ System.out.println("EXCEPTION DURING COMPILE " + e.getMessage());
+ System.out.println(getLog().toString());
+ throw e;
+ }
+ }
+
private Program pass1GenerateSSA() {
new Pass1TypeInference(program).execute();
diff --git a/src/main/java/dk/camelot64/kickc/NumberParser.java b/src/main/java/dk/camelot64/kickc/NumberParser.java
index 479539956..db39dd5ab 100644
--- a/src/main/java/dk/camelot64/kickc/NumberParser.java
+++ b/src/main/java/dk/camelot64/kickc/NumberParser.java
@@ -19,7 +19,7 @@ public class NumberParser {
return parseDecInt(literal);
}
} else {
- throw new NumberFormatException("Not Implemented: non-integer parsing. "+literal);
+ throw new NumberFormatException("Not Implemented: non-integer parsing. " + literal);
}
}
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmAddressingMode.java b/src/main/java/dk/camelot64/kickc/asm/AsmAddressingMode.java
index e8bb8af4c..1498c630d 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmAddressingMode.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmAddressingMode.java
@@ -38,7 +38,7 @@ public enum AsmAddressingMode {
public String getAsm(String mnemnonic, String parameter) {
String replaced = template.replace("%i", mnemnonic);
- if(parameter!=null) {
+ if(parameter != null) {
replaced = replaced.replace("%p", parameter);
}
return replaced;
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmBasicUpstart.java b/src/main/java/dk/camelot64/kickc/asm/AsmBasicUpstart.java
index a0f8b2748..9b9a5d652 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmBasicUpstart.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmBasicUpstart.java
@@ -22,7 +22,7 @@ public class AsmBasicUpstart implements AsmLine {
@Override
public String getAsm() {
- return ":BasicUpstart("+function+")";
+ return ":BasicUpstart(" + function + ")";
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmClobber.java b/src/main/java/dk/camelot64/kickc/asm/AsmClobber.java
index dfb1de7fe..d03f441be 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmClobber.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmClobber.java
@@ -1,8 +1,9 @@
package dk.camelot64.kickc.asm;
-/** Information about what parts of the CPU an ASM instruction clobbers */
+/** Information about what parts of the CPU an ASM instruction clobbers */
public class AsmClobber {
+ public static final AsmClobber CLOBBER_ALL = new AsmClobber(true);
boolean clobberA;
boolean clobberX;
boolean clobberY;
@@ -14,6 +15,7 @@ public class AsmClobber {
public AsmClobber() {
}
+
AsmClobber(boolean clobberAll) {
this.clobberA = clobberAll;
this.clobberX = clobberAll;
@@ -24,69 +26,66 @@ public class AsmClobber {
this.clobberZ = clobberAll;
}
-
public boolean isClobberA() {
return clobberA;
}
- public boolean isClobberX() {
- return clobberX;
- }
-
- public boolean isClobberY() {
- return clobberY;
- }
-
- public boolean isClobberC() {
- return clobberC;
- }
-
- public boolean isClobberN() {
- return clobberN;
- }
-
- public boolean isClobberZ() {
- return clobberZ;
- }
-
- public boolean isClobberV() {
- return clobberV;
- }
-
public void setClobberA(boolean clobberA) {
this.clobberA = clobberA;
}
+ public boolean isClobberX() {
+ return clobberX;
+ }
+
public void setClobberX(boolean clobberX) {
this.clobberX = clobberX;
}
+ public boolean isClobberY() {
+ return clobberY;
+ }
+
public void setClobberY(boolean clobberY) {
this.clobberY = clobberY;
}
+ public boolean isClobberC() {
+ return clobberC;
+ }
+
public void setClobberC(boolean clobberC) {
this.clobberC = clobberC;
}
+ public boolean isClobberN() {
+ return clobberN;
+ }
+
public void setClobberN(boolean clobberN) {
this.clobberN = clobberN;
}
+ public boolean isClobberZ() {
+ return clobberZ;
+ }
+
public void setClobberZ(boolean clobberZ) {
this.clobberZ = clobberZ;
}
+ public boolean isClobberV() {
+ return clobberV;
+ }
+
public void setClobberV(boolean clobberV) {
this.clobberV = clobberV;
}
- public static final AsmClobber CLOBBER_ALL = new AsmClobber(true);
-
-
/**
* Adds clobber.
* Effective updates so this clobber also clobbers anything added
+ *
* @param clobber The clobber to add
*/
public void add(AsmClobber clobber) {
@@ -102,13 +101,13 @@ public class AsmClobber {
@Override
public String toString() {
return
- (clobberA?"A":"") +
- (clobberX?"X":"") +
- (clobberY?"Y":"") +
- (clobberC?"C":"") +
- (clobberN?"N":"") +
- (clobberZ?"Z":"") +
- (clobberV?"V":"") ;
+ (clobberA ? "A" : "") +
+ (clobberX ? "X" : "") +
+ (clobberY ? "Y" : "") +
+ (clobberC ? "C" : "") +
+ (clobberN ? "N" : "") +
+ (clobberZ ? "Z" : "") +
+ (clobberV ? "V" : "");
}
}
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmComment.java b/src/main/java/dk/camelot64/kickc/asm/AsmComment.java
index 7c6037d0f..3897f5f12 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmComment.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmComment.java
@@ -27,7 +27,7 @@ public class AsmComment implements AsmLine {
@Override
public String getAsm() {
- return "// "+comment;
+ return "// " + comment;
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmConstant.java b/src/main/java/dk/camelot64/kickc/asm/AsmConstant.java
index 42ca0bc0c..84f95cbf1 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmConstant.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmConstant.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.asm;
-/** ASM constant declaration */
+/** ASM constant declaration */
public class AsmConstant implements AsmLine {
private final String name;
private final String value;
@@ -24,7 +24,7 @@ public class AsmConstant implements AsmLine {
@Override
public String getAsm() {
- return ".const "+name+" = "+value;
+ return ".const " + name + " = " + value;
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmDataFill.java b/src/main/java/dk/camelot64/kickc/asm/AsmDataFill.java
index 64dfac27c..85b980c72 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmDataFill.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmDataFill.java
@@ -25,7 +25,7 @@ public class AsmDataFill implements AsmLine {
@Override
public int getLineBytes() {
- return size*getElementBytes();
+ return size * getElementBytes();
}
@Override
@@ -36,9 +36,9 @@ public class AsmDataFill implements AsmLine {
@Override
public String getAsm() {
StringBuilder asm = new StringBuilder();
- asm.append(label+": ");
+ asm.append(label + ": ");
asm.append(".fill ");
- asm.append(AsmFormat.getAsmNumber(size*type.bytes));
+ asm.append(AsmFormat.getAsmNumber(size * type.bytes));
asm.append(", ");
asm.append(fillValue);
return asm.toString();
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmDataNumeric.java b/src/main/java/dk/camelot64/kickc/asm/AsmDataNumeric.java
index 3fc5d0555..9a453d572 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmDataNumeric.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmDataNumeric.java
@@ -12,21 +12,6 @@ public class AsmDataNumeric implements AsmLine {
private List values;
private int index;
- public static enum Type {
- BYTE("byte", 1),
- WORD("word", 2),
- DWORD("dword", 4);
-
- public final String asm;
- public final int bytes;
-
- Type(String asm, int bytes) {
- this.asm = asm;
- this.bytes = bytes;
- }
-
- }
-
public AsmDataNumeric(String label, Type type, List values) {
this.label = label;
this.type = type;
@@ -74,4 +59,19 @@ public class AsmDataNumeric implements AsmLine {
this.index = index;
}
+ public static enum Type {
+ BYTE("byte", 1),
+ WORD("word", 2),
+ DWORD("dword", 4);
+
+ public final String asm;
+ public final int bytes;
+
+ Type(String asm, int bytes) {
+ this.asm = asm;
+ this.bytes = bytes;
+ }
+
+ }
+
}
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmDataString.java b/src/main/java/dk/camelot64/kickc/asm/AsmDataString.java
index 760d3d84c..0b2dbd979 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmDataString.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmDataString.java
@@ -25,7 +25,7 @@ public class AsmDataString implements AsmLine {
@Override
public String getAsm() {
StringBuilder asm = new StringBuilder();
- asm.append(label+": ");
+ asm.append(label + ": ");
asm.append(".text ");
asm.append(value);
return asm.toString();
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmInstruction.java b/src/main/java/dk/camelot64/kickc/asm/AsmInstruction.java
index 341f34024..82d79aff2 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmInstruction.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmInstruction.java
@@ -18,10 +18,18 @@ public class AsmInstruction implements AsmLine {
return parameter;
}
+ public void setParameter(String parameter) {
+ this.parameter = parameter;
+ }
+
public AsmInstructionType getType() {
return type;
}
+ public void setType(AsmInstructionType type) {
+ this.type = type;
+ }
+
@Override
public int getLineBytes() {
return type.getBytes();
@@ -51,12 +59,4 @@ public class AsmInstruction implements AsmLine {
public void setIndex(int index) {
this.index = index;
}
-
- public void setParameter(String parameter) {
- this.parameter = parameter;
- }
-
- public void setType(AsmInstructionType type) {
- this.type = type;
- }
}
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmInstructionSet.java b/src/main/java/dk/camelot64/kickc/asm/AsmInstructionSet.java
index 400d894ba..769b405b1 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmInstructionSet.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmInstructionSet.java
@@ -1,7 +1,5 @@
package dk.camelot64.kickc.asm;
-import dk.camelot64.kickc.NumberParser;
-
import java.util.*;
/**
@@ -10,38 +8,10 @@ import java.util.*;
public class AsmInstructionSet {
private static AsmInstructionSet set = new AsmInstructionSet();
-
- public static AsmInstructionType getInstructionType(String mnemonic, AsmAddressingMode mode, boolean isZp) {
- AsmInstructionType type = null;
- if (AsmAddressingMode.ABS.equals(mode) && isZp) {
- type = set.getType(mnemonic, AsmAddressingMode.ZP);
- }
- if (AsmAddressingMode.ABX.equals(mode) && isZp) {
- type = set.getType(mnemonic, AsmAddressingMode.ZPX);
- }
- if (AsmAddressingMode.ABY.equals(mode) && isZp) {
- type = set.getType(mnemonic, AsmAddressingMode.ZPY);
- }
- if (type == null) {
- type = set.getType(mnemonic, mode);
- }
- if (type == null && AsmAddressingMode.ABS.equals(mode)) {
- type = set.getType(mnemonic, AsmAddressingMode.REL);
- }
- return type;
- }
-
private List instructions;
-
/** Maps mnemonic_addressingmMode to the instruction type */
private Map instructionsMap;
- private void add(int opcode, String mnemonic, AsmAddressingMode addressingmMode, double cycles) {
- AsmInstructionType instructionType = new AsmInstructionType(opcode, mnemonic, addressingmMode, cycles);
- instructions.add(instructionType);
- instructionsMap.put(mnemonic+"_"+addressingmMode.getName(), instructionType);
- }
-
public AsmInstructionSet() {
this.instructions = new ArrayList<>();
this.instructionsMap = new HashMap<>();
@@ -315,43 +285,43 @@ public class AsmInstructionSet {
add(0xfe, "inc", abx, 7.0);
add(0xff, "isc", abx, 7.0);
List jumps = Arrays.asList("jmp", "beq", "bne", "bcc", "bcs", "bvs", "bvc", "bmi", "bpl", "jsr");
- for (AsmInstructionType instruction : instructions) {
+ for(AsmInstructionType instruction : instructions) {
if(jumps.contains(instruction.getMnemnonic())) {
instruction.setJump(true);
}
}
- List cxs = Arrays.asList("dex", "inx", "ldx", "tax", "tsx", "las", "lax", "axs");
- for (AsmInstructionType instruction : instructions) {
+ List cxs = Arrays.asList("dex", "inx", "ldx", "tax", "tsx", "las", "lax", "axs");
+ for(AsmInstructionType instruction : instructions) {
if(cxs.contains(instruction.getMnemnonic())) {
instruction.getClobber().setClobberX(true);
}
}
- List cys = Arrays.asList("dey", "iny", "ldy", "tay" );
- for (AsmInstructionType instruction : instructions) {
+ List cys = Arrays.asList("dey", "iny", "ldy", "tay");
+ for(AsmInstructionType instruction : instructions) {
if(cys.contains(instruction.getMnemnonic())) {
instruction.getClobber().setClobberY(true);
}
}
List cas = Arrays.asList("ora", "and", "eor", "adc", "sbc", "lda", "txa", "tya", "pla", "slo", "rla", "sre", "rra", "isc", "anc", "alr", "arr", "xaa", "lax", "las");
- for (AsmInstructionType instruction : instructions) {
+ for(AsmInstructionType instruction : instructions) {
if(cas.contains(instruction.getMnemnonic())) {
instruction.getClobber().setClobberA(true);
}
}
List ccs = Arrays.asList("adc", "sbc", "cmp", "cpx", "cpy", "asl", "rol", "lsr", "ror", "plp", "rti", "clc", "sec", "slo", "rla", "sre", "rra", "dcp", "isc", "anc", "alr", "arr", "axs");
- for (AsmInstructionType instruction : instructions) {
+ for(AsmInstructionType instruction : instructions) {
if(ccs.contains(instruction.getMnemnonic())) {
instruction.getClobber().setClobberC(true);
}
}
List cvs = Arrays.asList("adc", "sbc", "plp", "rti", "bit", "rra", "isc", "arr");
- for (AsmInstructionType instruction : instructions) {
+ for(AsmInstructionType instruction : instructions) {
if(cvs.contains(instruction.getMnemnonic())) {
instruction.getClobber().setClobberV(true);
}
}
List czs = Arrays.asList("ora", "and", "eor", "adc", "sbc", "cmp", "cpx", "cpy", "dec", "dex", "dey", "inc", "inx", "iny", "asl", "rol", "lsr", "ror", "lda", "ldx", "ldy", "tax", "txa", "tay", "tya", "tsx", "txs", "pla", "plp", "rti", "bit", "slo", "rla", "sre", "rra", "lax", "dcp", "isc", "anc", "alr", "arr", "xaa", "lax", "axs", "las");
- for (AsmInstructionType instruction : instructions) {
+ for(AsmInstructionType instruction : instructions) {
if(czs.contains(instruction.getMnemnonic())) {
instruction.getClobber().setClobberZ(true);
instruction.getClobber().setClobberN(true);
@@ -359,8 +329,34 @@ public class AsmInstructionSet {
}
}
+ public static AsmInstructionType getInstructionType(String mnemonic, AsmAddressingMode mode, boolean isZp) {
+ AsmInstructionType type = null;
+ if(AsmAddressingMode.ABS.equals(mode) && isZp) {
+ type = set.getType(mnemonic, AsmAddressingMode.ZP);
+ }
+ if(AsmAddressingMode.ABX.equals(mode) && isZp) {
+ type = set.getType(mnemonic, AsmAddressingMode.ZPX);
+ }
+ if(AsmAddressingMode.ABY.equals(mode) && isZp) {
+ type = set.getType(mnemonic, AsmAddressingMode.ZPY);
+ }
+ if(type == null) {
+ type = set.getType(mnemonic, mode);
+ }
+ if(type == null && AsmAddressingMode.ABS.equals(mode)) {
+ type = set.getType(mnemonic, AsmAddressingMode.REL);
+ }
+ return type;
+ }
+
+ private void add(int opcode, String mnemonic, AsmAddressingMode addressingmMode, double cycles) {
+ AsmInstructionType instructionType = new AsmInstructionType(opcode, mnemonic, addressingmMode, cycles);
+ instructions.add(instructionType);
+ instructionsMap.put(mnemonic + "_" + addressingmMode.getName(), instructionType);
+ }
+
public AsmInstructionType getType(String mnemonic, AsmAddressingMode addressingMode) {
- String key = mnemonic.toLowerCase()+"_"+addressingMode.getName();
+ String key = mnemonic.toLowerCase() + "_" + addressingMode.getName();
return instructionsMap.get(key);
}
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmLabel.java b/src/main/java/dk/camelot64/kickc/asm/AsmLabel.java
index 83ed4eef9..4d1bef8e7 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmLabel.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmLabel.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.asm;
-/** A label / jump target */
+/** A label / jump target */
public class AsmLabel implements AsmLine {
private String label;
@@ -15,6 +15,10 @@ public class AsmLabel implements AsmLine {
return label;
}
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
@Override
public int getLineBytes() {
return 0;
@@ -27,7 +31,7 @@ public class AsmLabel implements AsmLine {
@Override
public String getAsm() {
- return label+":";
+ return label + ":";
}
@Override
@@ -44,8 +48,4 @@ public class AsmLabel implements AsmLine {
public String toString() {
return getAsm();
}
-
- public void setLabel(String label) {
- this.label = label;
- }
}
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmLabelDecl.java b/src/main/java/dk/camelot64/kickc/asm/AsmLabelDecl.java
index 7501a6ca4..53f4222a1 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmLabelDecl.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmLabelDecl.java
@@ -2,7 +2,7 @@ package dk.camelot64.kickc.asm;
import dk.camelot64.kickc.fragment.AsmFormat;
-/** A label declaration .label lbl = val */
+/** A label declaration .label lbl = val */
public class AsmLabelDecl implements AsmLine {
private final String name;
private final int address;
@@ -26,7 +26,7 @@ public class AsmLabelDecl implements AsmLine {
@Override
public String getAsm() {
- return ".label "+name+" = "+ AsmFormat.getAsmNumber(address);
+ return ".label " + name + " = " + AsmFormat.getAsmNumber(address);
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmProgram.java b/src/main/java/dk/camelot64/kickc/asm/AsmProgram.java
index 0a8715a78..b3d5a12bd 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmProgram.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmProgram.java
@@ -76,15 +76,17 @@ public class AsmProgram {
/**
* Add a constant declararion to the ASM
+ *
* @param name The name of the constant
* @param value The value of the constant
*/
- public void addConstant(String name, String value) {
- addLine(new AsmConstant(name, value));
- }
+ public void addConstant(String name, String value) {
+ addLine(new AsmConstant(name, value));
+ }
/**
* Add a BYTE/WORD/DWORD data declaration tot the ASM
+ *
* @param label The label of the data
* @param type The type of the data
* @param asmElements The value of the elements
@@ -95,6 +97,7 @@ public class AsmProgram {
/**
* Add a FILL data declaration to the ASM
+ *
* @param label The label of the data
* @param type The type of the data
* @param size The size of data to fill
@@ -105,6 +108,7 @@ public class AsmProgram {
/**
* Add a string data declaration to the ASM
+ *
* @param label The label of the data
* @param value The value of the string
*/
@@ -114,6 +118,7 @@ public class AsmProgram {
/**
* Add data alignment to the ASM
+ *
* @param alignment The number to align the address of the next data to
*/
public void addDataAlignment(String alignment) {
@@ -129,7 +134,7 @@ public class AsmProgram {
*/
public int getBytes() {
int bytes = 0;
- for (AsmSegment segment : segments) {
+ for(AsmSegment segment : segments) {
bytes += segment.getBytes();
}
return bytes;
@@ -143,7 +148,7 @@ public class AsmProgram {
*/
public double getCycles() {
double cycles = 0.0;
- for (AsmSegment segment : segments) {
+ for(AsmSegment segment : segments) {
cycles += segment.getCycles();
}
return cycles;
@@ -157,7 +162,7 @@ public class AsmProgram {
*/
public AsmClobber getClobber() {
AsmClobber clobber = new AsmClobber();
- for (AsmSegment segment : segments) {
+ for(AsmSegment segment : segments) {
clobber.add(segment.getClobber());
}
return clobber;
@@ -169,12 +174,17 @@ public class AsmProgram {
public String toString(AsmPrintState printState) {
StringBuilder out = new StringBuilder();
- for (AsmSegment segment : segments) {
+ for(AsmSegment segment : segments) {
out.append(segment.toString(printState));
}
return out.toString();
}
+ @Override
+ public String toString() {
+ return toString(true);
+ }
+
static class AsmPrintState {
boolean comments;
String indent;
@@ -193,7 +203,7 @@ public class AsmProgram {
}
public void decIndent() {
- if(this.indent.length()>=2) {
+ if(this.indent.length() >= 2) {
this.indent = this.indent.substring(0, this.indent.length() - 2);
}
}
@@ -205,10 +215,4 @@ public class AsmProgram {
}
- @Override
- public String toString() {
- return toString(true);
- }
-
-
}
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmProgramStaticRegisterValues.java b/src/main/java/dk/camelot64/kickc/asm/AsmProgramStaticRegisterValues.java
index 070431e3d..8ed96dc8a 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmProgramStaticRegisterValues.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmProgramStaticRegisterValues.java
@@ -18,169 +18,28 @@ public class AsmProgramStaticRegisterValues {
initValues();
}
- public AsmRegisterValues getValues(AsmInstruction instruction) {
- return values.get(instruction);
- }
-
- private void initValues() {
- AsmRegisterValues current = new AsmRegisterValues();
- for (AsmSegment segment : program.getSegments()) {
- for (AsmLine line : segment.getLines()) {
- current = updateStaticRegisterValues(current, line);
- }
- }
- }
-
- private AsmRegisterValues updateStaticRegisterValues(AsmRegisterValues current, AsmLine line) {
- if (line instanceof AsmLabel) {
- current = new AsmRegisterValues();
- } else if (line instanceof AsmScopeBegin) {
- current = new AsmRegisterValues();
- } else if (line instanceof AsmScopeEnd) {
- current = new AsmRegisterValues();
- } else if (line instanceof AsmInstruction) {
- AsmInstruction instruction = (AsmInstruction) line;
- values.put(instruction, current);
- current = new AsmRegisterValues(current);
- AsmInstructionType instructionType = instruction.getType();
- AsmClobber clobber = instructionType.getClobber();
- if(instruction.getType().getMnemnonic().equals("jsr")) {
- clobber = AsmClobber.CLOBBER_ALL;
- }
- if (clobber.isClobberA()) {
- current.setA(null);
- current.setaMem(null);
- }
- if (clobber.isClobberX()) {
- current.setX(null);
- current.setxMem(null);
- }
- if (clobber.isClobberY()) {
- current.setY(null);
- current.setyMem(null);
- }
- if (clobber.isClobberC()) {
- current.setC(null);
- }
- if (clobber.isClobberN()) {
- current.setN(null);
- }
- if (clobber.isClobberV()) {
- current.setV(null);
- }
- if (clobber.isClobberZ()) {
- current.setZ(null);
- }
- String mnemnonic = instructionType.getMnemnonic();
- AsmAddressingMode addressingMode = instructionType.getAddressingMode();
- if ((mnemnonic.equals("inc") || mnemnonic.equals("dec") || mnemnonic.equals("ror") || mnemnonic.equals("rol") || mnemnonic.equals("lsr") || mnemnonic.equals("asl")) && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
- String modParam = instruction.getParameter();
- if(current.getaMem()!=null && current.getaMem().equals(modParam)) {
- current.setaMem(null);
- }
- if(current.getxMem()!=null && current.getxMem().equals(modParam)) {
- current.setxMem(null);
- }
- if(current.getyMem()!=null && current.getyMem().equals(modParam)) {
- current.setyMem(null);
- }
- }
- if (mnemnonic.equals("lda") && addressingMode.equals(AsmAddressingMode.IMM)) {
- current.setA(instruction.getParameter());
- current.setaMem(null);
- Integer immValue = getImmValue(instruction.getParameter());
- if (immValue != null) {
- current.setZ(immValue == 0);
- current.setN(immValue > 127);
- }
- }
- if (mnemnonic.equals("lda") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
- current.setaMem(instruction.getParameter());
- current.setA(null);
- }
- if (mnemnonic.equals("sta") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
- current.setaMem(instruction.getParameter());
- }
- if (mnemnonic.equals("ldx") && addressingMode.equals(AsmAddressingMode.IMM)) {
- current.setX(instruction.getParameter());
- current.setxMem(null);
- Integer immValue = getImmValue(instruction.getParameter());
- if (immValue != null) {
- current.setZ(immValue == 0);
- current.setN(immValue > 127);
- }
- }
- if (mnemnonic.equals("ldx") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
- current.setxMem(instruction.getParameter());
- current.setX(null);
- }
- if (mnemnonic.equals("stx") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
- current.setxMem(instruction.getParameter());
- }
- if (mnemnonic.equals("ldy") && addressingMode.equals(AsmAddressingMode.IMM)) {
- current.setY(instruction.getParameter());
- current.setyMem(null);
- Integer immValue = getImmValue(instruction.getParameter());
- if (immValue != null) {
- current.setZ(immValue == 0);
- current.setN(immValue > 127);
- }
- }
- if (mnemnonic.equals("ldy") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
- current.setyMem(instruction.getParameter());
- }
- if (mnemnonic.equals("sty") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
- current.setyMem(instruction.getParameter());
- current.setY(null);
- }
- if (mnemnonic.equals("txa")) {
- current.setA(current.getX());
- current.setaMem(current.getxMem());
- }
- if (mnemnonic.equals("tax")) {
- current.setX(current.getA());
- current.setxMem(current.getaMem());
- }
- if (mnemnonic.equals("tya")) {
- current.setA(current.getY());
- current.setaMem(current.getyMem());
- }
- if (mnemnonic.equals("tay")) {
- current.setY(current.getA());
- current.setyMem(current.getaMem());
- }
- if (mnemnonic.equals("sec")) {
- current.setC(Boolean.TRUE);
- }
- if (mnemnonic.equals("clc")) {
- current.setC(Boolean.FALSE);
- }
- }
- return current;
- }
-
public static Integer getImmValue(String parameter) {
Integer immValue = null;
- if (parameter != null) {
+ if(parameter != null) {
if(parameter.startsWith("<")) {
try {
int parValue = Integer.parseInt(parameter.substring(1));
return 0xff & parValue;
- } catch (NumberFormatException e) {
+ } catch(NumberFormatException e) {
// ignore
}
} else if(parameter.startsWith(">")) {
try {
int parValue = Integer.parseInt(parameter.substring(1));
return 0xff & (parValue / 0x100);
- } catch (NumberFormatException e) {
+ } catch(NumberFormatException e) {
// ignore
}
} else {
try {
immValue = Integer.parseInt(parameter);
return immValue;
- } catch (NumberFormatException e) {
+ } catch(NumberFormatException e) {
// ignore
}
}
@@ -189,17 +48,158 @@ public class AsmProgramStaticRegisterValues {
}
public static boolean matchImm(String immVal1, String immVal2) {
- if (immVal1 != null && immVal2 != null && immVal1.equals(immVal2)) {
+ if(immVal1 != null && immVal2 != null && immVal1.equals(immVal2)) {
return true;
}
Integer immInt1 = getImmValue(immVal1);
Integer immInt2 = getImmValue(immVal2);
- if (immInt1 != null && immInt2 != null && immInt1.equals(immInt2)) {
+ if(immInt1 != null && immInt2 != null && immInt1.equals(immInt2)) {
return true;
}
return false;
}
+ public AsmRegisterValues getValues(AsmInstruction instruction) {
+ return values.get(instruction);
+ }
+
+ private void initValues() {
+ AsmRegisterValues current = new AsmRegisterValues();
+ for(AsmSegment segment : program.getSegments()) {
+ for(AsmLine line : segment.getLines()) {
+ current = updateStaticRegisterValues(current, line);
+ }
+ }
+ }
+
+ private AsmRegisterValues updateStaticRegisterValues(AsmRegisterValues current, AsmLine line) {
+ if(line instanceof AsmLabel) {
+ current = new AsmRegisterValues();
+ } else if(line instanceof AsmScopeBegin) {
+ current = new AsmRegisterValues();
+ } else if(line instanceof AsmScopeEnd) {
+ current = new AsmRegisterValues();
+ } else if(line instanceof AsmInstruction) {
+ AsmInstruction instruction = (AsmInstruction) line;
+ values.put(instruction, current);
+ current = new AsmRegisterValues(current);
+ AsmInstructionType instructionType = instruction.getType();
+ AsmClobber clobber = instructionType.getClobber();
+ if(instruction.getType().getMnemnonic().equals("jsr")) {
+ clobber = AsmClobber.CLOBBER_ALL;
+ }
+ if(clobber.isClobberA()) {
+ current.setA(null);
+ current.setaMem(null);
+ }
+ if(clobber.isClobberX()) {
+ current.setX(null);
+ current.setxMem(null);
+ }
+ if(clobber.isClobberY()) {
+ current.setY(null);
+ current.setyMem(null);
+ }
+ if(clobber.isClobberC()) {
+ current.setC(null);
+ }
+ if(clobber.isClobberN()) {
+ current.setN(null);
+ }
+ if(clobber.isClobberV()) {
+ current.setV(null);
+ }
+ if(clobber.isClobberZ()) {
+ current.setZ(null);
+ }
+ String mnemnonic = instructionType.getMnemnonic();
+ AsmAddressingMode addressingMode = instructionType.getAddressingMode();
+ if((mnemnonic.equals("inc") || mnemnonic.equals("dec") || mnemnonic.equals("ror") || mnemnonic.equals("rol") || mnemnonic.equals("lsr") || mnemnonic.equals("asl")) && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
+ String modParam = instruction.getParameter();
+ if(current.getaMem() != null && current.getaMem().equals(modParam)) {
+ current.setaMem(null);
+ }
+ if(current.getxMem() != null && current.getxMem().equals(modParam)) {
+ current.setxMem(null);
+ }
+ if(current.getyMem() != null && current.getyMem().equals(modParam)) {
+ current.setyMem(null);
+ }
+ }
+ if(mnemnonic.equals("lda") && addressingMode.equals(AsmAddressingMode.IMM)) {
+ current.setA(instruction.getParameter());
+ current.setaMem(null);
+ Integer immValue = getImmValue(instruction.getParameter());
+ if(immValue != null) {
+ current.setZ(immValue == 0);
+ current.setN(immValue > 127);
+ }
+ }
+ if(mnemnonic.equals("lda") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
+ current.setaMem(instruction.getParameter());
+ current.setA(null);
+ }
+ if(mnemnonic.equals("sta") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
+ current.setaMem(instruction.getParameter());
+ }
+ if(mnemnonic.equals("ldx") && addressingMode.equals(AsmAddressingMode.IMM)) {
+ current.setX(instruction.getParameter());
+ current.setxMem(null);
+ Integer immValue = getImmValue(instruction.getParameter());
+ if(immValue != null) {
+ current.setZ(immValue == 0);
+ current.setN(immValue > 127);
+ }
+ }
+ if(mnemnonic.equals("ldx") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
+ current.setxMem(instruction.getParameter());
+ current.setX(null);
+ }
+ if(mnemnonic.equals("stx") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
+ current.setxMem(instruction.getParameter());
+ }
+ if(mnemnonic.equals("ldy") && addressingMode.equals(AsmAddressingMode.IMM)) {
+ current.setY(instruction.getParameter());
+ current.setyMem(null);
+ Integer immValue = getImmValue(instruction.getParameter());
+ if(immValue != null) {
+ current.setZ(immValue == 0);
+ current.setN(immValue > 127);
+ }
+ }
+ if(mnemnonic.equals("ldy") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
+ current.setyMem(instruction.getParameter());
+ }
+ if(mnemnonic.equals("sty") && (addressingMode.equals(AsmAddressingMode.ZP) || addressingMode.equals(AsmAddressingMode.ABS))) {
+ current.setyMem(instruction.getParameter());
+ current.setY(null);
+ }
+ if(mnemnonic.equals("txa")) {
+ current.setA(current.getX());
+ current.setaMem(current.getxMem());
+ }
+ if(mnemnonic.equals("tax")) {
+ current.setX(current.getA());
+ current.setxMem(current.getaMem());
+ }
+ if(mnemnonic.equals("tya")) {
+ current.setA(current.getY());
+ current.setaMem(current.getyMem());
+ }
+ if(mnemnonic.equals("tay")) {
+ current.setY(current.getA());
+ current.setyMem(current.getaMem());
+ }
+ if(mnemnonic.equals("sec")) {
+ current.setC(Boolean.TRUE);
+ }
+ if(mnemnonic.equals("clc")) {
+ current.setC(Boolean.FALSE);
+ }
+ }
+ return current;
+ }
+
/**
* Known values of registers/flags at an instruction. null where value is unknown.
*/
@@ -235,48 +235,64 @@ public class AsmProgramStaticRegisterValues {
return a;
}
+ public void setA(String a) {
+ this.a = a;
+ }
+
public String getaMem() {
return aMem;
}
+ public void setaMem(String aMem) {
+ this.aMem = aMem;
+ }
+
public String getX() {
return x;
}
- public String getY() {
- return y;
- }
-
- public Boolean getC() {
- return c;
- }
-
- public Boolean getV() {
- return v;
- }
-
- public Boolean getN() {
- return n;
- }
-
- public Boolean getZ() {
- return z;
- }
-
public void setX(String x) {
this.x = x;
}
+ public String getY() {
+ return y;
+ }
+
public void setY(String y) {
this.y = y;
}
- public void setA(String a) {
- this.a = a;
+ public Boolean getC() {
+ return c;
}
- public void setaMem(String aMem) {
- this.aMem = aMem;
+ public void setC(Boolean c) {
+ this.c = c;
+ }
+
+ public Boolean getV() {
+ return v;
+ }
+
+ public void setV(Boolean v) {
+ this.v = v;
+ }
+
+ public Boolean getN() {
+ return n;
+ }
+
+ public void setN(Boolean n) {
+ this.n = n;
+ }
+
+ public Boolean getZ() {
+ return z;
+ }
+
+ public void setZ(Boolean z) {
+ this.z = z;
}
public String getxMem() {
@@ -295,22 +311,6 @@ public class AsmProgramStaticRegisterValues {
this.yMem = yMem;
}
- public void setC(Boolean c) {
- this.c = c;
- }
-
- public void setV(Boolean v) {
- this.v = v;
- }
-
- public void setN(Boolean n) {
- this.n = n;
- }
-
- public void setZ(Boolean z) {
- this.z = z;
- }
-
}
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmScopeBegin.java b/src/main/java/dk/camelot64/kickc/asm/AsmScopeBegin.java
index a6fb1809e..fab3e932e 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmScopeBegin.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmScopeBegin.java
@@ -27,7 +27,7 @@ public class AsmScopeBegin implements AsmLine {
@Override
public String getAsm() {
- return label+":"+" {";
+ return label + ":" + " {";
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmScopeEnd.java b/src/main/java/dk/camelot64/kickc/asm/AsmScopeEnd.java
index 3e449934b..b6b19765f 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmScopeEnd.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmScopeEnd.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.asm;
-/** The end of a scope */
+/** The end of a scope */
public class AsmScopeEnd implements AsmLine {
private int index;
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmSegment.java b/src/main/java/dk/camelot64/kickc/asm/AsmSegment.java
index 54ac86350..e7f9d644e 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmSegment.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmSegment.java
@@ -70,7 +70,7 @@ public class AsmSegment {
}
public void setFragment(String fragment) {
- this.fragment = fragment;
+ this.fragment = fragment;
}
public String getPhiTransitionId() {
@@ -97,7 +97,7 @@ public class AsmSegment {
*/
public int getBytes() {
int bytes = 0;
- for (AsmLine line : lines) {
+ for(AsmLine line : lines) {
bytes += line.getLineBytes();
}
return bytes;
@@ -111,7 +111,7 @@ public class AsmSegment {
*/
public double getCycles() {
double cycles = 0.0;
- for (AsmLine line : lines) {
+ for(AsmLine line : lines) {
cycles += line.getLineCycles();
}
return cycles;
@@ -125,8 +125,8 @@ public class AsmSegment {
*/
public AsmClobber getClobber() {
AsmClobber clobber = new AsmClobber();
- for (AsmLine line : lines) {
- if (line instanceof AsmInstruction) {
+ for(AsmLine line : lines) {
+ if(line instanceof AsmInstruction) {
AsmInstruction asmInstruction = (AsmInstruction) line;
AsmInstructionType asmInstructionType = asmInstruction.getType();
AsmClobber asmClobber = asmInstructionType.getClobber();
@@ -138,27 +138,27 @@ public class AsmSegment {
public String toString(AsmProgram.AsmPrintState printState) {
StringBuffer out = new StringBuffer();
- if (printState.isComments()) {
+ if(printState.isComments()) {
out.append(printState.getIndent()).append("//SEG").append(getIndex());
- if (source != null) {
+ if(source != null) {
out.append(" ").append(source);
}
- if(phiTransitionId!=null) {
+ if(phiTransitionId != null) {
out.append(" [").append(phiTransitionId);
- if(phiTransitionAssignmentIdx!=null) {
+ if(phiTransitionAssignmentIdx != null) {
out.append("#").append(phiTransitionAssignmentIdx);
}
out.append("]");
}
- if (fragment!=null) {
+ if(fragment != null) {
out.append(" -- ");
out.append(fragment).append(" ");
}
out.append("\n");
}
- for (AsmLine line : lines) {
- if (line instanceof AsmComment && !printState.isComments()) {
- if (!((AsmComment) line).getComment().contains("Fragment")) {
+ for(AsmLine line : lines) {
+ if(line instanceof AsmComment && !printState.isComments()) {
+ if(!((AsmComment) line).getComment().contains("Fragment")) {
continue;
}
}
@@ -166,7 +166,7 @@ public class AsmSegment {
printState.decIndent();
}
out.append(printState.getIndent());
- if (line instanceof AsmComment || line instanceof AsmInstruction || line instanceof AsmLabelDecl || line instanceof AsmConstant || line instanceof AsmDataNumeric || line instanceof AsmDataFill || line instanceof AsmDataString|| line instanceof AsmDataAlignment) {
+ if(line instanceof AsmComment || line instanceof AsmInstruction || line instanceof AsmLabelDecl || line instanceof AsmConstant || line instanceof AsmDataNumeric || line instanceof AsmDataFill || line instanceof AsmDataString || line instanceof AsmDataAlignment) {
out.append(" ");
}
out.append(line.getAsm() + "\n");
diff --git a/src/main/java/dk/camelot64/kickc/asm/AsmSetPc.java b/src/main/java/dk/camelot64/kickc/asm/AsmSetPc.java
index f3688cc10..11697de30 100644
--- a/src/main/java/dk/camelot64/kickc/asm/AsmSetPc.java
+++ b/src/main/java/dk/camelot64/kickc/asm/AsmSetPc.java
@@ -26,7 +26,7 @@ public class AsmSetPc implements AsmLine {
@Override
public String getAsm() {
- return ".pc = "+ AsmFormat.getAsmNumber(address)+" \""+name+"\"";
+ return ".pc = " + AsmFormat.getAsmNumber(address) + " \"" + name + "\"";
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
index 4bf6511c3..18f14f3e0 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFormat.java
@@ -2,141 +2,141 @@ package dk.camelot64.kickc.fragment;
import dk.camelot64.kickc.model.*;
-/** Formatting of numbers, constants, names and more for KickAssembler */
+/** Formatting of numbers, constants, names and more for KickAssembler */
public class AsmFormat {
- /**
- * Get ASM code for a constant value
- *
- * @param value The constant value
- * @param precedence The precedence of the outer expression operator. Used to generate perenthesis when needed.
- * @param codeScope The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
- * @return The ASM string representing the constant value
- */
- public static String getAsmConstant(Program program, ConstantValue value, int precedence, ScopeRef codeScope) {
- if (value instanceof ConstantRef) {
- ConstantVar constantVar = program.getScope().getConstant((ConstantRef) value);
- String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
- return getAsmParamName(constantVar.getScope().getRef(), asmName, codeScope);
- } else if (value instanceof ConstantInteger) {
- return getAsmNumber(((ConstantInteger) value).getNumber());
- } else if (value instanceof ConstantChar) {
- return "'" + ((ConstantChar) value).getValue() + "'";
- } else if (value instanceof ConstantString) {
- return "\"" + ((ConstantString) value).getValue() + "\"";
- } else if (value instanceof ConstantUnary) {
- ConstantUnary unary = (ConstantUnary) value;
- Operator operator = unary.getOperator();
- boolean parenthesis = operator.getPrecedence() > precedence;
- return (parenthesis ? "(" : "") +
- getAsmConstantUnary(program, codeScope, operator, unary.getOperand(), precedence) +
- (parenthesis ? ")" : "");
- } else if (value instanceof ConstantBinary) {
- ConstantBinary binary = (ConstantBinary) value;
- Operator operator = binary.getOperator();
- boolean parenthesis = operator.getPrecedence() > precedence;
- return
- (parenthesis ? "(" : "") +
- getAsmConstant(program, binary.getLeft(), operator.getPrecedence(), codeScope) +
- operator.getOperator() +
- getAsmConstant(program, binary.getRight(), operator.getPrecedence(), codeScope) +
- (parenthesis ? ")" : "");
- } else {
- throw new RuntimeException("Constant type not supported " + value);
- }
- }
+ /**
+ * Get ASM code for a constant value
+ *
+ * @param value The constant value
+ * @param precedence The precedence of the outer expression operator. Used to generate perenthesis when needed.
+ * @param codeScope The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
+ * @return The ASM string representing the constant value
+ */
+ public static String getAsmConstant(Program program, ConstantValue value, int precedence, ScopeRef codeScope) {
+ if(value instanceof ConstantRef) {
+ ConstantVar constantVar = program.getScope().getConstant((ConstantRef) value);
+ String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
+ return getAsmParamName(constantVar.getScope().getRef(), asmName, codeScope);
+ } else if(value instanceof ConstantInteger) {
+ return getAsmNumber(((ConstantInteger) value).getNumber());
+ } else if(value instanceof ConstantChar) {
+ return "'" + ((ConstantChar) value).getValue() + "'";
+ } else if(value instanceof ConstantString) {
+ return "\"" + ((ConstantString) value).getValue() + "\"";
+ } else if(value instanceof ConstantUnary) {
+ ConstantUnary unary = (ConstantUnary) value;
+ Operator operator = unary.getOperator();
+ boolean parenthesis = operator.getPrecedence() > precedence;
+ return (parenthesis ? "(" : "") +
+ getAsmConstantUnary(program, codeScope, operator, unary.getOperand(), precedence) +
+ (parenthesis ? ")" : "");
+ } else if(value instanceof ConstantBinary) {
+ ConstantBinary binary = (ConstantBinary) value;
+ Operator operator = binary.getOperator();
+ boolean parenthesis = operator.getPrecedence() > precedence;
+ return
+ (parenthesis ? "(" : "") +
+ getAsmConstant(program, binary.getLeft(), operator.getPrecedence(), codeScope) +
+ operator.getOperator() +
+ getAsmConstant(program, binary.getRight(), operator.getPrecedence(), codeScope) +
+ (parenthesis ? ")" : "");
+ } else {
+ throw new RuntimeException("Constant type not supported " + value);
+ }
+ }
- /**
- * Get ASM code for a constant unary expression
- *
- * @param program The program
- * @param codeScope The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
- * @param operator The unary operator
- * @param operand The operand of the unary expression
- * @return The ASM string representing the constant value
- */
- private static String getAsmConstantUnary(Program program, ScopeRef codeScope, Operator operator, ConstantValue operand, int outerPrecedence) {
- if (Operator.CAST_BYTE.equals(operator) || Operator.CAST_SBYTE.equals(operator)) {
- SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
- if (SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
- // No cast needed
- return getAsmConstant(program, operand, outerPrecedence, codeScope);
- } else {
- return "$ff & " + getAsmConstant(program, operand, Operator.BOOL_AND.getPrecedence(), codeScope);
- }
- } else if (Operator.CAST_WORD.equals(operator) || Operator.CAST_SWORD.equals(operator) || Operator.CAST_PTRBY.equals(operator)) {
- SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
- if (SymbolType.isWord(operandType) || SymbolType.isSWord(operandType)) {
- // No cast needed
- return getAsmConstant(program, operand, outerPrecedence, codeScope);
- } else {
- return "$ffff & " + getAsmConstant(program, operand, Operator.BOOL_AND.getPrecedence(), codeScope);
- }
- } else if (Operator.INCREMENT.equals(operator)) {
- return getAsmConstant(program, operand, Operator.PLUS.getPrecedence(), codeScope) + "+1";
- } else if (Operator.DECREMENT.equals(operator)) {
- return getAsmConstant(program, operand, Operator.PLUS.getPrecedence(), codeScope) + "-1";
- } else {
- return operator.getOperator() +
- getAsmConstant(program, operand, operator.getPrecedence(), codeScope);
- }
- }
+ /**
+ * Get ASM code for a constant unary expression
+ *
+ * @param program The program
+ * @param codeScope The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
+ * @param operator The unary operator
+ * @param operand The operand of the unary expression
+ * @return The ASM string representing the constant value
+ */
+ private static String getAsmConstantUnary(Program program, ScopeRef codeScope, Operator operator, ConstantValue operand, int outerPrecedence) {
+ if(Operator.CAST_BYTE.equals(operator) || Operator.CAST_SBYTE.equals(operator)) {
+ SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
+ if(SymbolType.isByte(operandType) || SymbolType.isSByte(operandType)) {
+ // No cast needed
+ return getAsmConstant(program, operand, outerPrecedence, codeScope);
+ } else {
+ return "$ff & " + getAsmConstant(program, operand, Operator.BOOL_AND.getPrecedence(), codeScope);
+ }
+ } else if(Operator.CAST_WORD.equals(operator) || Operator.CAST_SWORD.equals(operator) || Operator.CAST_PTRBY.equals(operator)) {
+ SymbolType operandType = SymbolTypeInference.inferType(program.getScope(), operand);
+ if(SymbolType.isWord(operandType) || SymbolType.isSWord(operandType)) {
+ // No cast needed
+ return getAsmConstant(program, operand, outerPrecedence, codeScope);
+ } else {
+ return "$ffff & " + getAsmConstant(program, operand, Operator.BOOL_AND.getPrecedence(), codeScope);
+ }
+ } else if(Operator.INCREMENT.equals(operator)) {
+ return getAsmConstant(program, operand, Operator.PLUS.getPrecedence(), codeScope) + "+1";
+ } else if(Operator.DECREMENT.equals(operator)) {
+ return getAsmConstant(program, operand, Operator.PLUS.getPrecedence(), codeScope) + "-1";
+ } else {
+ return operator.getOperator() +
+ getAsmConstant(program, operand, operator.getPrecedence(), codeScope);
+ }
+ }
- public static String getAsmNumber(Number number) {
- if (number instanceof Integer) {
- if (number.intValue() >= 0 && number.intValue() <= 9) {
- return String.format("%d", number.intValue());
- } else {
- return String.format("$%x", number);
- }
- }
- throw new RuntimeException("Unsupported number type " + number);
- }
+ public static String getAsmNumber(Number number) {
+ if(number instanceof Integer) {
+ if(number.intValue() >= 0 && number.intValue() <= 9) {
+ return String.format("%d", number.intValue());
+ } else {
+ return String.format("$%x", number);
+ }
+ }
+ throw new RuntimeException("Unsupported number type " + number);
+ }
- /**
- * Get the ASM parameter for a specific bound constant/ variable
- *
- * @param varScopeRef The scope containing the var/const
- * @param asmName The ASM name of the variable (local name or specific ASM name).
- * @param codeScopeRef The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
- * @return The ASM parameter to use in the ASM code
- */
- static String getAsmParamName(ScopeRef varScopeRef, String asmName, ScopeRef codeScopeRef) {
- if (!varScopeRef.equals(codeScopeRef) && varScopeRef.getFullName().length() > 0) {
- String param = varScopeRef.getFullName() + "." + asmName
- .replace('@', 'b')
- .replace(':', '_')
- .replace("#", "_")
- .replace("$", "_");
- //param = ""+((Registers.RegisterZp) register).getZp();
- return param;
- } else {
- String param = asmName.replace('@', 'b').replace(':', '_').replace("#", "_").replace("$", "_");
- //param = ""+((Registers.RegisterZp) register).getZp();
- return param;
- }
- }
+ /**
+ * Get the ASM parameter for a specific bound constant/ variable
+ *
+ * @param varScopeRef The scope containing the var/const
+ * @param asmName The ASM name of the variable (local name or specific ASM name).
+ * @param codeScopeRef The scope containing the code being generated. Used for adding scope to the name when needed (eg. line.x1 when referencing x1 variable inside line scope from outside line scope).
+ * @return The ASM parameter to use in the ASM code
+ */
+ static String getAsmParamName(ScopeRef varScopeRef, String asmName, ScopeRef codeScopeRef) {
+ if(!varScopeRef.equals(codeScopeRef) && varScopeRef.getFullName().length() > 0) {
+ String param = varScopeRef.getFullName() + "." + asmName
+ .replace('@', 'b')
+ .replace(':', '_')
+ .replace("#", "_")
+ .replace("$", "_");
+ //param = ""+((Registers.RegisterZp) register).getZp();
+ return param;
+ } else {
+ String param = asmName.replace('@', 'b').replace(':', '_').replace("#", "_").replace("$", "_");
+ //param = ""+((Registers.RegisterZp) register).getZp();
+ return param;
+ }
+ }
- /**
- * Get the ASM parameter for a specific bound variable
- *
- * @param boundVar The variable
- * @return The ASM parameter to use in the ASM code
- */
- static String getAsmParamName(Variable boundVar, ScopeRef codeScopeRef) {
- ScopeRef varScopeRef = boundVar.getScope().getRef();
- String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
- return getAsmParamName(varScopeRef, asmName, codeScopeRef);
- }
+ /**
+ * Get the ASM parameter for a specific bound variable
+ *
+ * @param boundVar The variable
+ * @return The ASM parameter to use in the ASM code
+ */
+ static String getAsmParamName(Variable boundVar, ScopeRef codeScopeRef) {
+ ScopeRef varScopeRef = boundVar.getScope().getRef();
+ String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
+ return getAsmParamName(varScopeRef, asmName, codeScopeRef);
+ }
- /**
- * Get the ASM parameter for a specific bound constant
- *
- * @param boundVar The constant
- * @return The ASM parameter to use in the ASM code
- */
- private static String getAsmParamName(ConstantVar boundVar, ScopeRef codeScopeRef) {
- ScopeRef varScopeRef = boundVar.getScope().getRef();
- String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
- return getAsmParamName(varScopeRef, asmName, codeScopeRef);
- }
+ /**
+ * Get the ASM parameter for a specific bound constant
+ *
+ * @param boundVar The constant
+ * @return The ASM parameter to use in the ASM code
+ */
+ private static String getAsmParamName(ConstantVar boundVar, ScopeRef codeScopeRef) {
+ ScopeRef varScopeRef = boundVar.getScope().getRef();
+ String asmName = boundVar.getAsmName() == null ? boundVar.getLocalName() : boundVar.getAsmName();
+ return getAsmParamName(varScopeRef, asmName, codeScopeRef);
+ }
}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragment.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragment.java
index 4de09b6f9..0b1f54343 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragment.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragment.java
@@ -12,308 +12,308 @@ import java.util.Map;
/** ASM Code Fragment with register/variable bindings that can be used for generating ASM code for a specific statement . */
public class AsmFragment {
- /** The symbol table. */
- private Program program;
+ /** The symbol table. */
+ private Program program;
- /** The name of the fragment used in error messages. */
- private String name;
+ /** The name of the fragment used in error messages. */
+ private String name;
- /** The fragment template for the ASM code. */
- private AsmFragmentTemplate fragmentTemplate;
+ /** The fragment template for the ASM code. */
+ private AsmFragmentTemplate fragmentTemplate;
- /** Binding of named values in the fragment to values (constants, variables, ...) . */
- private Map bindings;
+ /** Binding of named values in the fragment to values (constants, variables, ...) . */
+ private Map bindings;
- /** The scope containing the fragment. Used when referencing symbols defined in other scopes. */
- private ScopeRef codeScopeRef;
+ /** The scope containing the fragment. Used when referencing symbols defined in other scopes. */
+ private ScopeRef codeScopeRef;
- public AsmFragment(
- Program program,
- String name,
- ScopeRef codeScopeRef,
- AsmFragmentTemplate fragmentTemplate,
- Map bindings) {
- this.program = program;
- this.name = name;
- this.fragmentTemplate = fragmentTemplate;
- this.bindings = bindings;
- this.codeScopeRef = codeScopeRef;
- }
+ public AsmFragment(
+ Program program,
+ String name,
+ ScopeRef codeScopeRef,
+ AsmFragmentTemplate fragmentTemplate,
+ Map bindings) {
+ this.program = program;
+ this.name = name;
+ this.fragmentTemplate = fragmentTemplate;
+ this.bindings = bindings;
+ this.codeScopeRef = codeScopeRef;
+ }
- public Value getBinding(String name) {
- return bindings.get(name);
- }
+ public Value getBinding(String name) {
+ return bindings.get(name);
+ }
- /**
- * Get the value to replace a bound name with from the fragment signature
- *
- * @param name The name of the bound value in the fragment
- * @return The bound value to use in the generated ASM code
- */
- public AsmParameter getBoundValue(String name) {
- Value boundValue = null;
- if (name.length() == 2) {
- // Short name!
- for (String boundName : bindings.keySet()) {
- if (boundName.substring(boundName.length() - 2).equals(name)) {
- boundValue = getBinding(boundName);
- break;
- }
+ /**
+ * Get the value to replace a bound name with from the fragment signature
+ *
+ * @param name The name of the bound value in the fragment
+ * @return The bound value to use in the generated ASM code
+ */
+ public AsmParameter getBoundValue(String name) {
+ Value boundValue = null;
+ if(name.length() == 2) {
+ // Short name!
+ for(String boundName : bindings.keySet()) {
+ if(boundName.substring(boundName.length() - 2).equals(name)) {
+ boundValue = getBinding(boundName);
+ break;
}
- } else {
- // Long name
- boundValue = getBinding(name);
- }
+ }
+ } else {
+ // Long name
+ boundValue = getBinding(name);
+ }
- if (boundValue == null) {
- throw new RuntimeException("Binding '" + name + "' not found in fragment " + this.name + ".asm");
- }
- if (boundValue instanceof Variable) {
- Variable boundVar = (Variable) boundValue;
- Registers.Register register = boundVar.getAllocation();
- if (register != null && register instanceof Registers.RegisterZp) {
- return new AsmParameter(AsmFormat.getAsmParamName(boundVar, codeScopeRef), true);
- } else {
- throw new RuntimeException("Register Type not implemented " + register);
- }
- } else if (boundValue instanceof ConstantVar) {
- ConstantVar constantVar = (ConstantVar) boundValue;
- String constantValueAsm = AsmFormat.getAsmConstant(program, constantVar.getRef(), 99, codeScopeRef);
- boolean constantValueZp = SymbolType.BYTE.equals(constantVar.getType(program.getScope()));
- return new AsmParameter(constantValueAsm, constantValueZp);
- } else if (boundValue instanceof ConstantValue) {
- ConstantValue boundConst = (ConstantValue) boundValue;
- String constantValueAsm = AsmFormat.getAsmConstant(program, boundConst, 99, codeScopeRef);
- boolean constantValueZp = SymbolType.BYTE.equals(boundConst.getType(program.getScope()));
- return new AsmParameter(constantValueAsm, constantValueZp);
- } else if (boundValue instanceof Label) {
- String param = ((Label) boundValue).getLocalName().replace('@', 'b').replace(':', '_').replace("$", "_");
- return new AsmParameter(param, false);
- } else {
- throw new RuntimeException("Bound Value Type not implemented " + boundValue);
- }
- }
+ if(boundValue == null) {
+ throw new RuntimeException("Binding '" + name + "' not found in fragment " + this.name + ".asm");
+ }
+ if(boundValue instanceof Variable) {
+ Variable boundVar = (Variable) boundValue;
+ Registers.Register register = boundVar.getAllocation();
+ if(register != null && register instanceof Registers.RegisterZp) {
+ return new AsmParameter(AsmFormat.getAsmParamName(boundVar, codeScopeRef), true);
+ } else {
+ throw new RuntimeException("Register Type not implemented " + register);
+ }
+ } else if(boundValue instanceof ConstantVar) {
+ ConstantVar constantVar = (ConstantVar) boundValue;
+ String constantValueAsm = AsmFormat.getAsmConstant(program, constantVar.getRef(), 99, codeScopeRef);
+ boolean constantValueZp = SymbolType.BYTE.equals(constantVar.getType(program.getScope()));
+ return new AsmParameter(constantValueAsm, constantValueZp);
+ } else if(boundValue instanceof ConstantValue) {
+ ConstantValue boundConst = (ConstantValue) boundValue;
+ String constantValueAsm = AsmFormat.getAsmConstant(program, boundConst, 99, codeScopeRef);
+ boolean constantValueZp = SymbolType.BYTE.equals(boundConst.getType(program.getScope()));
+ return new AsmParameter(constantValueAsm, constantValueZp);
+ } else if(boundValue instanceof Label) {
+ String param = ((Label) boundValue).getLocalName().replace('@', 'b').replace(':', '_').replace("$", "_");
+ return new AsmParameter(param, false);
+ } else {
+ throw new RuntimeException("Bound Value Type not implemented " + boundValue);
+ }
+ }
- public String getFragmentName() {
- return name;
- }
+ public String getFragmentName() {
+ return name;
+ }
- /**
- * A parameter of an ASM instruction from a bound value.
- */
- public static class AsmParameter {
+ /**
+ * Generate assembler code for the assembler fragment.
+ *
+ * @param asm The assembler sequence to generate into.
+ */
+ public void generate(AsmProgram asm) {
+ AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(name, this, asm);
+ asmSequenceGenerator.generate(fragmentTemplate.getBodyAsm());
+ }
- private String param;
- private boolean zp;
+ /**
+ * A parameter of an ASM instruction from a bound value.
+ */
+ public static class AsmParameter {
- public AsmParameter(String param, boolean zp) {
- this.param = param;
- this.zp = zp;
- }
+ private String param;
+ private boolean zp;
- public String getParam() {
- return param;
- }
+ public AsmParameter(String param, boolean zp) {
+ this.param = param;
+ this.zp = zp;
+ }
- public boolean isZp() {
- return zp;
- }
- }
+ public String getParam() {
+ return param;
+ }
- /**
- * Generate assembler code for the assembler fragment.
- *
- * @param asm The assembler sequence to generate into.
- */
- public void generate(AsmProgram asm) {
- AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(name, this, asm);
- asmSequenceGenerator.generate(fragmentTemplate.getBodyAsm());
- }
+ public boolean isZp() {
+ return zp;
+ }
+ }
- private static class AsmSequenceGenerator extends KickCBaseVisitor {
+ private static class AsmSequenceGenerator extends KickCBaseVisitor {
- private String name;
- private AsmProgram program;
- private AsmFragment bindings;
+ private String name;
+ private AsmProgram program;
+ private AsmFragment bindings;
- public AsmSequenceGenerator(String name, AsmFragment bindings, AsmProgram program) {
- this.name = name;
- this.bindings = bindings;
- this.program = program;
- }
+ public AsmSequenceGenerator(String name, AsmFragment bindings, AsmProgram program) {
+ this.name = name;
+ this.bindings = bindings;
+ this.program = program;
+ }
- public AsmProgram getProgram() {
- return program;
- }
+ public AsmProgram getProgram() {
+ return program;
+ }
- public void generate(KickCParser.AsmLinesContext context) {
- this.visit(context);
- }
+ public void generate(KickCParser.AsmLinesContext context) {
+ this.visit(context);
+ }
- @Override
- public Object visitAsmLabel(KickCParser.AsmLabelContext ctx) {
- program.addLine(new AsmLabel(ctx.getChild(0).getText()));
- return null;
- }
+ @Override
+ public Object visitAsmLabel(KickCParser.AsmLabelContext ctx) {
+ program.addLine(new AsmLabel(ctx.getChild(0).getText()));
+ return null;
+ }
- @Override
- public Object visitAsmBytes(KickCParser.AsmBytesContext ctx) {
- ArrayList values = new ArrayList<>();
- for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
- values.add(ctx.getChild(i).getText());
- }
- program.addLine(new AsmDataNumeric(null, AsmDataNumeric.Type.BYTE, values));
- return null;
- }
+ @Override
+ public Object visitAsmBytes(KickCParser.AsmBytesContext ctx) {
+ ArrayList values = new ArrayList<>();
+ for(int i = 1; i < ctx.getChildCount(); i = i + 2) {
+ values.add(ctx.getChild(i).getText());
+ }
+ program.addLine(new AsmDataNumeric(null, AsmDataNumeric.Type.BYTE, values));
+ return null;
+ }
- @Override
- public Object visitAsmInstruction(KickCParser.AsmInstructionContext ctx) {
- KickCParser.AsmParamModeContext paramModeCtx = ctx.asmParamMode();
- AsmInstruction instruction;
- if (paramModeCtx == null) {
- AsmInstructionType type = AsmInstructionSet.getInstructionType(
- ctx.MNEMONIC().getText(),
- AsmAddressingMode.NON,
- false);
- instruction = new AsmInstruction(type, null);
- } else {
- instruction = (AsmInstruction) this.visit(paramModeCtx);
- }
- if (instruction != null) {
- program.addLine(instruction);
- } else {
- throw new RuntimeException("Error parsing ASM fragment line in dk/camelot64/kickc/fragment/asm/" + name + ".asm\n - Line: " + ctx.getText());
- }
- return null;
- }
-
- @Override
- public Object visitAsmModeAbs(KickCParser.AsmModeAbsContext ctx) {
- return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABS);
- }
-
- @Override
- public Object visitAsmModeImm(KickCParser.AsmModeImmContext ctx) {
- return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IMM);
- }
-
- @Override
- public Object visitAsmModeAbsXY(KickCParser.AsmModeAbsXYContext ctx) {
- String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
- if (xy.equals("x")) {
- return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABX);
- } else if (xy.equals("y")) {
- return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABY);
- } else {
- throw new RuntimeException("Unknown addressing mode " + ctx.getText());
- }
- }
-
- @Override
- public Object visitAsmModeIndIdxXY(KickCParser.AsmModeIndIdxXYContext ctx) {
- String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
- if (xy.equals("y")) {
- return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IZY);
- } else {
- throw new RuntimeException("Unknown addressing mode " + ctx.getText());
- }
- }
-
- @Override
- public Object visitAsmModeIdxIndXY(KickCParser.AsmModeIdxIndXYContext ctx) {
- String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
- if (xy.equals("x")) {
- return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IZX);
- } else {
- throw new RuntimeException("Unknown addressing mode " + ctx.getText());
- }
- }
-
- @Override
- public Object visitAsmModeInd(KickCParser.AsmModeIndContext ctx) {
- return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IND);
- }
-
- private AsmInstruction createAsmInstruction(
- KickCParser.AsmParamModeContext ctx,
- KickCParser.AsmExprContext exprCtx,
- AsmAddressingMode addressingMode) {
- KickCParser.AsmInstructionContext instructionCtx = (KickCParser.AsmInstructionContext) ctx.getParent();
- String mnemonic = instructionCtx.MNEMONIC().getSymbol().getText();
- AsmParameter parameter = (AsmParameter) this.visit(exprCtx);
+ @Override
+ public Object visitAsmInstruction(KickCParser.AsmInstructionContext ctx) {
+ KickCParser.AsmParamModeContext paramModeCtx = ctx.asmParamMode();
+ AsmInstruction instruction;
+ if(paramModeCtx == null) {
AsmInstructionType type = AsmInstructionSet.getInstructionType(
- mnemonic,
- addressingMode,
- parameter.isZp());
- if (type == null) {
- throw new RuntimeException("Error in " + name + ".asm line " + ctx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + addressingMode + " " + parameter);
- }
- return new AsmInstruction(type, parameter.getParam());
- }
+ ctx.MNEMONIC().getText(),
+ AsmAddressingMode.NON,
+ false);
+ instruction = new AsmInstruction(type, null);
+ } else {
+ instruction = (AsmInstruction) this.visit(paramModeCtx);
+ }
+ if(instruction != null) {
+ program.addLine(instruction);
+ } else {
+ throw new RuntimeException("Error parsing ASM fragment line in dk/camelot64/kickc/fragment/asm/" + name + ".asm\n - Line: " + ctx.getText());
+ }
+ return null;
+ }
- @Override
- public AsmParameter visitAsmExprBinary(KickCParser.AsmExprBinaryContext ctx) {
- AsmParameter left = (AsmParameter) this.visit(ctx.asmExpr(0));
- AsmParameter right = (AsmParameter) this.visit(ctx.asmExpr(1));
- String param = "" + left.getParam() + ctx.getChild(1).getText() + right.getParam();
- boolean zp = left.isZp() && right.isZp();
- return new AsmParameter(param, zp);
- }
+ @Override
+ public Object visitAsmModeAbs(KickCParser.AsmModeAbsContext ctx) {
+ return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABS);
+ }
- @Override
- public AsmParameter visitAsmExprUnary(KickCParser.AsmExprUnaryContext ctx) {
- AsmParameter sub = (AsmParameter) this.visit(ctx.asmExpr());
- String operator = ctx.getChild(0).getText();
- String param = operator + sub.getParam();
- boolean isZp = sub.isZp();
- if (operator.equals("<") || operator.equals(">")) {
- isZp = true;
- }
- return new AsmParameter(param, isZp);
- }
+ @Override
+ public Object visitAsmModeImm(KickCParser.AsmModeImmContext ctx) {
+ return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IMM);
+ }
- @Override
- public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) {
- Number number = NumberParser.parseLiteral(ctx.NUMBER().getText());
- ConstantInteger intVal = new ConstantInteger(number.intValue());
- boolean isZp = SymbolType.isByte(intVal.getType()) || SymbolType.isSByte(intVal.getType());
- String param = AsmFormat.getAsmNumber(number);
- return new AsmParameter(param, isZp);
- }
+ @Override
+ public Object visitAsmModeAbsXY(KickCParser.AsmModeAbsXYContext ctx) {
+ String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
+ if(xy.equals("x")) {
+ return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABX);
+ } else if(xy.equals("y")) {
+ return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.ABY);
+ } else {
+ throw new RuntimeException("Unknown addressing mode " + ctx.getText());
+ }
+ }
- @Override
- public Object visitAsmExprChar(KickCParser.AsmExprCharContext ctx) {
- return new AsmParameter(ctx.getText(), true);
- }
+ @Override
+ public Object visitAsmModeIndIdxXY(KickCParser.AsmModeIndIdxXYContext ctx) {
+ String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
+ if(xy.equals("y")) {
+ return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IZY);
+ } else {
+ throw new RuntimeException("Unknown addressing mode " + ctx.getText());
+ }
+ }
- @Override
- public AsmParameter visitAsmExprLabel(KickCParser.AsmExprLabelContext ctx) {
- String param = ctx.NAME().getSymbol().getText();
- return new AsmParameter(param, false);
- }
+ @Override
+ public Object visitAsmModeIdxIndXY(KickCParser.AsmModeIdxIndXYContext ctx) {
+ String xy = ctx.getChild(ctx.getChildCount() - 1).getText();
+ if(xy.equals("x")) {
+ return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IZX);
+ } else {
+ throw new RuntimeException("Unknown addressing mode " + ctx.getText());
+ }
+ }
- @Override
- public Object visitAsmExprLabelRel(KickCParser.AsmExprLabelRelContext ctx) {
- String param = ctx.ASMREL().getSymbol().getText();
- return new AsmParameter(param, false);
- }
+ @Override
+ public Object visitAsmModeInd(KickCParser.AsmModeIndContext ctx) {
+ return createAsmInstruction(ctx, ctx.asmExpr(), AsmAddressingMode.IND);
+ }
- @Override
- public AsmParameter visitAsmExprReplace(KickCParser.AsmExprReplaceContext ctx) {
- String replaceName = ctx.NAME().getSymbol().getText();
- return bindings.getBoundValue(replaceName);
- }
- }
+ private AsmInstruction createAsmInstruction(
+ KickCParser.AsmParamModeContext ctx,
+ KickCParser.AsmExprContext exprCtx,
+ AsmAddressingMode addressingMode) {
+ KickCParser.AsmInstructionContext instructionCtx = (KickCParser.AsmInstructionContext) ctx.getParent();
+ String mnemonic = instructionCtx.MNEMONIC().getSymbol().getText();
+ AsmParameter parameter = (AsmParameter) this.visit(exprCtx);
+ AsmInstructionType type = AsmInstructionSet.getInstructionType(
+ mnemonic,
+ addressingMode,
+ parameter.isZp());
+ if(type == null) {
+ throw new RuntimeException("Error in " + name + ".asm line " + ctx.getStart().getLine() + " - Instruction type unknown " + mnemonic + " " + addressingMode + " " + parameter);
+ }
+ return new AsmInstruction(type, parameter.getParam());
+ }
- public static class AluNotApplicableException extends RuntimeException {
+ @Override
+ public AsmParameter visitAsmExprBinary(KickCParser.AsmExprBinaryContext ctx) {
+ AsmParameter left = (AsmParameter) this.visit(ctx.asmExpr(0));
+ AsmParameter right = (AsmParameter) this.visit(ctx.asmExpr(1));
+ String param = "" + left.getParam() + ctx.getChild(1).getText() + right.getParam();
+ boolean zp = left.isZp() && right.isZp();
+ return new AsmParameter(param, zp);
+ }
- public AluNotApplicableException() {
- super("ALU register not appicable.");
- }
+ @Override
+ public AsmParameter visitAsmExprUnary(KickCParser.AsmExprUnaryContext ctx) {
+ AsmParameter sub = (AsmParameter) this.visit(ctx.asmExpr());
+ String operator = ctx.getChild(0).getText();
+ String param = operator + sub.getParam();
+ boolean isZp = sub.isZp();
+ if(operator.equals("<") || operator.equals(">")) {
+ isZp = true;
+ }
+ return new AsmParameter(param, isZp);
+ }
- public AluNotApplicableException(String message) {
- super(message);
- }
- }
+ @Override
+ public AsmParameter visitAsmExprInt(KickCParser.AsmExprIntContext ctx) {
+ Number number = NumberParser.parseLiteral(ctx.NUMBER().getText());
+ ConstantInteger intVal = new ConstantInteger(number.intValue());
+ boolean isZp = SymbolType.isByte(intVal.getType()) || SymbolType.isSByte(intVal.getType());
+ String param = AsmFormat.getAsmNumber(number);
+ return new AsmParameter(param, isZp);
+ }
+
+ @Override
+ public Object visitAsmExprChar(KickCParser.AsmExprCharContext ctx) {
+ return new AsmParameter(ctx.getText(), true);
+ }
+
+ @Override
+ public AsmParameter visitAsmExprLabel(KickCParser.AsmExprLabelContext ctx) {
+ String param = ctx.NAME().getSymbol().getText();
+ return new AsmParameter(param, false);
+ }
+
+ @Override
+ public Object visitAsmExprLabelRel(KickCParser.AsmExprLabelRelContext ctx) {
+ String param = ctx.ASMREL().getSymbol().getText();
+ return new AsmParameter(param, false);
+ }
+
+ @Override
+ public AsmParameter visitAsmExprReplace(KickCParser.AsmExprReplaceContext ctx) {
+ String replaceName = ctx.NAME().getSymbol().getText();
+ return bindings.getBoundValue(replaceName);
+ }
+ }
+
+ public static class AluNotApplicableException extends RuntimeException {
+
+ public AluNotApplicableException() {
+ super("ALU register not appicable.");
+ }
+
+ public AluNotApplicableException(String message) {
+ super(message);
+ }
+ }
}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java
index 62aeeccf4..70012c431 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentManager.java
@@ -19,535 +19,531 @@ import java.util.*;
*/
public class AsmFragmentManager {
- /** Cache for the best fragment templates. Maps signature to the best fragment template for the signature. */
- private static Map bestFragmentCache = new HashMap<>();
+ /** Cache for the best fragment templates. Maps signature to the best fragment template for the signature. */
+ private static Map bestFragmentCache = new HashMap<>();
- /** Caches all asm fragment templates for all encountered signatures. */
- private static Map> fragmentTemplateCache = new LinkedHashMap<>();
+ /** Caches all asm fragment templates for all encountered signatures. */
+ private static Map> fragmentTemplateCache = new LinkedHashMap<>();
- /** Special singleton representing that the fragment can not be synthesized or loaded. */
- private static AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
+ /** Special singleton representing that the fragment can not be synthesized or loaded. */
+ private static AsmFragmentTemplate UNKNOWN = new AsmFragmentTemplate("UNKNOWN", null);
+ /**
+ * All the synthesize rules available.
+ */
+ private static List fragmentSyntheses;
- static Map> getFragmentTemplateCache() {
- return fragmentTemplateCache;
- }
+ static Map> getFragmentTemplateCache() {
+ return fragmentTemplateCache;
+ }
- public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) {
- AsmFragmentTemplate bestTemplate = bestFragmentCache.get(signature.getSignature());
- if (bestTemplate == UNKNOWN) {
- if (log.isVerboseFragmentLog()) {
- log.append("Unknown fragment " + signature.getSignature());
+ public static AsmFragment getFragment(AsmFragmentSignature signature, CompileLog log) {
+ AsmFragmentTemplate bestTemplate = bestFragmentCache.get(signature.getSignature());
+ if(bestTemplate == UNKNOWN) {
+ if(log.isVerboseFragmentLog()) {
+ log.append("Unknown fragment " + signature.getSignature());
+ }
+ throw new UnknownFragmentException(signature.toString());
+ }
+ if(bestTemplate == null) {
+ AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateSynthesizer(signature.getSignature(), log);
+ List candidates = synthesizer.loadOrSynthesizeFragment(signature.getSignature(), new AsmSynthesisPath());
+ if(candidates.size() == 0) {
+ if(log.isVerboseFragmentLog()) {
+ log.append("Unknown fragment " + signature.toString());
}
+ bestFragmentCache.put(signature.getSignature(), UNKNOWN);
throw new UnknownFragmentException(signature.toString());
- }
- if (bestTemplate == null) {
- AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentTemplateSynthesizer(signature.getSignature(), log);
- List candidates = synthesizer.loadOrSynthesizeFragment(signature.getSignature(), new AsmSynthesisPath());
- if (candidates.size() == 0) {
- if (log.isVerboseFragmentLog()) {
- log.append("Unknown fragment " + signature.toString());
- }
- bestFragmentCache.put(signature.getSignature(), UNKNOWN);
- throw new UnknownFragmentException(signature.toString());
+ }
+ double minScore = Double.MAX_VALUE;
+ double maxScore = Double.MIN_VALUE;
+ AsmFragmentTemplate maxTemplate = null;
+ for(AsmFragmentTemplate candidateTemplate : candidates) {
+ AsmFragment candidateFragment = new AsmFragment(
+ signature.getProgram(),
+ signature.getSignature(),
+ signature.getCodeScope(),
+ candidateTemplate,
+ signature.getBindings());
+ AsmProgram candidateAsm = new AsmProgram();
+ candidateAsm.startSegment(null, signature.toString());
+ candidateFragment.generate(candidateAsm);
+ double score = candidateAsm.getCycles();
+ if(score < minScore) {
+ minScore = score;
+ bestTemplate = candidateTemplate;
}
- double minScore = Double.MAX_VALUE;
- double maxScore = Double.MIN_VALUE;
- AsmFragmentTemplate maxTemplate = null;
- for (AsmFragmentTemplate candidateTemplate : candidates) {
- AsmFragment candidateFragment = new AsmFragment(
- signature.getProgram(),
- signature.getSignature(),
- signature.getCodeScope(),
- candidateTemplate,
- signature.getBindings());
- AsmProgram candidateAsm = new AsmProgram();
- candidateAsm.startSegment(null, signature.toString());
- candidateFragment.generate(candidateAsm);
- double score = candidateAsm.getCycles();
- if (score < minScore) {
- minScore = score;
- bestTemplate = candidateTemplate;
- }
- if (score > maxScore) {
- maxScore = score;
- maxTemplate = candidateTemplate;
- }
+ if(score > maxScore) {
+ maxScore = score;
+ maxTemplate = candidateTemplate;
}
- if (log.isVerboseFragmentLog()) {
- log.append("Found fragment " + bestTemplate.getName() + " score: " + minScore + " from " + candidates.size() + " candidates");
+ }
+ if(log.isVerboseFragmentLog()) {
+ log.append("Found fragment " + bestTemplate.getName() + " score: " + minScore + " from " + candidates.size() + " candidates");
+ }
+ bestFragmentCache.put(signature.getSignature(), bestTemplate);
+ }
+ // Count usages
+ AsmFragmentUsages.incUsage(bestTemplate);
+ // Return the resulting fragment instance
+ return new AsmFragment(
+ signature.getProgram(),
+ signature.getSignature(),
+ signature.getCodeScope(),
+ bestTemplate,
+ signature.getBindings());
+ }
+
+ /**
+ * Look for a fragment on the disk.
+ *
+ * @param signature The fragment signature
+ * @return The fragment file contents. Null if the fragment is not on the disk.
+ */
+ private static CharStream loadFragment(String signature) {
+ ClassLoader classLoader = AsmFragmentManager.class.getClassLoader();
+ URL fragmentUrl = classLoader.getResource("dk/camelot64/kickc/fragment/asm/" + signature + ".asm");
+ if(fragmentUrl == null) {
+ return null;
+ }
+ try {
+ InputStream fragmentStream = fragmentUrl.openStream();
+ return CharStreams.fromStream(fragmentStream);
+ } catch(IOException e) {
+ throw new RuntimeException("Error loading fragment file " + fragmentUrl);
+ }
+ }
+
+ static File[] allFragmentFiles() {
+ ClassLoader classLoader = AsmFragmentManager.class.getClassLoader();
+ String path = classLoader.getResource("dk/camelot64/kickc/fragment/asm/").getPath();
+ return new File(path).listFiles((dir, name) -> name.endsWith(".asm"));
+
+ }
+
+ private static List getFragmentSyntheses() {
+ if(fragmentSyntheses == null) {
+ fragmentSyntheses = initFragmentSyntheses();
+ }
+ return fragmentSyntheses;
+ }
+
+ private static List initFragmentSyntheses() {
+ Map mapZ = new LinkedHashMap<>();
+ mapZ.put("z2", "z1");
+ mapZ.put("z3", "z2");
+ Map mapZ2 = new LinkedHashMap<>();
+ mapZ2.put("z3", "z1");
+ Map mapZ3 = new LinkedHashMap<>();
+ mapZ3.put("z3", "z2");
+ Map mapC = new LinkedHashMap<>();
+ mapC.put("c2", "c1");
+ mapC.put("c3", "c2");
+ Map mapC3 = new LinkedHashMap<>();
+ mapC3.put("c3", "c2");
+ Map mapZC = new LinkedHashMap<>();
+ mapZC.putAll(mapZ);
+ mapZC.putAll(mapC);
+ Map mapSToU = new LinkedHashMap<>();
+ mapSToU.put("vbsz1", "vbuz1");
+ mapSToU.put("vbsz2", "vbuz2");
+ mapSToU.put("vbsz3", "vbuz3");
+ mapSToU.put("vbsc1", "vbuc1");
+ mapSToU.put("vbsc2", "vbuc2");
+ mapSToU.put("vbsc3", "vbuc3");
+ mapSToU.put("vbsaa", "vbuaa");
+ mapSToU.put("vbsxx", "vbuxx");
+ mapSToU.put("vbsyy", "vbuyy");
+ mapSToU.put("vwsz1", "vwuz1");
+ mapSToU.put("vwsz2", "vwuz2");
+ mapSToU.put("vwsz3", "vwuz3");
+ mapSToU.put("vwsc1", "vwuc1");
+ mapSToU.put("vwsc2", "vwuc2");
+ mapSToU.put("vwsc3", "vwuc3");
+
+ List synths = new ArrayList<>();
+
+ // NEW STYLE REWRITES - Utilizes that all combinations are tried
+
+ // Replace first AA with XX
+ synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1xx$2", null, null));
+ // Replace two AAs with XX
+ synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1xx$2xx$3", null, null));
+ // Replace second (not first) AA with XX
+ synths.add(new AsmFragmentSynthesis("(.*)aa(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1aa$2xx$3", null, null));
+
+ // Replace first AA with YY
+ synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1yy$2", null, null));
+ // Replace two AAs with YY
+ synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1yy$2yy$3", null, null));
+ // Replace second (not first) AA with YY
+ synths.add(new AsmFragmentSynthesis("(.*)aa(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1aa$2yy$3", null, null));
+
+ // Replace first XX with AA
+ synths.add(new AsmFragmentSynthesis("(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1aa$2", null, null));
+ // Replace two XXs with AA
+ synths.add(new AsmFragmentSynthesis("(.*vb.)xx(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1aa$2aa$3", null, null));
+ // Replace second (not first) XX with AA
+ synths.add(new AsmFragmentSynthesis("(.*)xx(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1xx$2aa$3", null, null));
+
+ // Replace first YY with AA
+ synths.add(new AsmFragmentSynthesis("(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1aa$2", null, null));
+ // Replace two YYs with AA
+ synths.add(new AsmFragmentSynthesis("(.*vb.)yy(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1aa$2aa$3", null, null));
+ // Replace second (not first) YY with AA
+ synths.add(new AsmFragmentSynthesis("(.*)yy(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1yy$2aa$3", null, null));
+
+ // Replace Z1 with AA (only one)
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*aa.*", "lda {z1}", "$1aa$2", null, mapZ));
+ // Replace two Z1s with AA
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*aa.*", "lda {z1}", "$1aa$2aa$3", null, mapZ));
+ // Replace first (not second) Z1 with AA
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*aa.*", "lda {z1}", "$1aa$2z1$3", null, null));
+ // Replace second (not first) Z1 with AA
+ synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*aa.*", "lda {z1}", "$1z1$2aa$3", null, null));
+
+ // Replace Z1 with YY (only one)
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*yy.*", "ldy {z1}", "$1yy$2", null, mapZ));
+ // Replace two Z1s with YY
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*yy.*", "ldy {z1}", "$1yy$2yy$3", null, mapZ));
+ // Replace first (not second) Z1 with YY
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*yy.*", "ldy {z1}", "$1yy$2z1$3", null, null));
+ // Replace second (not first) Z1 with YY
+ synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*yy.*", "ldy {z1}", "$1z1$2yy$3", null, null));
+
+ // Replace Z1 with XX (only one)
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*xx.*", "ldx {z1}", "$1xx$2", null, mapZ));
+ // Replace two Z1s with XX
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*xx.*", "ldx {z1}", "$1xx$2xx$3", null, mapZ));
+ // Replace first (not second) Z1 with XX
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*xx.*", "ldx {z1}", "$1xx$2z1$3", null, null));
+ // Replace second (not first) Z1 with XX
+ synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*xx.*", "ldx {z1}", "$1z1$2xx$3", null, null));
+
+ // Replace Z2 with AA (only one)
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*aa.*", "lda {z2}", "$1aa$2", null, mapZ3));
+ // Replace two Z2s with AA
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*aa.*", "lda {z2}", "$1aa$2aa$3", null, mapZ3));
+ // Replace first (of 2) Z2 with AA
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*aa.*", "lda {z2}", "$1aa$2z2$3", null, null));
+ // Replace second (of 2) Z2 with AA
+ synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*aa.*", "lda {z2}", "$1z2$2aa$3", null, null));
+
+ // Replace Z2 with YY (only one)
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*yy.*", "ldy {z2}", "$1yy$2", null, mapZ3));
+ // Replace two Z2s with YY
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*yy.*", "ldy {z2}", "$1yy$2yy$3", null, mapZ3));
+ // Replace first (of 2) Z2 with YY
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*yy.*", "ldy {z2}", "$1yy$2z2$3", null, null));
+ // Replace second (of 2) Z2 with YY
+ synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*yy.*", "ldy {z2}", "$1z2$2yy$3", null, null));
+
+ // Replace Z2 with XX(only one)
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*xx.*", "ldx {z2}", "$1xx$2", null, mapZ3));
+ // Replace two Z2s with XX
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*xx.*", "ldx {z2}", "$1xx$2xx$3", null, mapZ3));
+ // Replace first (of 2) Z2 with XX
+ synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*xx.*", "ldx {z2}", "$1xx$2z2$3", null, null));
+ // Replace second (of 2) Z2 with XX
+ synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*xx.*", "ldx {z2}", "$1z2$2xx$3", null, null));
+
+
+ // OLD STYLE REWRITES - written when only one rule could be taken
+
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.aa)", ".*=vb.aa_.*", null, "$1=$4_$3_$2", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.xx)", ".*=vb.[ax][ax]_.*", null, "$1=$4_$3_$2", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.yy)", ".*=vb.[axy][axy]_.*", null, "$1=$4_$3_$2", null, null));
+
+ synths.add(new AsmFragmentSynthesis("vbuxx=(.*)", null, null, "vbuaa=$1", "tax\n", null));
+ synths.add(new AsmFragmentSynthesis("vbsxx=(.*)", null, null, "vbsaa=$1", "tax\n", null));
+ synths.add(new AsmFragmentSynthesis("vbuyy=(.*)", null, null, "vbuaa=$1", "tay\n", null));
+ synths.add(new AsmFragmentSynthesis("vbsyy=(.*)", null, null, "vbsaa=$1", "tay\n", null));
+ synths.add(new AsmFragmentSynthesis("vbuz1=(.*)", ".*=.*vb.z1.*", null, "vbuaa=$1", "sta {z1}\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("vbsz1=(.*)", ".*=.*vb.z1.*", null, "vbsaa=$1", "sta {z1}\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1}\n", mapC));
+ synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1=(.*c1.*)", null, null, "vb$1aa=$2", "sta {c1}\n", null));
+ synths.add(new AsmFragmentSynthesis("_deref_pbuz1=(.*)", ".*z1.*z1.*", null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("_deref_pbuz1=(.*z1.*)", null, null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y\n", null));
+
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*)", ".*z1.*z1.*|.*c1.*c1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapZC));
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},y\n", mapC));
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},x\n", mapC));
+ synths.add(new AsmFragmentSynthesis("pb(.)z1_derefidx_vbuz2=(.*)", ".*z1.*z1.*|.*z2.*z2.*", null, "vb$1aa=$2", "ldy {z2}\n" + "sta ({z1}),y\n", mapZ2));
+
+ synths.add(new AsmFragmentSynthesis("(.*)=_deref_pb(.)c1(.*)", ".*=.*aa.*", "lda {c1}\n", "$1=vb$2aa$3", null, mapC));
+ synths.add(new AsmFragmentSynthesis("(.*)=_deref_pb(.)z1(.*)", ".*z1.*z1.*|.*=.*aa.*|.*=.*yy.*", "ldy #0\n" + "lda ({z1}),y\n", "$1=vb$2aa$3", null, mapZ));
+
+ // Convert array indexing with A register to X/Y register by prefixing tax/tay (..._derefidx_vbuaa... -> ..._derefidx_vbuxx... /... _derefidx_vbuyy... )
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuaa(.*)", ".*=.*xx.*", "tax\n", "$1=$2_derefidx_vbuxx$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuaa(.*)", ".*=.*yy.*", "tay\n", "$1=$2_derefidx_vbuyy$3", null, null));
+ // Convert array indexing with zero page to x/y register by prefixing ldx z1 / ldy z1 ( ..._derefidx_vbuzn... -> ..._derefidx_vbuxx... / ..._derefidx_vbuyy... )
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz1(.*)", ".*=.*xx.*|.*z1.*z1.*", "ldx {z1}\n", "$1=$2_derefidx_vbuxx$3", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz1(.*)", ".*=.*yy.*|.*z1.*z1.*", "ldy {z1}\n", "$1=$2_derefidx_vbuyy$3", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz2(.*)", ".*=.*xx.*|.*z2.*z2.*", "ldx {z2}\n", "$1=$2_derefidx_vbuxx$3", null, mapZ3));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz2(.*)", ".*=.*yy.*|.*z2.*z2.*", "ldy {z2}\n", "$1=$2_derefidx_vbuyy$3", null, mapZ3));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz3(.*)", ".*=.*yy.*", "ldy {z3}\n", "$1=$2_derefidx_vbuyy$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz3(.*)", ".*=.*xx.*", "ldx {z3}\n", "$1=$2_derefidx_vbuxx$3", null, null));
+ // Convert array indexing twice with A/zp1/zp2 to X/Y register with a ldx/ldy prefix ( ..._derefidx_vbunn..._derefidx_vbunn... -> ..._derefidx_vbuxx..._derefidx_vbuxx... )
+ synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuaa(.*)_derefidx_vbuaa(.*)", ".*aa.*aa.*aa.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "tax\n", null));
+ synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuaa(.*)_derefidx_vbuaa(.*)", ".*aa.*aa.*aa.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "tay\n", null));
+ synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1(.*)_derefidx_vbuz1(.*)", ".*z1.*z1.*z1.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "ldx {z1}\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1(.*)_derefidx_vbuz1(.*)", ".*z1.*z1.*z1.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "ldy {z1}\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz2(.*)_derefidx_vbuz2(.*)", ".*z2.*z2.*z2.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "ldx {z2}\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz2(.*)_derefidx_vbuz2(.*)", ".*z2.*z2.*z2.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "ldy {z2}\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*c1.*)", ".*z1.*z1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*z1.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapC));
+
+ // Convert X/Y-based array indexing of a constant pointer into A-register by prefixing lda cn,x / lda cn,y ( ...pb.c1_derefidx_vbuxx... / ...pb.c1_derefidx_vbuyy... -> ...vb.aa... )
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuxx(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, mapC));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*c1.*)pb(.)c1_derefidx_vbuxx(.*)", ".*=.*aa.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuxx(.*c1.*)", ".*=.*aa.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuyy(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, mapC));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*c1.*)pb(.)c1_derefidx_vbuyy(.*)", ".*=.*aa.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuyy(.*c1.*)", ".*=.*aa.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuxx(.*)", ".*=.*aa.*|.*c2.*c2.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, mapC3));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*c2.*)pb(.)c2_derefidx_vbuxx(.*)", ".*=.*aa.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuxx(.*c2.*)", ".*=.*aa.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuyy(.*)", ".*=.*aa.*|.*c2.*c2.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, mapC3));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*c2.*)pb(.)c2_derefidx_vbuyy(.*)", ".*=.*aa.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuyy(.*c2.*)", ".*=.*aa.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, null));
+
+ // Convert zeropage/constants/X/Y in assignments to A-register using LDA/TXA/TYA prefix
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz1(.*)", ".*z1.*=.*|.*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2vbuaa$3", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz1(.*)", ".*z1.*=.*|.*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2vbsaa$3", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz2(.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbuaa$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz2(.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbsaa$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz2(.*z3.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbuaa$3", null, mapZ3));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz2(.*z3.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbsaa$3", null, mapZ3));
+
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuxx", ".*=.*[ax][ax].*xx|.*derefidx_vb.xx", "txa\n", "$1=$2_vbuaa", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsxx", ".*=.*[ax][ax].*xx|.*derefidx_vb.xx", "txa\n", "$1=$2_vbsaa", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuyy", ".*=.*[ay][ay].*yy|.*derefidx_vb.yy", "tya\n", "$1=$2_vbuaa", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsyy", ".*=-*[ay][ay].*yy|.*derefidx_vb.yy", "tya\n", "$1=$2_vbsaa", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz1", ".*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2_vbuaa", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsz1", ".*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2_vbsaa", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz2", ".*=.*aa.*|.*z2.*z2.*", "lda {z2}\n", "$1=$2_vbuaa", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz3", ".*=.*aa.*|.*z3.*z3.*", "lda {z3}\n", "$1=$2_vbuaa", null, null));
+
+ synths.add(new AsmFragmentSynthesis("vbuz1=vbuz1(.*)", ".*=.*vb.aa.*|.*z1.*z1.*z1.*", "lda {z1}\n", "vbuaa=vbuaa$1", "sta {z1}\n", mapZ));
+ synths.add(new AsmFragmentSynthesis("vbsz1=vbsz1(.*)", ".*=.*vb.aa.*|.*z1.*z1.*z1.*", "lda {z1}\n", "vbsaa=vbsaa$1", "sta {z1}\n", mapZ));
+
+ synths.add(new AsmFragmentSynthesis("vbuz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*z1.*z1.*", "lda {z1}\n", "vbuaa_$1_$2", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("vbsz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*z1.*z1.*", "lda {z1}\n", "vbsaa_$1_$2", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*", "lda {c1}\n", "vb$1aa_$2_$3", null, mapC));
+ synths.add(new AsmFragmentSynthesis("_deref_pb(.)z1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*vb.yy.*|.*z1.*z1.*", "ldy #0\n" + "lda ({z1}),y\n", "vb$1aa_$2_$3", null, mapZ));
+
+ synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1_(.*)", ".*z1.*z1.*|.*.yy.*", "ldy {z1}\n", "$1_derefidx_vbuyy_$2", null, mapZ));
+
+
+ synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*z1.*z1.*|.*vb.xx.*", "ldx {z1}\n", "$1_derefidx_vbuxx_$2_$3", null, mapZ));
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy_(lt|gt|le|ge|eq|neq)_(.*)", ".*c1.*c1.*|.*aa.*", "lda {c1},y\n", "vb$1aa_$2_$3", null, mapC));
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy_(lt|gt|le|ge|eq|neq)_(.*c1.*)", ".*aa.*", "lda {c1},y\n", "vb$1aa_$2_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx_(lt|gt|le|ge|eq|neq)_(.*)", ".*c1.*c1.*|.*aa.*", "lda {c1},x\n", "vb$1aa_$2_$3", null, mapC));
+ synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx_(lt|gt|le|ge|eq|neq)_(.*c1.*)", ".*aa.*", "lda {c1},x\n", "vb$1aa_$2_$3", null, null));
+
+ synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.aa)_then_(.*)", ".*vb.aa.*_ge.*", null, "$2_lt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_ge.*", null, "$2_lt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_ge.*", null, "$2_lt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.aa)_then_(.*)", ".*vb.aa.*_lt.*", null, "$2_ge_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_lt.*", null, "$2_ge_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_lt.*", null, "$2_ge_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.aa)_then_(.*)", ".*vb.aa.*_gt.*", null, "$2_le_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_gt.*", null, "$2_le_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_gt.*", null, "$2_le_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.aa)_then_(.*)", ".*vb.aa.*_le.*", null, "$2_gt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_le.*", null, "$2_gt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_le.*", null, "$2_gt_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.aa)_then_(.*)", ".*vb.aa.*_neq.*", null, "$2_neq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_neq.*", null, "$2_neq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_neq.*", null, "$2_neq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.aa)_then_(.*)", ".*vb.aa.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_eq.*", null, "$2_eq_$1_then_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_eq.*", null, "$2_eq_$1_then_$3", null, null));
+
+ // Use unsigned ASM to synthesize signed ASM ( ...vbs... -> ...vbu... )
+ synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_(eq|neq)_(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_then_(.*)", null, null, "$1_$2_$3_then_$4", null, mapSToU));
+ synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)", null, null, "$1=$2", null, mapSToU));
+ synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_(plus|band|bxor|bor)_(vbsz.|csoby.|vbsaa|vbsxx|vbsyy)", null, null, "$1=$2_$3_$4", null, mapSToU));
+ synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=_(inc|dec)_(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)", null, null, "$1=_$2_$3", null, mapSToU));
+ synths.add(new AsmFragmentSynthesis("(vwsz.|vwsc.)_(eq|neq)_(vwsz.|vwsc.)_then_(.*)", null, null, "$1_$2_$3_then_$4", null, mapSToU));
+ synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsz.|vwsc.)", null, null, "$1=$2", null, mapSToU));
+ synths.add(new AsmFragmentSynthesis("(v.sz.)=(v.s..)_(band|bxor|bor)_(v.s..)", null, null, "$1=$2_$3_$4", null, mapSToU));
+ synths.add(new AsmFragmentSynthesis("(vbuz.|vbuaa|vbuxx|vbuyy)=_(lo|hi)_vws(z.|c.)", null, null, "$1=_$2_vwu$3", null, mapSToU));
+
+ // Use constant word ASM to synthesize unsigned constant byte ASM ( ...vb.c... -> vw.c... )
+ synths.add(new AsmFragmentSynthesis("(vwuz.)=(vwuz.)_(plus|minus|band|bxor|bor)_vb.c(.)", null, null, "$1=$2_$3_vwuc$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(vwuz.)=vb.c(.)_(plus|minus|band|bxor|bor)_(vwuz.)", null, null, "$1=vwuc$2_$3_$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsz.)_(plus|minus|band|bxor|bor)_vb.c(.)", null, null, "$1=$2_$3_vwsc$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(vwsz.)=vb.c(.)_(plus|minus|band|bxor|bor)_(vwsz.)", null, null, "$1=vwsc$2_$3_$4", null, null));
+
+ // Move constant words to the end of the ASM signature for symmetric operators ( ...vw.c...vw.z... -> ...vw.z...vw.c... )
+ synths.add(new AsmFragmentSynthesis("(vwuz.)=(vwuc.)_(plus|band|bxor|bor)_(vwuz.)", null, null, "$1=$4_$3_$2", null, null));
+ synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsc.)_(plus|band|bxor|bor)_(vwsz.)", null, null, "$1=$4_$3_$2", null, null));
+
+ // Use Z1/Z2 ASM to synthesize Z1-only code ( ...z1...z1... -> ...z1...z2... )
+ synths.add(new AsmFragmentSynthesis("(v..)z1=(v..)z1_(plus|minus|band|bxor|bor)_(.*)", ".*z2.*", null, "$1z1=$2z2_$3_$4", null, mapZ, false));
+ synths.add(new AsmFragmentSynthesis("(v..)z1=(.*)_(plus|minus|band|bxor|bor)_(v..)z1", ".*z2.*", null, "$1z1=$2_$3_$4z2", null, mapZ, false));
+ synths.add(new AsmFragmentSynthesis("(v..)z1=_(neg|lo|hi)_(v..)z1", ".*z2.*", null, "$1z1=_$2_$3z2", null, mapZ, false));
+
+ // Convert INC/DEC to +1/-1 ( ..._inc_xxx... -> ...xxx_plus_1_... / ..._dec_xxx... -> ...xxx_minus_1_... )
+ synths.add(new AsmFragmentSynthesis("vb(.)aa=_inc_(.*)", null, null, "vb$1aa=$2_plus_1", null, null));
+ synths.add(new AsmFragmentSynthesis("vb(.)aa=_dec_(.*)", null, null, "vb$1aa=$2_minus_1", null, null));
+
+ // Synthesize XX/YY using AA
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuxx(.*)", ".*=.*aa.*|.*derefidx_vb.xx.*", "txa\n", "$1=$2vbuaa$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsxx(.*)", ".*=.*aa.*|.*derefidx_vb.xx.*", "txa\n", "$1=$2vbsaa$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuyy(.*)", ".*=.*aa.*|.*derefidx_vb.yy.*", "tya\n", "$1=$2vbuaa$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsyy(.*)", ".*=.*aa.*|.*derefidx_vb.yy.*", "tya\n", "$1=$2vbsaa$3", null, null));
+ // Synthesize constants using AA
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuc1(.*)", ".*=.*aa.*|.*c1.*c1.*|.*c1_deref.*", "lda #{c1}\n", "$1=$2vbuaa$3", null, mapC));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsc1(.*)", ".*=.*aa.*|.*c1.*c1.*|.*c1_deref.*", "lda #{c1}\n", "$1=$2vbsaa$3", null, mapC));
+
+ // Synthesize some constant pointers as constant words
+ synths.add(new AsmFragmentSynthesis("(.*)_(lt|gt|le|ge|eq|neq)_p..([cz].)_then_(.*)", null, null, "$1_$2_vwu$3_then_$4", null, null));
+ synths.add(new AsmFragmentSynthesis("p..([cz].)_(lt|gt|le|ge|eq|neq)_(.*)", null, null, "vwu$1_$2_$3", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=p..([zc].)", null, null, "$1=vwu$2", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(plus|minus|bor|bxor)_p..([cz].)", null, null, "$1=$2_$3_vwu$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=p..([cz].)_(plus|minus|bor|bxor)_(.*)", null, null, "$1=vwu$2_$3_$4", null, null));
+ synths.add(new AsmFragmentSynthesis("p..([cz].)=(.*)_(sethi|setlo|plus|minus)_(.*)", null, null, "vwu$1=$2_$3_$4", null, null));
+ synths.add(new AsmFragmentSynthesis("(.*)=p..([cz].)_(sethi|setlo|plus|minus)_(.*)", null, null, "$1=vwu$2_$3_$4", null, null));
+
+ return synths;
+ }
+
+ /**
+ * The synthesis path describes the different signatures being attempted to synthesize a fragment.
+ * Used to avoid infinite loops during synthesis.
+ */
+ static class AsmSynthesisPath {
+
+ private ArrayDeque signatures;
+
+ public AsmSynthesisPath() {
+ this.signatures = new ArrayDeque<>();
+ }
+
+ private AsmSynthesisPath(ArrayDeque signatures) {
+ this.signatures = signatures;
+ }
+
+ AsmSynthesisPath add(String signature) {
+ ArrayDeque signatures = new ArrayDeque<>(this.signatures);
+ signatures.add(signature);
+ return new AsmSynthesisPath(signatures);
+ }
+
+ boolean has(String signature) {
+ return signatures.contains(signature);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder();
+ boolean first = true;
+ for(String signature : signatures) {
+ if(first) {
+ first = false;
+ } else {
+ str.append(" < ");
}
- bestFragmentCache.put(signature.getSignature(), bestTemplate);
- }
- // Count usages
- AsmFragmentUsages.incUsage(bestTemplate);
- // Return the resulting fragment instance
- return new AsmFragment(
- signature.getProgram(),
- signature.getSignature(),
- signature.getCodeScope(),
- bestTemplate,
- signature.getBindings());
- }
+ str.append(signature);
+ }
+ return str.toString();
+ }
+ }
+ /**
+ * Capable of creating fragments from signatures by loading them or synthesizing them from other smaller fragments.
+ *
+ * The synthesizer tries a lot of different combinations and keeps track of what has already been attempted.
+ */
+ static class AsmFragmentTemplateSynthesizer {
- /**
- * The synthesis path describes the different signatures being attempted to synthesize a fragment.
- * Used to avoid infinite loops during synthesis.
- */
- static class AsmSynthesisPath {
+ /** Signature of the fragment being synthesized. */
+ private String creating;
- private ArrayDeque signatures;
+ /** The log. */
+ private CompileLog log;
- public AsmSynthesisPath() {
- this.signatures = new ArrayDeque<>();
- }
+ AsmFragmentTemplateSynthesizer(String creating, CompileLog log) {
+ this.creating = creating;
+ this.log = log;
+ }
- private AsmSynthesisPath(ArrayDeque signatures) {
- this.signatures = signatures;
- }
-
- AsmSynthesisPath add(String signature) {
- ArrayDeque signatures = new ArrayDeque<>(this.signatures);
- signatures.add(signature);
- return new AsmSynthesisPath(signatures);
- }
-
- boolean has(String signature) {
- return signatures.contains(signature);
- }
-
- @Override
- public String toString() {
- StringBuilder str = new StringBuilder();
- boolean first = true;
- for (String signature : signatures) {
- if (first) {
- first = false;
- } else {
- str.append(" < ");
- }
- str.append(signature);
+ List loadOrSynthesizeFragment(String signature, AsmSynthesisPath path) {
+ if(path.has(signature)) {
+ // Synthesis loop - stop it here
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - Stopping synthesis loop at " + signature);
}
- return str.toString();
- }
- }
-
- /**
- * Capable of creating fragments from signatures by loading them or synthesizing them from other smaller fragments.
- *
- * The synthesizer tries a lot of different combinations and keeps track of what has already been attempted.
- */
- static class AsmFragmentTemplateSynthesizer {
-
- /** Signature of the fragment being synthesized. */
- private String creating;
-
- /** The log. */
- private CompileLog log;
-
- AsmFragmentTemplateSynthesizer(String creating, CompileLog log) {
- this.creating = creating;
- this.log = log;
- }
-
- List loadOrSynthesizeFragment(String signature, AsmSynthesisPath path) {
- if (path.has(signature)) {
- // Synthesis loop - stop it here
- if (log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - Stopping synthesis loop at " + signature);
- }
- return new ArrayList<>();
+ return new ArrayList<>();
+ }
+ // Add the current signature to the path
+ path = path.add(signature);
+ if(fragmentTemplateCache.get(signature) != null) {
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - Using cached " + signature);
}
- // Add the current signature to the path
- path = path.add(signature);
- if (fragmentTemplateCache.get(signature) != null) {
- if (log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - Using cached " + signature);
- }
- return fragmentTemplateCache.get(signature);
+ return fragmentTemplateCache.get(signature);
+ }
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - Attempting " + signature);
+ }
+ List candidates = new ArrayList<>();
+ // Synthesize the fragment from other fragments
+ List synths = getFragmentSyntheses();
+ for(AsmFragmentSynthesis synth : synths) {
+ List synthesized = synth.synthesize(signature, path, this);
+ if(synthesized != null) {
+ if(log.isVerboseFragmentLog() && synthesized.size() > 0) {
+ log.append("Finding fragment " + path.toString() + " - Successfully synthesized " + synthesized.size() + " fragments ");
+ }
+ candidates.addAll(synthesized);
}
- if (log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - Attempting " + signature);
+ }
+ // Load the fragment from disk
+ CharStream fragmentCharStream = loadFragment(signature);
+ if(fragmentCharStream != null) {
+ try {
+ String body = fragmentCharStream.toString();
+ candidates.add(new AsmFragmentTemplate(signature, body));
+
+ } catch(StringIndexOutOfBoundsException e) {
+ throw new RuntimeException("Problem reading fragment file " + signature, e);
}
- List candidates = new ArrayList<>();
- // Synthesize the fragment from other fragments
- List synths = getFragmentSyntheses();
- for (AsmFragmentSynthesis synth : synths) {
- List synthesized = synth.synthesize(signature, path, this);
- if (synthesized != null) {
- if (log.isVerboseFragmentLog() && synthesized.size() > 0) {
- log.append("Finding fragment " + path.toString() + " - Successfully synthesized " + synthesized.size() + " fragments ");
- }
- candidates.addAll(synthesized);
- }
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - Successfully loaded " + signature + ".asm");
}
- // Load the fragment from disk
- CharStream fragmentCharStream = loadFragment(signature);
- if (fragmentCharStream != null) {
- try {
- String body = fragmentCharStream.toString();
- candidates.add(new AsmFragmentTemplate(signature, body));
-
- } catch (StringIndexOutOfBoundsException e) {
- throw new RuntimeException("Problem reading fragment file " + signature, e);
- }
- if (log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - Successfully loaded " + signature + ".asm");
- }
+ }
+ if(candidates.size() == 0) {
+ if(log.isVerboseFragmentLog()) {
+ log.append("Finding fragment " + path.toString() + " - No synthesis/file found!");
}
- if (candidates.size() == 0) {
- if(log.isVerboseFragmentLog()) {
- log.append("Finding fragment " + path.toString() + " - No synthesis/file found!");
- }
- }
- fragmentTemplateCache.put(signature, candidates);
- return candidates;
- }
+ }
+ fragmentTemplateCache.put(signature, candidates);
+ return candidates;
+ }
- public String getCreating() {
- return creating;
- }
+ public String getCreating() {
+ return creating;
+ }
- public CompileLog getLog() {
- return log;
- }
- }
+ public CompileLog getLog() {
+ return log;
+ }
+ }
+ public static class UnknownFragmentException extends RuntimeException {
- /**
- * Look for a fragment on the disk.
- *
- * @param signature The fragment signature
- * @return The fragment file contents. Null if the fragment is not on the disk.
- */
- private static CharStream loadFragment(String signature) {
- ClassLoader classLoader = AsmFragmentManager.class.getClassLoader();
- URL fragmentUrl = classLoader.getResource("dk/camelot64/kickc/fragment/asm/" + signature + ".asm");
- if (fragmentUrl == null) {
- return null;
- }
- try {
- InputStream fragmentStream = fragmentUrl.openStream();
- return CharStreams.fromStream(fragmentStream);
- } catch (IOException e) {
- throw new RuntimeException("Error loading fragment file " + fragmentUrl);
- }
- }
+ private String fragmentSignature;
+ UnknownFragmentException(String signature) {
+ super("Fragment not found " + signature + ".asm");
+ this.fragmentSignature = signature;
+ }
- static File[] allFragmentFiles() {
- ClassLoader classLoader = AsmFragmentManager.class.getClassLoader();
- String path = classLoader.getResource("dk/camelot64/kickc/fragment/asm/").getPath();
- return new File(path).listFiles((dir, name) -> name.endsWith(".asm"));
-
- }
-
- public static class UnknownFragmentException extends RuntimeException {
-
- private String fragmentSignature;
-
- UnknownFragmentException(String signature) {
- super("Fragment not found " + signature + ".asm");
- this.fragmentSignature = signature;
- }
-
- public String getFragmentSignature() {
- return fragmentSignature;
- }
- }
-
- /**
- * All the synthesize rules available.
- */
- private static List fragmentSyntheses;
-
- private static List getFragmentSyntheses() {
- if (fragmentSyntheses == null) {
- fragmentSyntheses = initFragmentSyntheses();
- }
- return fragmentSyntheses;
- }
-
- private static List initFragmentSyntheses() {
- Map mapZ = new LinkedHashMap<>();
- mapZ.put("z2", "z1");
- mapZ.put("z3", "z2");
- Map mapZ2 = new LinkedHashMap<>();
- mapZ2.put("z3", "z1");
- Map mapZ3 = new LinkedHashMap<>();
- mapZ3.put("z3", "z2");
- Map mapC = new LinkedHashMap<>();
- mapC.put("c2", "c1");
- mapC.put("c3", "c2");
- Map mapC3 = new LinkedHashMap<>();
- mapC3.put("c3", "c2");
- Map mapZC = new LinkedHashMap<>();
- mapZC.putAll(mapZ);
- mapZC.putAll(mapC);
- Map mapSToU = new LinkedHashMap<>();
- mapSToU.put("vbsz1", "vbuz1");
- mapSToU.put("vbsz2", "vbuz2");
- mapSToU.put("vbsz3", "vbuz3");
- mapSToU.put("vbsc1", "vbuc1");
- mapSToU.put("vbsc2", "vbuc2");
- mapSToU.put("vbsc3", "vbuc3");
- mapSToU.put("vbsaa", "vbuaa");
- mapSToU.put("vbsxx", "vbuxx");
- mapSToU.put("vbsyy", "vbuyy");
- mapSToU.put("vwsz1", "vwuz1");
- mapSToU.put("vwsz2", "vwuz2");
- mapSToU.put("vwsz3", "vwuz3");
- mapSToU.put("vwsc1", "vwuc1");
- mapSToU.put("vwsc2", "vwuc2");
- mapSToU.put("vwsc3", "vwuc3");
-
- List synths = new ArrayList<>();
-
- // NEW STYLE REWRITES - Utilizes that all combinations are tried
-
- // Replace first AA with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1xx$2", null, null));
- // Replace two AAs with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1xx$2xx$3", null, null));
- // Replace second (not first) AA with XX
- synths.add(new AsmFragmentSynthesis("(.*)aa(.*vb.)aa(.*)", "...aa=.*|.*xx.*", "tax", "$1aa$2xx$3", null, null));
-
- // Replace first AA with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1yy$2", null, null));
- // Replace two AAs with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)aa(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1yy$2yy$3", null, null));
- // Replace second (not first) AA with YY
- synths.add(new AsmFragmentSynthesis("(.*)aa(.*vb.)aa(.*)", "...aa=.*|.*yy.*", "tay", "$1aa$2yy$3", null, null));
-
- // Replace first XX with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1aa$2", null, null));
- // Replace two XXs with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)xx(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1aa$2aa$3", null, null));
- // Replace second (not first) XX with AA
- synths.add(new AsmFragmentSynthesis("(.*)xx(.*vb.)xx(.*)", "...xx=.*|.*aa.*", "txa", "$1xx$2aa$3", null, null));
-
- // Replace first YY with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1aa$2", null, null));
- // Replace two YYs with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)yy(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1aa$2aa$3", null, null));
- // Replace second (not first) YY with AA
- synths.add(new AsmFragmentSynthesis("(.*)yy(.*vb.)yy(.*)", "...yy=.*|.*aa.*", "tya", "$1yy$2aa$3", null, null));
-
- // Replace Z1 with AA (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*aa.*", "lda {z1}", "$1aa$2", null, mapZ));
- // Replace two Z1s with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*aa.*", "lda {z1}", "$1aa$2aa$3", null, mapZ));
- // Replace first (not second) Z1 with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*aa.*", "lda {z1}", "$1aa$2z1$3", null, null));
- // Replace second (not first) Z1 with AA
- synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*aa.*", "lda {z1}", "$1z1$2aa$3", null, null));
-
- // Replace Z1 with YY (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*yy.*", "ldy {z1}", "$1yy$2", null, mapZ));
- // Replace two Z1s with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*yy.*", "ldy {z1}", "$1yy$2yy$3", null, mapZ));
- // Replace first (not second) Z1 with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*yy.*", "ldy {z1}", "$1yy$2z1$3", null, null));
- // Replace second (not first) Z1 with YY
- synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*yy.*", "ldy {z1}", "$1z1$2yy$3", null, null));
-
- // Replace Z1 with XX (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*|.*xx.*", "ldx {z1}", "$1xx$2", null, mapZ));
- // Replace two Z1s with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*vb.)z1(.*)", "...z1=.*|.*z1.*z1.*z1.*|.*xx.*", "ldx {z1}", "$1xx$2xx$3", null, mapZ));
- // Replace first (not second) Z1 with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)z1(.*)z1(.*)", "...z1=.*|.*xx.*", "ldx {z1}", "$1xx$2z1$3", null, null));
- // Replace second (not first) Z1 with XX
- synths.add(new AsmFragmentSynthesis("(.*)z1(.*vb.)z1(.*)", "...z1=.*|.*xx.*", "ldx {z1}", "$1z1$2xx$3", null, null));
-
- // Replace Z2 with AA (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*aa.*", "lda {z2}", "$1aa$2", null, mapZ3));
- // Replace two Z2s with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*aa.*", "lda {z2}", "$1aa$2aa$3", null, mapZ3));
- // Replace first (of 2) Z2 with AA
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*aa.*", "lda {z2}", "$1aa$2z2$3", null, null));
- // Replace second (of 2) Z2 with AA
- synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*aa.*", "lda {z2}", "$1z2$2aa$3", null, null));
-
- // Replace Z2 with YY (only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*yy.*", "ldy {z2}", "$1yy$2", null, mapZ3));
- // Replace two Z2s with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*yy.*", "ldy {z2}", "$1yy$2yy$3", null, mapZ3));
- // Replace first (of 2) Z2 with YY
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*yy.*", "ldy {z2}", "$1yy$2z2$3", null, null));
- // Replace second (of 2) Z2 with YY
- synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*yy.*", "ldy {z2}", "$1z2$2yy$3", null, null));
-
- // Replace Z2 with XX(only one)
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*|.*xx.*", "ldx {z2}", "$1xx$2", null, mapZ3));
- // Replace two Z2s with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*vb.)z2(.*)", "...z2=.*|.*z2.*z2.*z2.*|.*xx.*", "ldx {z2}", "$1xx$2xx$3", null, mapZ3));
- // Replace first (of 2) Z2 with XX
- synths.add(new AsmFragmentSynthesis("(.*vb.)z2(.*)z2(.*)", "...z2=.*|.*xx.*", "ldx {z2}", "$1xx$2z2$3", null, null));
- // Replace second (of 2) Z2 with XX
- synths.add(new AsmFragmentSynthesis("(.*)z2(.*vb.)z2(.*)", "...z2=.*|.*xx.*", "ldx {z2}", "$1z2$2xx$3", null, null));
-
-
- // OLD STYLE REWRITES - written when only one rule could be taken
-
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.aa)", ".*=vb.aa_.*", null, "$1=$4_$3_$2", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.xx)", ".*=vb.[ax][ax]_.*", null, "$1=$4_$3_$2", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(band|bor|bxor|plus)_(vb.yy)", ".*=vb.[axy][axy]_.*", null, "$1=$4_$3_$2", null, null));
-
- synths.add(new AsmFragmentSynthesis("vbuxx=(.*)", null, null, "vbuaa=$1", "tax\n", null));
- synths.add(new AsmFragmentSynthesis("vbsxx=(.*)", null, null, "vbsaa=$1", "tax\n", null));
- synths.add(new AsmFragmentSynthesis("vbuyy=(.*)", null, null, "vbuaa=$1", "tay\n", null));
- synths.add(new AsmFragmentSynthesis("vbsyy=(.*)", null, null, "vbsaa=$1", "tay\n", null));
- synths.add(new AsmFragmentSynthesis("vbuz1=(.*)", ".*=.*vb.z1.*", null, "vbuaa=$1", "sta {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("vbsz1=(.*)", ".*=.*vb.z1.*", null, "vbsaa=$1", "sta {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1}\n", mapC));
- synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1=(.*c1.*)", null, null, "vb$1aa=$2", "sta {c1}\n", null));
- synths.add(new AsmFragmentSynthesis("_deref_pbuz1=(.*)", ".*z1.*z1.*", null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y\n", mapZ));
- synths.add(new AsmFragmentSynthesis("_deref_pbuz1=(.*z1.*)", null, null, "vbuaa=$1", "ldy #0\n" + "sta ({z1}),y\n", null));
-
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*)", ".*z1.*z1.*|.*c1.*c1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapZC));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},y\n", mapC));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx=(.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "sta {c1},x\n", mapC));
- synths.add(new AsmFragmentSynthesis("pb(.)z1_derefidx_vbuz2=(.*)", ".*z1.*z1.*|.*z2.*z2.*", null, "vb$1aa=$2", "ldy {z2}\n" + "sta ({z1}),y\n", mapZ2));
-
- synths.add(new AsmFragmentSynthesis("(.*)=_deref_pb(.)c1(.*)", ".*=.*aa.*", "lda {c1}\n", "$1=vb$2aa$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("(.*)=_deref_pb(.)z1(.*)", ".*z1.*z1.*|.*=.*aa.*|.*=.*yy.*", "ldy #0\n" + "lda ({z1}),y\n", "$1=vb$2aa$3", null, mapZ));
-
- // Convert array indexing with A register to X/Y register by prefixing tax/tay (..._derefidx_vbuaa... -> ..._derefidx_vbuxx... /... _derefidx_vbuyy... )
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuaa(.*)", ".*=.*xx.*", "tax\n", "$1=$2_derefidx_vbuxx$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuaa(.*)", ".*=.*yy.*", "tay\n", "$1=$2_derefidx_vbuyy$3", null, null));
- // Convert array indexing with zero page to x/y register by prefixing ldx z1 / ldy z1 ( ..._derefidx_vbuzn... -> ..._derefidx_vbuxx... / ..._derefidx_vbuyy... )
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz1(.*)", ".*=.*xx.*|.*z1.*z1.*", "ldx {z1}\n", "$1=$2_derefidx_vbuxx$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz1(.*)", ".*=.*yy.*|.*z1.*z1.*", "ldy {z1}\n", "$1=$2_derefidx_vbuyy$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz2(.*)", ".*=.*xx.*|.*z2.*z2.*", "ldx {z2}\n", "$1=$2_derefidx_vbuxx$3", null, mapZ3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz2(.*)", ".*=.*yy.*|.*z2.*z2.*", "ldy {z2}\n", "$1=$2_derefidx_vbuyy$3", null, mapZ3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz3(.*)", ".*=.*yy.*", "ldy {z3}\n", "$1=$2_derefidx_vbuyy$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_derefidx_vbuz3(.*)", ".*=.*xx.*", "ldx {z3}\n", "$1=$2_derefidx_vbuxx$3", null, null));
- // Convert array indexing twice with A/zp1/zp2 to X/Y register with a ldx/ldy prefix ( ..._derefidx_vbunn..._derefidx_vbunn... -> ..._derefidx_vbuxx..._derefidx_vbuxx... )
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuaa(.*)_derefidx_vbuaa(.*)", ".*aa.*aa.*aa.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "tax\n", null));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuaa(.*)_derefidx_vbuaa(.*)", ".*aa.*aa.*aa.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "tay\n", null));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1(.*)_derefidx_vbuz1(.*)", ".*z1.*z1.*z1.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "ldx {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1(.*)_derefidx_vbuz1(.*)", ".*z1.*z1.*z1.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "ldy {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz2(.*)_derefidx_vbuz2(.*)", ".*z2.*z2.*z2.*|.*xx.*", null, "$1_derefidx_vbuxx$2_derefidx_vbuxx$3", "ldx {z2}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz2(.*)_derefidx_vbuz2(.*)", ".*z2.*z2.*z2.*|.*yy.*", null, "$1_derefidx_vbuyy$2_derefidx_vbuyy$3", "ldy {z2}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*c1.*)", ".*z1.*z1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapZ));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuz1=(.*z1.*)", ".*c1.*c1.*", null, "vb$1aa=$2", "ldx {z1}\n" + "sta {c1},x\n", mapC));
-
- // Convert X/Y-based array indexing of a constant pointer into A-register by prefixing lda cn,x / lda cn,y ( ...pb.c1_derefidx_vbuxx... / ...pb.c1_derefidx_vbuyy... -> ...vb.aa... )
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuxx(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, mapC));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*c1.*)pb(.)c1_derefidx_vbuxx(.*)", ".*=.*aa.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuxx(.*c1.*)", ".*=.*aa.*", "lda {c1},x\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuyy(.*)", ".*=.*aa.*|.*c1.*c1.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, mapC));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*c1.*)pb(.)c1_derefidx_vbuyy(.*)", ".*=.*aa.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c1_derefidx_vbuyy(.*c1.*)", ".*=.*aa.*", "lda {c1},y\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuxx(.*)", ".*=.*aa.*|.*c2.*c2.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, mapC3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*c2.*)pb(.)c2_derefidx_vbuxx(.*)", ".*=.*aa.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuxx(.*c2.*)", ".*=.*aa.*", "lda {c2},x\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuyy(.*)", ".*=.*aa.*|.*c2.*c2.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, mapC3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*c2.*)pb(.)c2_derefidx_vbuyy(.*)", ".*=.*aa.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)pb(.)c2_derefidx_vbuyy(.*c2.*)", ".*=.*aa.*", "lda {c2},y\n", "$1=$2vb$3aa$4", null, null));
-
- // Convert zeropage/constants/X/Y in assignments to A-register using LDA/TXA/TYA prefix
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz1(.*)", ".*z1.*=.*|.*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2vbuaa$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz1(.*)", ".*z1.*=.*|.*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2vbsaa$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz2(.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbuaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz2(.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbsaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuz2(.*z3.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbuaa$3", null, mapZ3));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsz2(.*z3.*)", ".*z2.*=.*|.*=.*aa.*|.*z2.*z2.*|.*z3.*", "lda {z2}\n", "$1=$2vbsaa$3", null, mapZ3));
-
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuxx", ".*=.*[ax][ax].*xx|.*derefidx_vb.xx", "txa\n", "$1=$2_vbuaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsxx", ".*=.*[ax][ax].*xx|.*derefidx_vb.xx", "txa\n", "$1=$2_vbsaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuyy", ".*=.*[ay][ay].*yy|.*derefidx_vb.yy", "tya\n", "$1=$2_vbuaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsyy", ".*=-*[ay][ay].*yy|.*derefidx_vb.yy", "tya\n", "$1=$2_vbsaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz1", ".*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2_vbuaa", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbsz1", ".*=.*aa.*|.*z1.*z1.*", "lda {z1}\n", "$1=$2_vbsaa", null, mapZ));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz2", ".*=.*aa.*|.*z2.*z2.*", "lda {z2}\n", "$1=$2_vbuaa", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_vbuz3", ".*=.*aa.*|.*z3.*z3.*", "lda {z3}\n", "$1=$2_vbuaa", null, null));
-
- synths.add(new AsmFragmentSynthesis("vbuz1=vbuz1(.*)", ".*=.*vb.aa.*|.*z1.*z1.*z1.*", "lda {z1}\n", "vbuaa=vbuaa$1", "sta {z1}\n", mapZ));
- synths.add(new AsmFragmentSynthesis("vbsz1=vbsz1(.*)", ".*=.*vb.aa.*|.*z1.*z1.*z1.*", "lda {z1}\n", "vbsaa=vbsaa$1", "sta {z1}\n", mapZ));
-
- synths.add(new AsmFragmentSynthesis("vbuz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*z1.*z1.*", "lda {z1}\n", "vbuaa_$1_$2", null, mapZ));
- synths.add(new AsmFragmentSynthesis("vbsz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*z1.*z1.*", "lda {z1}\n", "vbsaa_$1_$2", null, mapZ));
- synths.add(new AsmFragmentSynthesis("_deref_pb(.)c1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*", "lda {c1}\n", "vb$1aa_$2_$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("_deref_pb(.)z1_(lt|gt|le|ge|eq|neq)_(.*)", ".*vb.aa.*|.*vb.yy.*|.*z1.*z1.*", "ldy #0\n" + "lda ({z1}),y\n", "vb$1aa_$2_$3", null, mapZ));
-
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1_(.*)", ".*z1.*z1.*|.*.yy.*", "ldy {z1}\n", "$1_derefidx_vbuyy_$2", null, mapZ));
-
-
- synths.add(new AsmFragmentSynthesis("(.*)_derefidx_vbuz1_(lt|gt|le|ge|eq|neq)_(.*)", ".*z1.*z1.*|.*vb.xx.*", "ldx {z1}\n", "$1_derefidx_vbuxx_$2_$3", null, mapZ));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy_(lt|gt|le|ge|eq|neq)_(.*)", ".*c1.*c1.*|.*aa.*", "lda {c1},y\n", "vb$1aa_$2_$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuyy_(lt|gt|le|ge|eq|neq)_(.*c1.*)", ".*aa.*", "lda {c1},y\n", "vb$1aa_$2_$3", null, null));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx_(lt|gt|le|ge|eq|neq)_(.*)", ".*c1.*c1.*|.*aa.*", "lda {c1},x\n", "vb$1aa_$2_$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("pb(.)c1_derefidx_vbuxx_(lt|gt|le|ge|eq|neq)_(.*c1.*)", ".*aa.*", "lda {c1},x\n", "vb$1aa_$2_$3", null, null));
-
- synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.aa)_then_(.*)", ".*vb.aa.*_ge.*", null, "$2_lt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_ge.*", null, "$2_lt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_ge_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_ge.*", null, "$2_lt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.aa)_then_(.*)", ".*vb.aa.*_lt.*", null, "$2_ge_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_lt.*", null, "$2_ge_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_lt_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_lt.*", null, "$2_ge_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.aa)_then_(.*)", ".*vb.aa.*_gt.*", null, "$2_le_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_gt.*", null, "$2_le_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_gt_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_gt.*", null, "$2_le_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.aa)_then_(.*)", ".*vb.aa.*_le.*", null, "$2_gt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_le.*", null, "$2_gt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_le_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_le.*", null, "$2_gt_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.aa)_then_(.*)", ".*vb.aa.*_neq.*", null, "$2_neq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_neq.*", null, "$2_neq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_neq_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_neq.*", null, "$2_neq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.aa)_then_(.*)", ".*vb.aa.*_eq.*", null, "$2_eq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.xx)_then_(.*)", ".*vb.[ax][ax].*_eq.*", null, "$2_eq_$1_then_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)_eq_(vb.yy)_then_(.*)", ".*vb.[axy][axy].*_eq.*", null, "$2_eq_$1_then_$3", null, null));
-
- // Use unsigned ASM to synthesize signed ASM ( ...vbs... -> ...vbu... )
- synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_(eq|neq)_(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_then_(.*)", null, null, "$1_$2_$3_then_$4", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)", null, null, "$1=$2", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)_(plus|band|bxor|bor)_(vbsz.|csoby.|vbsaa|vbsxx|vbsyy)", null, null, "$1=$2_$3_$4", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)=_(inc|dec)_(vbsz.|vbsc.|vbsaa|vbsxx|vbsyy)", null, null, "$1=_$2_$3", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vwsz.|vwsc.)_(eq|neq)_(vwsz.|vwsc.)_then_(.*)", null, null, "$1_$2_$3_then_$4", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsz.|vwsc.)", null, null, "$1=$2", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(v.sz.)=(v.s..)_(band|bxor|bor)_(v.s..)", null, null, "$1=$2_$3_$4", null, mapSToU));
- synths.add(new AsmFragmentSynthesis("(vbuz.|vbuaa|vbuxx|vbuyy)=_(lo|hi)_vws(z.|c.)", null, null, "$1=_$2_vwu$3", null, mapSToU));
-
- // Use constant word ASM to synthesize unsigned constant byte ASM ( ...vb.c... -> vw.c... )
- synths.add(new AsmFragmentSynthesis("(vwuz.)=(vwuz.)_(plus|minus|band|bxor|bor)_vb.c(.)", null, null, "$1=$2_$3_vwuc$4", null, null));
- synths.add(new AsmFragmentSynthesis("(vwuz.)=vb.c(.)_(plus|minus|band|bxor|bor)_(vwuz.)", null, null, "$1=vwuc$2_$3_$4", null, null));
- synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsz.)_(plus|minus|band|bxor|bor)_vb.c(.)", null, null, "$1=$2_$3_vwsc$4", null, null));
- synths.add(new AsmFragmentSynthesis("(vwsz.)=vb.c(.)_(plus|minus|band|bxor|bor)_(vwsz.)", null, null, "$1=vwsc$2_$3_$4", null, null));
-
- // Move constant words to the end of the ASM signature for symmetric operators ( ...vw.c...vw.z... -> ...vw.z...vw.c... )
- synths.add(new AsmFragmentSynthesis("(vwuz.)=(vwuc.)_(plus|band|bxor|bor)_(vwuz.)", null, null, "$1=$4_$3_$2", null, null));
- synths.add(new AsmFragmentSynthesis("(vwsz.)=(vwsc.)_(plus|band|bxor|bor)_(vwsz.)", null, null, "$1=$4_$3_$2", null, null));
-
- // Use Z1/Z2 ASM to synthesize Z1-only code ( ...z1...z1... -> ...z1...z2... )
- synths.add(new AsmFragmentSynthesis("(v..)z1=(v..)z1_(plus|minus|band|bxor|bor)_(.*)", ".*z2.*", null, "$1z1=$2z2_$3_$4", null, mapZ, false));
- synths.add(new AsmFragmentSynthesis("(v..)z1=(.*)_(plus|minus|band|bxor|bor)_(v..)z1", ".*z2.*", null, "$1z1=$2_$3_$4z2", null, mapZ, false));
- synths.add(new AsmFragmentSynthesis("(v..)z1=_(neg|lo|hi)_(v..)z1", ".*z2.*", null, "$1z1=_$2_$3z2", null, mapZ, false));
-
- // Convert INC/DEC to +1/-1 ( ..._inc_xxx... -> ...xxx_plus_1_... / ..._dec_xxx... -> ...xxx_minus_1_... )
- synths.add(new AsmFragmentSynthesis("vb(.)aa=_inc_(.*)", null, null, "vb$1aa=$2_plus_1", null, null));
- synths.add(new AsmFragmentSynthesis("vb(.)aa=_dec_(.*)", null, null, "vb$1aa=$2_minus_1", null, null));
-
- // Synthesize XX/YY using AA
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuxx(.*)", ".*=.*aa.*|.*derefidx_vb.xx.*", "txa\n", "$1=$2vbuaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsxx(.*)", ".*=.*aa.*|.*derefidx_vb.xx.*", "txa\n", "$1=$2vbsaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuyy(.*)", ".*=.*aa.*|.*derefidx_vb.yy.*", "tya\n", "$1=$2vbuaa$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsyy(.*)", ".*=.*aa.*|.*derefidx_vb.yy.*", "tya\n", "$1=$2vbsaa$3", null, null));
- // Synthesize constants using AA
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbuc1(.*)", ".*=.*aa.*|.*c1.*c1.*|.*c1_deref.*", "lda #{c1}\n", "$1=$2vbuaa$3", null, mapC));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)vbsc1(.*)", ".*=.*aa.*|.*c1.*c1.*|.*c1_deref.*", "lda #{c1}\n", "$1=$2vbsaa$3", null, mapC));
-
- // Synthesize some constant pointers as constant words
- synths.add(new AsmFragmentSynthesis("(.*)_(lt|gt|le|ge|eq|neq)_p..([cz].)_then_(.*)", null, null, "$1_$2_vwu$3_then_$4", null, null));
- synths.add(new AsmFragmentSynthesis("p..([cz].)_(lt|gt|le|ge|eq|neq)_(.*)", null, null, "vwu$1_$2_$3", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=p..([zc].)", null, null, "$1=vwu$2", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=(.*)_(plus|minus|bor|bxor)_p..([cz].)", null, null, "$1=$2_$3_vwu$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=p..([cz].)_(plus|minus|bor|bxor)_(.*)", null, null, "$1=vwu$2_$3_$4", null, null));
- synths.add(new AsmFragmentSynthesis("p..([cz].)=(.*)_(sethi|setlo|plus|minus)_(.*)", null, null, "vwu$1=$2_$3_$4", null, null));
- synths.add(new AsmFragmentSynthesis("(.*)=p..([cz].)_(sethi|setlo|plus|minus)_(.*)", null, null, "$1=vwu$2_$3_$4", null, null));
-
- return synths;
- }
+ public String getFragmentSignature() {
+ return fragmentSignature;
+ }
+ }
}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java
index ff27e55c5..35ee1722b 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSignature.java
@@ -29,6 +29,13 @@ public class AsmFragmentSignature {
* The scope containing the fragment. Used when referencing symbols defined in other scopes.
*/
private ScopeRef codeScopeRef;
+ /**
+ * Zero page register name indexing.
+ */
+ private int nextZpByteIdx = 1;
+ private int nextZpBoolIdx = 1;
+ private int nextConstByteIdx = 1;
+ private int nextLabelIdx = 1;
public AsmFragmentSignature(
StatementConditionalJump conditionalJump,
@@ -67,25 +74,29 @@ public class AsmFragmentSignature {
setSignature(assignmentWithAluSignature(assignment, assignmentAlu));
}
+ private static String getOperatorFragmentName(Operator operator) {
+ return operator.getAsmOperator();
+ }
+
private String assignmentWithAluSignature(StatementAssignment assignment, StatementAssignment assignmentAlu) {
this.codeScopeRef = program.getStatementInfos().getBlock(assignment).getScope();
- if (!(assignment.getrValue2() instanceof VariableRef)) {
+ if(!(assignment.getrValue2() instanceof VariableRef)) {
throw new AsmFragment.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
}
VariableRef assignmentRValue2 = (VariableRef) assignment.getrValue2();
Variable assignmentRValue2Var = program.getSymbolInfos().getVariable(assignmentRValue2);
Registers.Register rVal2Register = assignmentRValue2Var.getAllocation();
- if (!rVal2Register.getType().equals(Registers.RegisterType.REG_ALU)) {
+ if(!rVal2Register.getType().equals(Registers.RegisterType.REG_ALU)) {
throw new AsmFragment.AluNotApplicableException("Error! ALU register only allowed as rValue2. " + assignment);
}
StringBuilder signature = new StringBuilder();
signature.append(bind(assignment.getlValue()));
signature.append("=");
- if (assignment.getrValue1() != null) {
+ if(assignment.getrValue1() != null) {
signature.append(bind(assignment.getrValue1()));
}
- if (assignment.getOperator() != null) {
+ if(assignment.getOperator() != null) {
signature.append(getOperatorFragmentName(assignment.getOperator()));
}
signature.append(assignmentRightSideSignature(
@@ -105,25 +116,25 @@ public class AsmFragmentSignature {
private String assignmentRightSideSignature(RValue rValue1, Operator operator, RValue rValue2) {
StringBuilder signature = new StringBuilder();
- if (rValue1 != null) {
+ if(rValue1 != null) {
signature.append(bind(rValue1));
}
- if (operator != null) {
+ if(operator != null) {
signature.append(getOperatorFragmentName(operator));
}
- if (
+ if(
rValue2 instanceof ConstantInteger &&
((ConstantInteger) rValue2).getNumber() == 1 &&
operator != null &&
(operator.getOperator().equals("-") || operator.getOperator().equals("+"))) {
signature.append("1");
- } else if (
+ } else if(
rValue2 instanceof ConstantInteger &&
((ConstantInteger) rValue2).getNumber() <= 7 &&
operator != null &&
(operator.getOperator().equals(">>") || operator.getOperator().equals("<<"))) {
signature.append(((ConstantInteger) rValue2).getNumber());
- } else if (
+ } else if(
rValue2 instanceof ConstantInteger &&
((ConstantInteger) rValue2).getNumber() == 0 &&
operator != null &&
@@ -140,15 +151,15 @@ public class AsmFragmentSignature {
ControlFlowBlock block,
ControlFlowGraph graph) {
StringBuilder signature = new StringBuilder();
- if (conditionalJump.getrValue1() != null) {
+ if(conditionalJump.getrValue1() != null) {
signature.append(bind(conditionalJump.getrValue1()));
}
- if (conditionalJump.getOperator() != null) {
+ if(conditionalJump.getOperator() != null) {
signature.append(getOperatorFragmentName(conditionalJump.getOperator()));
}
- if (conditionalJump.getrValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue2()).getNumber() == 0) {
+ if(conditionalJump.getrValue2() instanceof ConstantInteger && ((ConstantInteger) conditionalJump.getrValue2()).getNumber() == 0) {
signature.append("0");
- } else if (conditionalJump.getrValue2() instanceof ConstantBool) {
+ } else if(conditionalJump.getrValue2() instanceof ConstantBool) {
ConstantBool boolValue = (ConstantBool) conditionalJump.getrValue2();
signature.append(boolValue.toString());
} else {
@@ -158,7 +169,7 @@ public class AsmFragmentSignature {
LabelRef destination = conditionalJump.getDestination();
ControlFlowBlock destinationBlock = graph.getBlock(destination);
String destinationLabel;
- if (destinationBlock.hasPhiBlock()) {
+ if(destinationBlock.hasPhiBlock()) {
destinationLabel =
(destinationBlock.getLabel().getLocalName() +
"_from_" +
@@ -171,10 +182,6 @@ public class AsmFragmentSignature {
return signature.toString();
}
- private static String getOperatorFragmentName(Operator operator) {
- return operator.getAsmOperator();
- }
-
public String getSignature() {
return signature;
}
@@ -183,14 +190,6 @@ public class AsmFragmentSignature {
this.signature = signature;
}
- /**
- * Zero page register name indexing.
- */
- private int nextZpByteIdx = 1;
- private int nextZpBoolIdx = 1;
- private int nextConstByteIdx = 1;
- private int nextLabelIdx = 1;
-
/**
* Add bindings of a value.
*
@@ -198,39 +197,39 @@ public class AsmFragmentSignature {
* @return The bound name of the value. If the value has already been bound the existing bound name is returned.
*/
public String bind(Value value) {
- if (value instanceof PointerDereferenceSimple) {
+ if(value instanceof PointerDereferenceSimple) {
PointerDereferenceSimple deref = (PointerDereferenceSimple) value;
return "_deref_" + bind(deref.getPointer());
- } else if (value instanceof PointerDereferenceIndexed) {
+ } else if(value instanceof PointerDereferenceIndexed) {
PointerDereferenceIndexed deref = (PointerDereferenceIndexed) value;
return bind(deref.getPointer()) + "_derefidx_" + bind(deref.getIndex());
}
- if (value instanceof VariableRef) {
+ if(value instanceof VariableRef) {
value = program.getSymbolInfos().getVariable((VariableRef) value);
}
- if (value instanceof ConstantRef) {
+ if(value instanceof ConstantRef) {
value = program.getScope().getConstant((ConstantRef) value);
}
// Find value if it is already bound
- for (String name : bindings.keySet()) {
+ for(String name : bindings.keySet()) {
Value bound = bindings.get(name);
- if (bound.equals(value)) {
+ if(bound.equals(value)) {
return name;
}
}
- if (value instanceof Variable) {
+ if(value instanceof Variable) {
Variable variable = (Variable) value;
Registers.Register register = variable.getAllocation();
// Find value if it is already bound
- for (String name : bindings.keySet()) {
+ for(String name : bindings.keySet()) {
Value bound = bindings.get(name);
- if (bound instanceof Variable) {
+ if(bound instanceof Variable) {
Registers.Register boundRegister = ((Variable) bound).getAllocation();
- if (boundRegister != null && boundRegister.equals(register)) {
- if (SymbolTypeInference.typeMatch(((Variable) bound).getType(), variable.getType())) {
+ if(boundRegister != null && boundRegister.equals(register)) {
+ if(SymbolTypeInference.typeMatch(((Variable) bound).getType(), variable.getType())) {
return name;
}
}
@@ -240,9 +239,9 @@ public class AsmFragmentSignature {
String name = getTypePrefix(varType) + getRegisterName(register);
bindings.put(name, value);
return name;
- } else if (value instanceof ConstantVar || value instanceof ConstantValue) {
+ } else if(value instanceof ConstantVar || value instanceof ConstantValue) {
SymbolType constType;
- if (value instanceof ConstantVar) {
+ if(value instanceof ConstantVar) {
constType = ((ConstantVar) value).getType();
} else {
constType = SymbolTypeInference.inferType(program.getScope(), (ConstantValue) value);
@@ -250,7 +249,7 @@ public class AsmFragmentSignature {
String name = getTypePrefix(constType) + "c" + nextConstByteIdx++;
bindings.put(name, value);
return name;
- } else if (value instanceof Label) {
+ } else if(value instanceof Label) {
String name = "la" + nextLabelIdx++;
bindings.put(name, value);
return name;
@@ -260,27 +259,28 @@ public class AsmFragmentSignature {
/**
* Get the symbol type part of the binding name (eg. vbu/pws/...)
+ *
* @param type The type
* @return The type name
*/
private String getTypePrefix(SymbolType type) {
- if (SymbolType.isByte(type)) {
+ if(SymbolType.isByte(type)) {
return "vbu";
- } else if (SymbolType.isSByte(type)) {
+ } else if(SymbolType.isSByte(type)) {
return "vbs";
- } else if (SymbolType.isWord(type)) {
+ } else if(SymbolType.isWord(type)) {
return "vwu";
- } else if (SymbolType.isSWord(type)) {
+ } else if(SymbolType.isSWord(type)) {
return "vws";
- } else if (SymbolType.STRING.equals(type)) {
+ } else if(SymbolType.STRING.equals(type)) {
return "pbu";
- } else if (type instanceof SymbolTypePointer) {
+ } else if(type instanceof SymbolTypePointer) {
SymbolType elementType = ((SymbolTypePointer) type).getElementType();
- if (SymbolType.isByte(elementType)) {
+ if(SymbolType.isByte(elementType)) {
return "pbu";
- } else if (SymbolType.isSByte(elementType)) {
+ } else if(SymbolType.isSByte(elementType)) {
return "pbs";
- } else if (SymbolType.isWord(elementType)) {
+ } else if(SymbolType.isWord(elementType)) {
return "pwu";
} else {
throw new RuntimeException("Not implemented " + type);
@@ -293,21 +293,22 @@ public class AsmFragmentSignature {
/**
* Get the register part of the binding name (eg. aa, z1, c2, ...).
* Examines all previous bindings to reuse register index if the same register is bound multiple times.
+ *
* @param register The register
* @return The register part of the binding name.
*/
private String getRegisterName(Registers.Register register) {
- if (Registers.RegisterType.ZP_BYTE.equals(register.getType())) {
+ if(Registers.RegisterType.ZP_BYTE.equals(register.getType())) {
return "z" + getRegisterZpNameIdx((Registers.RegisterZp) register);
- } else if (Registers.RegisterType.ZP_WORD.equals(register.getType())) {
+ } else if(Registers.RegisterType.ZP_WORD.equals(register.getType())) {
return "z" + getRegisterZpNameIdx((Registers.RegisterZp) register);
- } else if (Registers.RegisterType.REG_A_BYTE.equals(register.getType())) {
+ } else if(Registers.RegisterType.REG_A_BYTE.equals(register.getType())) {
return "aa";
- } else if (Registers.RegisterType.REG_X_BYTE.equals(register.getType())) {
+ } else if(Registers.RegisterType.REG_X_BYTE.equals(register.getType())) {
return "xx";
- } else if (Registers.RegisterType.REG_Y_BYTE.equals(register.getType())) {
+ } else if(Registers.RegisterType.REG_Y_BYTE.equals(register.getType())) {
return "yy";
- } else if (Registers.RegisterType.REG_ALU.equals(register.getType())) {
+ } else if(Registers.RegisterType.REG_ALU.equals(register.getType())) {
throw new AsmFragment.AluNotApplicableException();
} else {
throw new RuntimeException("Not implemented " + register.getType());
@@ -317,17 +318,18 @@ public class AsmFragmentSignature {
/**
* Get the register ZP name index to use for a specific register.
* Examines all previous bindings to reuse register index if the same register is bound multiple times.
+ *
* @param register The register to find an index for
* @return The index. Either reused ot allocated from {@link #nextZpByteIdx}
*/
private String getRegisterZpNameIdx(Registers.RegisterZp register) {
- for (String boundName : bindings.keySet()) {
+ for(String boundName : bindings.keySet()) {
Value boundValue = bindings.get(boundName);
- if (boundValue instanceof Variable) {
+ if(boundValue instanceof Variable) {
Registers.Register boundRegister = ((Variable) boundValue).getAllocation();
- if (boundRegister != null && boundRegister.isZp()) {
+ if(boundRegister != null && boundRegister.isZp()) {
Registers.RegisterZp boundRegisterZp = (Registers.RegisterZp) boundRegister;
- if (register.getZp() == boundRegisterZp.getZp()) {
+ if(register.getZp() == boundRegisterZp.getZp()) {
// Found other register with same ZP address!
return boundName.substring(boundName.length() - 1);
}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSynthesis.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSynthesis.java
index 23db6ae0f..b4ed0ed36 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSynthesis.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentSynthesis.java
@@ -10,94 +10,94 @@ import java.util.regex.Pattern;
/** AsmFragment synthesis mechanism based on matching fragment signature and reusing another fragment with added prefix/postfix and some bind-mappings */
class AsmFragmentSynthesis {
- private String sigMatch;
- private String sigAvoid;
- private String asmPrefix;
- private String sigReplace;
- private String asmPostfix;
- private Map bindMappings;
- private boolean mapSignature;
- private String subSignature;
+ private String sigMatch;
+ private String sigAvoid;
+ private String asmPrefix;
+ private String sigReplace;
+ private String asmPostfix;
+ private Map bindMappings;
+ private boolean mapSignature;
+ private String subSignature;
- AsmFragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings, boolean mapSignature) {
- this.sigMatch = sigMatch;
- this.sigAvoid = sigAvoid;
- this.asmPrefix = asmPrefix;
- this.sigReplace = sigReplace;
- this.asmPostfix = asmPostfix;
- this.bindMappings = bindMappings;
- this.mapSignature = mapSignature;
- }
+ AsmFragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings, boolean mapSignature) {
+ this.sigMatch = sigMatch;
+ this.sigAvoid = sigAvoid;
+ this.asmPrefix = asmPrefix;
+ this.sigReplace = sigReplace;
+ this.asmPostfix = asmPostfix;
+ this.bindMappings = bindMappings;
+ this.mapSignature = mapSignature;
+ }
- public AsmFragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings) {
- this(sigMatch, sigAvoid, asmPrefix, sigReplace, asmPostfix, bindMappings, true);
- }
+ public AsmFragmentSynthesis(String sigMatch, String sigAvoid, String asmPrefix, String sigReplace, String asmPostfix, Map bindMappings) {
+ this(sigMatch, sigAvoid, asmPrefix, sigReplace, asmPostfix, bindMappings, true);
+ }
- public String getName() {
- return sigMatch + (sigAvoid == null ? "" : ("/" + sigAvoid));
- }
+ static String regexpRewriteSignature(String signature, String match, String replace) {
+ Pattern p = Pattern.compile(match);
+ Matcher m = p.matcher(signature);
+ String output = signature;
+ if(m.find()) {
+ // getReplacement first number with "number" and second number with the first
+ output = m.replaceAll(replace);
+ }
+ return output;
+ }
- public List synthesize(String signature, AsmFragmentManager.AsmSynthesisPath path, AsmFragmentManager.AsmFragmentTemplateSynthesizer synthesizer) {
- ArrayList candidates = new ArrayList<>();
- if (signature.matches(sigMatch)) {
- if (sigAvoid == null || !signature.matches(sigAvoid)) {
- subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace);
- if (mapSignature && bindMappings != null) {
- // When mapping the signature we do the map replacement in the signature
- for (String bound : bindMappings.keySet()) {
- subSignature = subSignature.replace(bound, bindMappings.get(bound));
- }
- }
- List subFragmentTemplates = synthesizer.loadOrSynthesizeFragment(subSignature, path);
- for (AsmFragmentTemplate subFragmentTemplate : subFragmentTemplates) {
- if (subFragmentTemplate != null) {
- StringBuilder newFragment = new StringBuilder();
- if (asmPrefix != null) {
- newFragment.append(asmPrefix).append("\n");
- }
- String subFragment = subFragmentTemplate.getBody();
- if (bindMappings != null) {
- if (mapSignature) {
- // When mapping the signature we do the reverse replacement in the ASM
- List reverse = new ArrayList<>(bindMappings.keySet());
- Collections.reverse(reverse);
- for (String bound : reverse) {
- subFragment = subFragment.replace("{" + bindMappings.get(bound) + "}", "{" + bound + "}");
- }
- } else {
- // When not mapping the signature we do the replacement directly in the ASM
- for (String bound : bindMappings.keySet()) {
- subFragment = subFragment.replace("{" + bound + "}", "{" + bindMappings.get(bound) + "}");
- }
- }
- }
- newFragment.append(subFragment);
- if (asmPostfix != null) {
- newFragment.append("\n");
- newFragment.append(asmPostfix);
- }
- candidates.add(new AsmFragmentTemplate(signature, newFragment.toString(), this, subFragmentTemplate));
- }
- }
+ public String getName() {
+ return sigMatch + (sigAvoid == null ? "" : ("/" + sigAvoid));
+ }
+
+ public List synthesize(String signature, AsmFragmentManager.AsmSynthesisPath path, AsmFragmentManager.AsmFragmentTemplateSynthesizer synthesizer) {
+ ArrayList candidates = new ArrayList<>();
+ if(signature.matches(sigMatch)) {
+ if(sigAvoid == null || !signature.matches(sigAvoid)) {
+ subSignature = regexpRewriteSignature(signature, sigMatch, sigReplace);
+ if(mapSignature && bindMappings != null) {
+ // When mapping the signature we do the map replacement in the signature
+ for(String bound : bindMappings.keySet()) {
+ subSignature = subSignature.replace(bound, bindMappings.get(bound));
+ }
}
- }
- return candidates;
- }
+ List subFragmentTemplates = synthesizer.loadOrSynthesizeFragment(subSignature, path);
+ for(AsmFragmentTemplate subFragmentTemplate : subFragmentTemplates) {
+ if(subFragmentTemplate != null) {
+ StringBuilder newFragment = new StringBuilder();
+ if(asmPrefix != null) {
+ newFragment.append(asmPrefix).append("\n");
+ }
+ String subFragment = subFragmentTemplate.getBody();
+ if(bindMappings != null) {
+ if(mapSignature) {
+ // When mapping the signature we do the reverse replacement in the ASM
+ List reverse = new ArrayList<>(bindMappings.keySet());
+ Collections.reverse(reverse);
+ for(String bound : reverse) {
+ subFragment = subFragment.replace("{" + bindMappings.get(bound) + "}", "{" + bound + "}");
+ }
+ } else {
+ // When not mapping the signature we do the replacement directly in the ASM
+ for(String bound : bindMappings.keySet()) {
+ subFragment = subFragment.replace("{" + bound + "}", "{" + bindMappings.get(bound) + "}");
+ }
+ }
+ }
+ newFragment.append(subFragment);
+ if(asmPostfix != null) {
+ newFragment.append("\n");
+ newFragment.append(asmPostfix);
+ }
+ candidates.add(new AsmFragmentTemplate(signature, newFragment.toString(), this, subFragmentTemplate));
+ }
+ }
+ }
+ }
+ return candidates;
+ }
- public String getSubSignature() {
- return subSignature;
- }
-
- static String regexpRewriteSignature(String signature, String match, String replace) {
- Pattern p = Pattern.compile(match);
- Matcher m = p.matcher(signature);
- String output = signature;
- if (m.find()) {
- // getReplacement first number with "number" and second number with the first
- output = m.replaceAll(replace);
- }
- return output;
- }
+ public String getSubSignature() {
+ return subSignature;
+ }
}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java
index e2dc3e751..6b24feefc 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentTemplate.java
@@ -10,119 +10,114 @@ import org.antlr.v4.runtime.*;
*/
public class AsmFragmentTemplate {
- /** The fragment template signature name. */
- private String signature;
+ /** true if the fragment was loaded from disk. */
+ boolean file;
+ /** The fragment template signature name. */
+ private String signature;
+ /** The fragment template body */
+ private String body;
+ /** The parsed ASM lines. Initially null. Will be non-null, is the template is ever used to generate ASM code. */
+ private KickCParser.AsmLinesContext bodyAsm;
+ /** The synthesis that created the fragment. null if the fragment template was loaded. */
+ private AsmFragmentSynthesis synthesis;
- /** The fragment template body */
- private String body;
+ /** The sub fragment template that the synthesis modified to create this. null if the fragment template was loaded. */
+ private AsmFragmentTemplate subFragment;
- /** The parsed ASM lines. Initially null. Will be non-null, is the template is ever used to generate ASM code. */
- private KickCParser.AsmLinesContext bodyAsm;
+ public AsmFragmentTemplate(String signature, String body) {
+ this.signature = signature;
+ this.body = body;
+ this.file = true;
+ }
- /** true if the fragment was loaded from disk. */
- boolean file;
+ AsmFragmentTemplate(String signature, String body, AsmFragmentSynthesis synthesis, AsmFragmentTemplate subFragment) {
+ this.signature = signature;
+ this.body = body;
+ this.synthesis = synthesis;
+ this.subFragment = subFragment;
+ this.file = false;
+ }
- /** The synthesis that created the fragment. null if the fragment template was loaded. */
- private AsmFragmentSynthesis synthesis;
+ /**
+ * Creates an inline ASM fragment template
+ *
+ * @param bodyLines Parsed ASM body
+ */
+ public AsmFragmentTemplate(KickCParser.AsmLinesContext bodyLines) {
+ this.signature = "--inline--";
+ this.bodyAsm = bodyLines;
+ }
- /** The sub fragment template that the synthesis modified to create this. null if the fragment template was loaded. */
- private AsmFragmentTemplate subFragment;
+ /**
+ * Parse an ASM fragment.
+ *
+ * @param fragmentBody The stream containing the fragment syntax
+ * @param fragmentFileName The filename (used in error messages)
+ * @return The parsed fragment ready for generating
+ */
+ private static KickCParser.AsmLinesContext parseBody(String fragmentBody, final String fragmentFileName) {
+ CodePointCharStream fragmentCharStream = CharStreams.fromString(fragmentBody);
+ KickCLexer kickCLexer = new KickCLexer(fragmentCharStream);
+ KickCParser kickCParser = new KickCParser(new CommonTokenStream(kickCLexer));
+ kickCParser.addErrorListener(new BaseErrorListener() {
+ @Override
+ public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+ throw new RuntimeException("Error parsing fragment " + fragmentFileName + "\n - Line: " + line + "\n - Message: " + msg);
+ }
+ });
+ kickCParser.setBuildParseTree(true);
+ KickCParser.AsmFileContext asmFile = kickCParser.asmFile();
+ return asmFile.asmLines();
+ }
- public AsmFragmentTemplate(String signature, String body) {
- this.signature = signature;
- this.body = body;
- this.file = true;
- }
+ public String getSignature() {
+ return signature;
+ }
- AsmFragmentTemplate(String signature, String body, AsmFragmentSynthesis synthesis, AsmFragmentTemplate subFragment) {
- this.signature = signature;
- this.body = body;
- this.synthesis = synthesis;
- this.subFragment = subFragment;
- this.file = false;
- }
+ public String getBody() {
+ return body;
+ }
- /**
- * Creates an inline ASM fragment template
- *
- * @param bodyLines Parsed ASM body
- */
- public AsmFragmentTemplate(KickCParser.AsmLinesContext bodyLines) {
- this.signature = "--inline--";
- this.bodyAsm = bodyLines;
- }
+ public KickCParser.AsmLinesContext getBodyAsm() {
+ if(bodyAsm == null) {
+ bodyAsm = parseBody(body, signature);
+ }
+ return bodyAsm;
+ }
- public String getSignature() {
- return signature;
- }
+ public boolean isFile() {
+ return file;
+ }
- public String getBody() {
- return body;
- }
+ public AsmFragmentSynthesis getSynthesis() {
+ return synthesis;
+ }
- public KickCParser.AsmLinesContext getBodyAsm() {
- if (bodyAsm == null) {
- bodyAsm = parseBody(body, signature);
- }
- return bodyAsm;
- }
+ public AsmFragmentTemplate getSubFragment() {
+ return subFragment;
+ }
- /**
- * Parse an ASM fragment.
- *
- * @param fragmentBody The stream containing the fragment syntax
- * @param fragmentFileName The filename (used in error messages)
- * @return The parsed fragment ready for generating
- */
- private static KickCParser.AsmLinesContext parseBody(String fragmentBody, final String fragmentFileName) {
- CodePointCharStream fragmentCharStream = CharStreams.fromString(fragmentBody);
- KickCLexer kickCLexer = new KickCLexer(fragmentCharStream);
- KickCParser kickCParser = new KickCParser(new CommonTokenStream(kickCLexer));
- kickCParser.addErrorListener(new BaseErrorListener() {
- @Override
- public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
- throw new RuntimeException("Error parsing fragment " + fragmentFileName + "\n - Line: " + line + "\n - Message: " + msg);
- }
- });
- kickCParser.setBuildParseTree(true);
- KickCParser.AsmFileContext asmFile = kickCParser.asmFile();
- return asmFile.asmLines();
- }
+ public String getName() {
+ StringBuilder name = new StringBuilder();
+ name.append(signature);
+ if(synthesis != null) {
+ name.append(" < ");
+ name.append(subFragment.getName());
+ }
+ return name.toString();
+ }
+ @Override
+ public boolean equals(Object o) {
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+ AsmFragmentTemplate that = (AsmFragmentTemplate) o;
+ return getName().equals(that.getName());
+ }
- public boolean isFile() {
- return file;
- }
-
- public AsmFragmentSynthesis getSynthesis() {
- return synthesis;
- }
-
- public AsmFragmentTemplate getSubFragment() {
- return subFragment;
- }
-
- public String getName() {
- StringBuilder name = new StringBuilder();
- name.append(signature);
- if (synthesis != null) {
- name.append(" < ");
- name.append(subFragment.getName());
- }
- return name.toString();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- AsmFragmentTemplate that = (AsmFragmentTemplate) o;
- return getName().equals(that.getName());
- }
-
- @Override
- public int hashCode() {
- return getName().hashCode();
- }
+ @Override
+ public int hashCode() {
+ return getName().hashCode();
+ }
}
diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java
index 582f7730c..3d980dce4 100644
--- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java
+++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentUsages.java
@@ -8,176 +8,176 @@ import java.util.*;
/** Statistics for usage of the ASM fragments. Also contains a methos for identifying redundant/unused files. */
public class AsmFragmentUsages {
- /** Usage Statistics for fragment templates. */
- private static Map fragmentTemplateUsage = new HashMap<>();
+ /** Usage Statistics for fragment templates. */
+ private static Map fragmentTemplateUsage = new HashMap<>();
- /**
- * Count one usage of ASM fragment templates - directly or through synthesis
- *
- * @param fragmentTemplate The template to increment usage of
- */
- static void incUsage(AsmFragmentTemplate fragmentTemplate) {
- Integer usage = fragmentTemplateUsage.get(fragmentTemplate);
- if (usage == null) {
- usage = 0;
- }
- fragmentTemplateUsage.put(fragmentTemplate, usage + 1);
- AsmFragmentTemplate subFragment = fragmentTemplate.getSubFragment();
- if (subFragment != null) {
- incUsage(subFragment);
- }
- }
+ /**
+ * Count one usage of ASM fragment templates - directly or through synthesis
+ *
+ * @param fragmentTemplate The template to increment usage of
+ */
+ static void incUsage(AsmFragmentTemplate fragmentTemplate) {
+ Integer usage = fragmentTemplateUsage.get(fragmentTemplate);
+ if(usage == null) {
+ usage = 0;
+ }
+ fragmentTemplateUsage.put(fragmentTemplate, usage + 1);
+ AsmFragmentTemplate subFragment = fragmentTemplate.getSubFragment();
+ if(subFragment != null) {
+ incUsage(subFragment);
+ }
+ }
- /**
- * Log the usage of all template fragemnts (both loaded and synthesized).
- *
- * @param log The compile log to add the output to
- */
- public static void logUsages(CompileLog log, boolean logRedundantFiles, boolean logUnusedFiles, boolean logFileDetails, boolean logAllDetails) {
+ /**
+ * Log the usage of all template fragemnts (both loaded and synthesized).
+ *
+ * @param log The compile log to add the output to
+ */
+ public static void logUsages(CompileLog log, boolean logRedundantFiles, boolean logUnusedFiles, boolean logFileDetails, boolean logAllDetails) {
- Map> fragmentTemplateCache = AsmFragmentManager.getFragmentTemplateCache();
- ArrayList signatures = new ArrayList<>(fragmentTemplateCache.keySet());
- Collections.sort(signatures);
- File[] files = AsmFragmentManager.allFragmentFiles();
+ Map> fragmentTemplateCache = AsmFragmentManager.getFragmentTemplateCache();
+ ArrayList signatures = new ArrayList<>(fragmentTemplateCache.keySet());
+ Collections.sort(signatures);
+ File[] files = AsmFragmentManager.allFragmentFiles();
- if (logRedundantFiles) {
- // Find all file fragments that were bested by a synthesized fragment
- log.append("\nREDUNDANT ASM FRAGMENT FILE ANALYSIS (if found remove them from disk)");
- for (String signature : signatures) {
- List templates = fragmentTemplateCache.get(signature);
- AsmFragmentTemplate fileTemplate = null;
- int fileUsage = 0;
- AsmFragmentTemplate maxTemplate = null;
- int maxUsage = 0;
- for (AsmFragmentTemplate template : templates) {
- Integer usage = fragmentTemplateUsage.get(template);
- if (usage == null) usage = 0;
- if (template.isFile()) {
- fileTemplate = template;
- fileUsage = usage;
- }
- if (usage > maxUsage) {
- maxUsage = usage;
- maxTemplate = template;
- }
- }
- if (fileTemplate != null && fileUsage == 0 && maxUsage > 0) {
- log.append("rm " + fileTemplate.getName() + ".asm #synthesized by " + maxTemplate.getName() + " - usages: " + maxUsage);
- }
+ if(logRedundantFiles) {
+ // Find all file fragments that were bested by a synthesized fragment
+ log.append("\nREDUNDANT ASM FRAGMENT FILE ANALYSIS (if found remove them from disk)");
+ for(String signature : signatures) {
+ List templates = fragmentTemplateCache.get(signature);
+ AsmFragmentTemplate fileTemplate = null;
+ int fileUsage = 0;
+ AsmFragmentTemplate maxTemplate = null;
+ int maxUsage = 0;
+ for(AsmFragmentTemplate template : templates) {
+ Integer usage = fragmentTemplateUsage.get(template);
+ if(usage == null) usage = 0;
+ if(template.isFile()) {
+ fileTemplate = template;
+ fileUsage = usage;
+ }
+ if(usage > maxUsage) {
+ maxUsage = usage;
+ maxTemplate = template;
+ }
}
-
- Set redundantSignatures = new LinkedHashSet<>();
- for (File file : files) {
- String fileName = file.getName();
- String signature = fileName.substring(0, fileName.length() - 4);
- // Try to synthesize the fragment - and check if the synthesis is as good as the file body
- AsmFragmentManager.AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentManager.AsmFragmentTemplateSynthesizer(signature, log);
- List templates = synthesizer.loadOrSynthesizeFragment(signature, new AsmFragmentManager.AsmSynthesisPath());
- AsmFragmentTemplate fileTemplate = null;
- for (AsmFragmentTemplate template : templates) {
- if (template.isFile()) {
- fileTemplate = template;
- }
- }
- for (AsmFragmentTemplate template : templates) {
- if (!template.isFile() && template.getBody().equals(fileTemplate.getBody())) {
- // Check if the synthesis uses a file marked as redundant
- AsmFragmentTemplate sourceFileTemplate = template;
- while (!sourceFileTemplate.isFile()) {
- sourceFileTemplate = sourceFileTemplate.getSubFragment();
- }
- if (redundantSignatures.contains(sourceFileTemplate.getSignature())) {
- throw new RuntimeException("Problem in redundancy analysis! " + sourceFileTemplate.getSignature() + ".asm seems redundant but is needed for synthesis of " + signature);
- }
- log.append("rm " + fileTemplate.getName() + ".asm #synthesized same ASM by " + template.getName());
- redundantSignatures.add(signature);
- break;
- }
- }
+ if(fileTemplate != null && fileUsage == 0 && maxUsage > 0) {
+ log.append("rm " + fileTemplate.getName() + ".asm #synthesized by " + maxTemplate.getName() + " - usages: " + maxUsage);
}
- }
+ }
- if (logUnusedFiles) {
- log.append("\nUNUSED ASM FRAGMENT FILES ANALYSIS (if found consider removing them from disk)");
- for (File file : files) {
- String fileName = file.getName();
- String signature = fileName.substring(0, fileName.length() - 4);
- List templates = fragmentTemplateCache.get(signature);
- if (templates != null && templates.size() > 0) {
- // The template has been loaded / synthesized - is the usage count zero?
- boolean allZero = true;
- Integer fileUsage = null;
- for (AsmFragmentTemplate template : templates) {
- Integer usage = fragmentTemplateUsage.get(template);
- if (usage == null) usage = 0;
- if (usage > 0) {
- allZero = false;
- }
- if (template.isFile()) {
- fileUsage = usage;
- }
- }
- if (fileUsage == null) {
- throw new RuntimeException("Error! Template file never loaded according to usage stats " + fileName);
- }
- if (allZero) {
- log.append("git mv " + fileName + " unused # Loaded but never used");
- }
- } else {
- // The template has never been loaded
- log.append("git mv " + fileName + " unused # Never loaded");
- }
+ Set redundantSignatures = new LinkedHashSet<>();
+ for(File file : files) {
+ String fileName = file.getName();
+ String signature = fileName.substring(0, fileName.length() - 4);
+ // Try to synthesize the fragment - and check if the synthesis is as good as the file body
+ AsmFragmentManager.AsmFragmentTemplateSynthesizer synthesizer = new AsmFragmentManager.AsmFragmentTemplateSynthesizer(signature, log);
+ List templates = synthesizer.loadOrSynthesizeFragment(signature, new AsmFragmentManager.AsmSynthesisPath());
+ AsmFragmentTemplate fileTemplate = null;
+ for(AsmFragmentTemplate template : templates) {
+ if(template.isFile()) {
+ fileTemplate = template;
+ }
}
- }
-
- if (logFileDetails) {
- log.append("\nDETAILED ASM FILE USAGES");
- // Find all file templates
- List fileTemplates = new ArrayList<>();
- for (String signature : signatures) {
- List templates = fragmentTemplateCache.get(signature);
- for (AsmFragmentTemplate template : templates) {
- if (template.isFile()) {
- fileTemplates.add(template);
- }
- }
+ for(AsmFragmentTemplate template : templates) {
+ if(!template.isFile() && template.getBody().equals(fileTemplate.getBody())) {
+ // Check if the synthesis uses a file marked as redundant
+ AsmFragmentTemplate sourceFileTemplate = template;
+ while(!sourceFileTemplate.isFile()) {
+ sourceFileTemplate = sourceFileTemplate.getSubFragment();
+ }
+ if(redundantSignatures.contains(sourceFileTemplate.getSignature())) {
+ throw new RuntimeException("Problem in redundancy analysis! " + sourceFileTemplate.getSignature() + ".asm seems redundant but is needed for synthesis of " + signature);
+ }
+ log.append("rm " + fileTemplate.getName() + ".asm #synthesized same ASM by " + template.getName());
+ redundantSignatures.add(signature);
+ break;
+ }
}
- logTemplatesByUsage(log, fileTemplates);
+ }
+ }
- }
-
- if (logAllDetails) {
- log.append("\nDETAILED ASM FRAGMENT USAGES");
- List allTemplates = new ArrayList<>();
- for (String signature : signatures) {
- List templates = fragmentTemplateCache.get(signature);
- for (AsmFragmentTemplate template : templates) {
- allTemplates.add(template);
- }
+ if(logUnusedFiles) {
+ log.append("\nUNUSED ASM FRAGMENT FILES ANALYSIS (if found consider removing them from disk)");
+ for(File file : files) {
+ String fileName = file.getName();
+ String signature = fileName.substring(0, fileName.length() - 4);
+ List templates = fragmentTemplateCache.get(signature);
+ if(templates != null && templates.size() > 0) {
+ // The template has been loaded / synthesized - is the usage count zero?
+ boolean allZero = true;
+ Integer fileUsage = null;
+ for(AsmFragmentTemplate template : templates) {
+ Integer usage = fragmentTemplateUsage.get(template);
+ if(usage == null) usage = 0;
+ if(usage > 0) {
+ allZero = false;
+ }
+ if(template.isFile()) {
+ fileUsage = usage;
+ }
+ }
+ if(fileUsage == null) {
+ throw new RuntimeException("Error! Template file never loaded according to usage stats " + fileName);
+ }
+ if(allZero) {
+ log.append("git mv " + fileName + " unused # Loaded but never used");
+ }
+ } else {
+ // The template has never been loaded
+ log.append("git mv " + fileName + " unused # Never loaded");
}
- logTemplatesByUsage(log, allTemplates);
- }
+ }
+ }
+
+ if(logFileDetails) {
+ log.append("\nDETAILED ASM FILE USAGES");
+ // Find all file templates
+ List fileTemplates = new ArrayList<>();
+ for(String signature : signatures) {
+ List templates = fragmentTemplateCache.get(signature);
+ for(AsmFragmentTemplate template : templates) {
+ if(template.isFile()) {
+ fileTemplates.add(template);
+ }
+ }
+ }
+ logTemplatesByUsage(log, fileTemplates);
+
+ }
+
+ if(logAllDetails) {
+ log.append("\nDETAILED ASM FRAGMENT USAGES");
+ List allTemplates = new ArrayList<>();
+ for(String signature : signatures) {
+ List templates = fragmentTemplateCache.get(signature);
+ for(AsmFragmentTemplate template : templates) {
+ allTemplates.add(template);
+ }
+ }
+ logTemplatesByUsage(log, allTemplates);
+ }
- }
+ }
- private static void logTemplatesByUsage(CompileLog log, List fileTemplates) {
- // Sort by usage
- Collections.sort(fileTemplates, (o1, o2) -> {
- Integer u1 = fragmentTemplateUsage.get(o1);
- Integer u2 = fragmentTemplateUsage.get(o2);
- if (u1 == null) u1 = 0;
- if (u2 == null) u2 = 0;
- return u2 - u1;
- }
- );
- // Output
- for (AsmFragmentTemplate template : fileTemplates) {
- Integer usage = fragmentTemplateUsage.get(template);
- if (usage == null) usage = 0;
- log.append(String.format("%8d", usage) + " " + (template.isFile()?"*":"")+template.getName());
- }
- }
+ private static void logTemplatesByUsage(CompileLog log, List fileTemplates) {
+ // Sort by usage
+ Collections.sort(fileTemplates, (o1, o2) -> {
+ Integer u1 = fragmentTemplateUsage.get(o1);
+ Integer u2 = fragmentTemplateUsage.get(o2);
+ if(u1 == null) u1 = 0;
+ if(u2 == null) u2 = 0;
+ return u2 - u1;
+ }
+ );
+ // Output
+ for(AsmFragmentTemplate template : fileTemplates) {
+ Integer usage = fragmentTemplateUsage.get(template);
+ if(usage == null) usage = 0;
+ log.append(String.format("%8d", usage) + " " + (template.isFile() ? "*" : "") + template.getName());
+ }
+ }
}
diff --git a/src/main/java/dk/camelot64/kickc/model/CallGraph.java b/src/main/java/dk/camelot64/kickc/model/CallGraph.java
index 2ae37e7af..219295d0d 100644
--- a/src/main/java/dk/camelot64/kickc/model/CallGraph.java
+++ b/src/main/java/dk/camelot64/kickc/model/CallGraph.java
@@ -25,7 +25,7 @@ public class CallGraph {
*/
public CallBlock getOrCreateCallBlock(LabelRef scopeLabel) {
CallBlock callBlock = getCallBlock(scopeLabel);
- if (callBlock != null) {
+ if(callBlock != null) {
return callBlock;
}
// Not found - create it
@@ -41,8 +41,8 @@ public class CallGraph {
* @return The call block for the scope. Null if the call block does not exist (no calls are made from it).
*/
private CallBlock getCallBlock(LabelRef scopeLabel) {
- for (CallBlock callBlock : callBlocks) {
- if (callBlock.getScopeLabel().equals(scopeLabel)) {
+ for(CallBlock callBlock : callBlocks) {
+ if(callBlock.getScopeLabel().equals(scopeLabel)) {
return callBlock;
}
}
@@ -55,13 +55,14 @@ public class CallGraph {
/**
* Get sub call blocks called from a specific call block.
+ *
* @param block The block to find subs for
* @return The sub call blocks called from the passed block
*/
public Collection getCalledBlocks(CallBlock block) {
Collection calledLabels = block.getCalledBlocks();
LinkedHashSet called = new LinkedHashSet<>();
- for (LabelRef calledLabel : calledLabels) {
+ for(LabelRef calledLabel : calledLabels) {
called.add(getOrCreateCallBlock(calledLabel));
}
return called;
@@ -69,13 +70,14 @@ public class CallGraph {
/**
* Get all call blocks that call a specific call block
+ *
* @param scopeLabel The label of scope (the call block)
* @return The scope labels of call blocks that call the passed block
*/
public Collection getCallingBlocks(LabelRef scopeLabel) {
ArrayList callingBlocks = new ArrayList<>();
- for (CallBlock callBlock : callBlocks) {
- if (callBlock.getCalledBlocks().contains(scopeLabel)) {
+ for(CallBlock callBlock : callBlocks) {
+ if(callBlock.getCalledBlocks().contains(scopeLabel)) {
callingBlocks.add(callBlock.getScopeLabel());
}
}
@@ -85,7 +87,7 @@ public class CallGraph {
@Override
public String toString() {
StringBuilder out = new StringBuilder();
- for (CallBlock callBlock : callBlocks) {
+ for(CallBlock callBlock : callBlocks) {
out.append(callBlock.toString()).append("\n");
}
return out.toString();
@@ -93,14 +95,15 @@ public class CallGraph {
/**
* Get all calls of a specific procedure
+ *
* @param label The label of the procedure
* @return All calls
*/
public Collection getCallers(LabelRef label) {
Collection callers = new ArrayList<>();
- for (CallBlock callBlock : callBlocks) {
- for (CallBlock.Call call : callBlock.getCalls()) {
- if (call.getProcedure().equals(label)) {
+ for(CallBlock callBlock : callBlocks) {
+ for(CallBlock.Call call : callBlock.getCalls()) {
+ if(call.getProcedure().equals(label)) {
callers.add(call);
}
}
@@ -140,7 +143,7 @@ public class CallGraph {
*/
public Collection getCalledBlocks() {
LinkedHashSet called = new LinkedHashSet<>();
- for (Call call : calls) {
+ for(Call call : calls) {
called.add(call.getProcedure());
}
return called;
@@ -150,7 +153,7 @@ public class CallGraph {
public String toString() {
StringBuilder out = new StringBuilder();
out.append("Calls in [").append(scopeLabel.toString()).append("] to ");
- for (Call call : calls) {
+ for(Call call : calls) {
out.append(call.toString()).append(" ");
}
return out.toString();
@@ -158,6 +161,7 @@ public class CallGraph {
/**
* Get all calls
+ *
* @return The calls
*/
public List getCalls() {
@@ -166,13 +170,14 @@ public class CallGraph {
/**
* Get all calls to a specific call block
+ *
* @param scope The scope label of the block
* @return All calls to the passed scope
*/
public Collection getCalls(LabelRef scope) {
ArrayList callsToScope = new ArrayList<>();
- for (Call call : calls) {
- if (call.getProcedure().equals(scope)) {
+ for(Call call : calls) {
+ if(call.getProcedure().equals(scope)) {
callsToScope.add(call);
}
}
@@ -211,7 +216,7 @@ public class CallGraph {
public String toString() {
StringBuilder out = new StringBuilder();
out.append(procedure);
- if (callStatementIdx != null) {
+ if(callStatementIdx != null) {
out.append(":").append(callStatementIdx);
}
return out.toString();
diff --git a/src/main/java/dk/camelot64/kickc/model/CompileError.java b/src/main/java/dk/camelot64/kickc/model/CompileError.java
index b9d5fa0c6..e75d69538 100644
--- a/src/main/java/dk/camelot64/kickc/model/CompileError.java
+++ b/src/main/java/dk/camelot64/kickc/model/CompileError.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.model;
-/** Signals some error in the code (or compilation) */
+/** Signals some error in the code (or compilation) */
public class CompileError extends RuntimeException {
public CompileError(String message) {
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantArrayList.java b/src/main/java/dk/camelot64/kickc/model/ConstantArrayList.java
index 84e2c5cc8..a1a657c06 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantArrayList.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantArrayList.java
@@ -39,8 +39,8 @@ public class ConstantArrayList implements ConstantValue {
StringBuilder out = new StringBuilder();
boolean first = true;
out.append("{ ");
- for (ConstantValue constantValue : list) {
- if (!first) {
+ for(ConstantValue constantValue : list) {
+ if(!first) {
out.append(", ");
}
first = false;
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantBinary.java b/src/main/java/dk/camelot64/kickc/model/ConstantBinary.java
index 06a34065f..65632e875 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantBinary.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantBinary.java
@@ -37,7 +37,7 @@ public class ConstantBinary implements ConstantValue {
@Override
public String toString(Program program) {
- return left.toString(program)+operator.toString()+right.toString(program);
+ return left.toString(program) + operator.toString() + right.toString(program);
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantBool.java b/src/main/java/dk/camelot64/kickc/model/ConstantBool.java
index d90b5e6b0..619f66aca 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantBool.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantBool.java
@@ -23,9 +23,9 @@ public class ConstantBool implements ConstantValue {
@Override
public String toString(Program program) {
- if(program ==null) {
+ if(program == null) {
return Boolean.toString(value);
- } else {
+ } else {
return //"("+SymbolTypeBasic.BOOLEAN.getTypeName()+") "+
Boolean.toString(value);
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantChar.java b/src/main/java/dk/camelot64/kickc/model/ConstantChar.java
index db33fc0b4..168f98d5b 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantChar.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantChar.java
@@ -22,12 +22,12 @@ public class ConstantChar implements ConstantValue {
@Override
public String toString() {
- return toString(null);
+ return toString(null);
}
@Override
public String toString(Program program) {
- if (program == null) {
+ if(program == null) {
return "'" + value + "'";
} else {
return "(" + SymbolType.BYTE.getTypeName() + ") " + "'" + value + "'";
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantDouble.java b/src/main/java/dk/camelot64/kickc/model/ConstantDouble.java
index 2a91c3dd7..e3e8a6b51 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantDouble.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantDouble.java
@@ -27,9 +27,9 @@ public class ConstantDouble implements ConstantValue {
@Override
public String toString(Program program) {
- if(program ==null) {
+ if(program == null) {
return Double.toString(number);
- } else {
+ } else {
return "(" + SymbolType.VOID.getTypeName() + ") " + Double.toString(number);
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantInteger.java b/src/main/java/dk/camelot64/kickc/model/ConstantInteger.java
index 551285c46..3b0bc373e 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantInteger.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantInteger.java
@@ -29,8 +29,8 @@ public class ConstantInteger implements ConstantValue {
public SymbolType getType() {
ArrayList potentialTypes = new ArrayList<>();
Integer number = getNumber();
- for (SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) {
- if(number>=typeInteger.getMinValue() && number<= typeInteger.getMaxValue()) {
+ for(SymbolTypeInteger typeInteger : SymbolType.getIntegerTypes()) {
+ if(number >= typeInteger.getMinValue() && number <= typeInteger.getMaxValue()) {
potentialTypes.add(typeInteger);
}
}
@@ -44,7 +44,7 @@ public class ConstantInteger implements ConstantValue {
@Override
public String toString(Program program) {
- if (program == null) {
+ if(program == null) {
return Integer.toString(number);
} else {
return "(" + getType(program.getScope()).getTypeName() + ") " + Integer.toString(number);
@@ -53,8 +53,8 @@ public class ConstantInteger implements ConstantValue {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
ConstantInteger that = (ConstantInteger) o;
return number != null ? number.equals(that.number) : that.number == null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantString.java b/src/main/java/dk/camelot64/kickc/model/ConstantString.java
index 4dae792e6..a8c0485f6 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantString.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantString.java
@@ -22,12 +22,12 @@ public class ConstantString implements ConstantValue {
@Override
public String toString() {
- return toString(null);
+ return toString(null);
}
@Override
public String toString(Program program) {
- if (program == null) {
+ if(program == null) {
return "\"" + value + "\"";
} else {
return "(" + SymbolType.STRING.getTypeName() + ") " + "\"" + value + "\"";
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantUnary.java b/src/main/java/dk/camelot64/kickc/model/ConstantUnary.java
index 6e8775537..e00c4ec35 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantUnary.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantUnary.java
@@ -29,14 +29,14 @@ public class ConstantUnary implements ConstantValue {
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
ConstantUnary that = (ConstantUnary) o;
- if (!operator.equals(that.operator)) {
+ if(!operator.equals(that.operator)) {
return false;
}
return operand.equals(that.operand);
@@ -51,7 +51,7 @@ public class ConstantUnary implements ConstantValue {
@Override
public String toString(Program program) {
- return operator.toString()+operand.toString(program);
+ return operator.toString() + operand.toString(program);
}
@Override
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantValueCalculator.java b/src/main/java/dk/camelot64/kickc/model/ConstantValueCalculator.java
index 3d6f14086..ac2253beb 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantValueCalculator.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantValueCalculator.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.model;
-/** Can calculate the exact value for constants (used for type inference).*/
+/** Can calculate the exact value for constants (used for type inference). */
public class ConstantValueCalculator {
@@ -28,7 +28,7 @@ public class ConstantValueCalculator {
// Cannot calculate value of inline array
return null;
} else {
- throw new RuntimeException("Unknown constant value "+value);
+ throw new RuntimeException("Unknown constant value " + value);
}
}
@@ -52,28 +52,28 @@ public class ConstantValueCalculator {
private static ConstantValue castWord(ConstantValue value) {
if(value instanceof ConstantInteger) {
- return new ConstantInteger(0xffff&((ConstantInteger) value).getNumber());
+ return new ConstantInteger(0xffff & ((ConstantInteger) value).getNumber());
}
return null;
}
private static ConstantValue castSWord(ConstantValue value) {
if(value instanceof ConstantInteger) {
- return new ConstantInteger(0xffff&((ConstantInteger) value).getNumber());
+ return new ConstantInteger(0xffff & ((ConstantInteger) value).getNumber());
}
return null;
}
private static ConstantValue castByte(ConstantValue value) {
if(value instanceof ConstantInteger) {
- return new ConstantInteger(0xff&((ConstantInteger) value).getNumber());
+ return new ConstantInteger(0xff & ((ConstantInteger) value).getNumber());
}
return null;
}
private static ConstantValue castSByte(ConstantValue value) {
if(value instanceof ConstantInteger) {
- return new ConstantInteger(0xff&((ConstantInteger) value).getNumber());
+ return new ConstantInteger(0xff & ((ConstantInteger) value).getNumber());
}
return null;
}
@@ -83,7 +83,6 @@ public class ConstantValueCalculator {
}
-
public static ConstantValue calcValue(ProgramScope programScope, ConstantValue value1, Operator operator, ConstantValue value2) {
if(operator.equals(Operator.MULTIPLY)) {
return multiply(calcValue(programScope, value1), calcValue(programScope, value2));
@@ -113,21 +112,25 @@ public class ConstantValueCalculator {
private static ConstantValue multiply(ConstantValue value1, ConstantValue value2) {
if(value1 instanceof ConstantInteger && value2 instanceof ConstantInteger) {
- return new ConstantInteger(((ConstantInteger) value1).getNumber()*((ConstantInteger) value2).getNumber());
+ return new ConstantInteger(((ConstantInteger) value1).getNumber() * ((ConstantInteger) value2).getNumber());
}
return null;
}
private static ConstantValue plus(ConstantValue value1, ConstantValue value2) {
if(value1 instanceof ConstantInteger && value2 instanceof ConstantInteger) {
- return new ConstantInteger(((ConstantInteger) value1).getNumber()+((ConstantInteger) value2).getNumber());
- } if(value1 instanceof ConstantInteger && value2 instanceof ConstantChar) {
- return new ConstantInteger(((ConstantInteger) value1).getNumber()+((ConstantChar) value2).getValue());
- } if(value1 instanceof ConstantChar && value2 instanceof ConstantInteger) {
- return new ConstantInteger(((ConstantChar) value1).getValue()+((ConstantInteger) value2).getNumber());
- } if(value1 instanceof ConstantString && value2 instanceof ConstantString) {
+ return new ConstantInteger(((ConstantInteger) value1).getNumber() + ((ConstantInteger) value2).getNumber());
+ }
+ if(value1 instanceof ConstantInteger && value2 instanceof ConstantChar) {
+ return new ConstantInteger(((ConstantInteger) value1).getNumber() + ((ConstantChar) value2).getValue());
+ }
+ if(value1 instanceof ConstantChar && value2 instanceof ConstantInteger) {
+ return new ConstantInteger(((ConstantChar) value1).getValue() + ((ConstantInteger) value2).getNumber());
+ }
+ if(value1 instanceof ConstantString && value2 instanceof ConstantString) {
return new ConstantString(((ConstantString) value1).getValue() + ((ConstantString) value2).getValue());
- } if(value1 instanceof ConstantString && value2 instanceof ConstantChar) {
+ }
+ if(value1 instanceof ConstantString && value2 instanceof ConstantChar) {
return new ConstantString(((ConstantString) value1).getValue() + ((ConstantChar) value2).getValue());
}
return null;
@@ -135,14 +138,14 @@ public class ConstantValueCalculator {
private static ConstantValue minus(ConstantValue value1, ConstantValue value2) {
if(value1 instanceof ConstantInteger && value2 instanceof ConstantInteger) {
- return new ConstantInteger(((ConstantInteger) value1).getNumber()-((ConstantInteger) value2).getNumber());
+ return new ConstantInteger(((ConstantInteger) value1).getNumber() - ((ConstantInteger) value2).getNumber());
}
return null;
}
private static ConstantValue div(ConstantValue value1, ConstantValue value2) {
if(value1 instanceof ConstantInteger && value2 instanceof ConstantInteger) {
- return new ConstantInteger(((ConstantInteger) value1).getNumber()/((ConstantInteger) value2).getNumber());
+ return new ConstantInteger(((ConstantInteger) value1).getNumber() / ((ConstantInteger) value2).getNumber());
}
return null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ConstantVar.java b/src/main/java/dk/camelot64/kickc/model/ConstantVar.java
index c6cdfb08f..bf231595c 100644
--- a/src/main/java/dk/camelot64/kickc/model/ConstantVar.java
+++ b/src/main/java/dk/camelot64/kickc/model/ConstantVar.java
@@ -64,17 +64,17 @@ public class ConstantVar implements Symbol {
}
@Override
- public int getScopeDepth() {
- if(scope==null) {
- return 0;
- } else {
- return scope.getScopeDepth()+1;
- }
+ public void setScope(Scope scope) {
+ this.scope = scope;
}
@Override
- public void setScope(Scope scope) {
- this.scope = scope;
+ public int getScopeDepth() {
+ if(scope == null) {
+ return 0;
+ } else {
+ return scope.getScopeDepth() + 1;
+ }
}
public ConstantValue getValue() {
@@ -101,7 +101,7 @@ public class ConstantVar implements Symbol {
public String toString(Program program) {
String s = new StringBuilder()
.append("(")
- .append("const"+" ")
+ .append("const" + " ")
.append(type.getTypeName())
.append(") ")
.append(getFullName()).toString();
@@ -115,22 +115,22 @@ public class ConstantVar implements Symbol {
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
ConstantVar that = (ConstantVar) o;
- if (name != null ? !name.equals(that.name) : that.name != null) {
+ if(name != null ? !name.equals(that.name) : that.name != null) {
return false;
}
- if (scope != null ? !scope.equals(that.scope) : that.scope != null) {
+ if(scope != null ? !scope.equals(that.scope) : that.scope != null) {
return false;
}
- if (type != null ? !type.equals(that.type) : that.type != null) {
+ if(type != null ? !type.equals(that.type) : that.type != null) {
return false;
}
return value != null ? value.equals(that.value) : that.value == null;
diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowBlock.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowBlock.java
index 0f7c6ad4b..f589d3e6b 100644
--- a/src/main/java/dk/camelot64/kickc/model/ControlFlowBlock.java
+++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowBlock.java
@@ -9,9 +9,11 @@ import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
-/** A named/labelled sequence of SSA statements connected to other basic blocks.
+/**
+ * A named/labelled sequence of SSA statements connected to other basic blocks.
* The connections defines the control flow of the program.
- * The block only knows its own successors. To find predecessor blocks access to the entire graph is needed.*/
+ * The block only knows its own successors. To find predecessor blocks access to the entire graph is needed.
+ */
public class ControlFlowBlock {
/** The label representing the block. */
@@ -70,14 +72,14 @@ public class ControlFlowBlock {
/**
* Add a statement just before the call statement.
- *
+ *
* Fails if there is no call statement
*
* @param statement The statement to add.
*/
public void addStatementBeforeCall(Statement newStatement) {
ListIterator listIterator = statements.listIterator();
- while (listIterator.hasNext()) {
+ while(listIterator.hasNext()) {
Statement statement = listIterator.next();
if(statement instanceof StatementCall) {
listIterator.previous();
@@ -85,17 +87,17 @@ public class ControlFlowBlock {
return;
}
}
- throw new RuntimeException("No call statement in block "+getLabel().getFullName());
- }
-
- public void setDefaultSuccessor(LabelRef defaultSuccessor) {
- this.defaultSuccessor = defaultSuccessor;
+ throw new RuntimeException("No call statement in block " + getLabel().getFullName());
}
public LabelRef getDefaultSuccessor() {
return defaultSuccessor;
}
+ public void setDefaultSuccessor(LabelRef defaultSuccessor) {
+ this.defaultSuccessor = defaultSuccessor;
+ }
+
public LabelRef getConditionalSuccessor() {
return conditionalSuccessor;
}
@@ -118,6 +120,7 @@ public class ControlFlowBlock {
/**
* Is the block the entry of a procedure, ie. the first block of the code of the procedure.
+ *
* @return true if this is the entry of a procedure
*/
public boolean isProcedureEntry(Program program) {
@@ -126,7 +129,8 @@ public class ControlFlowBlock {
}
/**
- * Is the block the exit of a procedure, ie. the last block of code of the the procedure
+ * Is the block the exit of a procedure, ie. the last block of code of the the procedure
+ *
* @param program
* @return true if this is the exit of a procedure
*/
@@ -139,12 +143,12 @@ public class ControlFlowBlock {
ControlFlowGraph graph = program.getGraph();
StringBuffer out = new StringBuffer();
out.append(label.getFullName() + ":");
- out.append(" scope:["+scope.getFullName()+"] ");
+ out.append(" scope:[" + scope.getFullName() + "] ");
out.append(" from");
- if (graph != null) {
+ if(graph != null) {
List predecessors = graph.getPredecessors(this);
- if (predecessors.size() > 0) {
- for (ControlFlowBlock predecessor : predecessors) {
+ if(predecessors.size() > 0) {
+ for(ControlFlowBlock predecessor : predecessors) {
out.append(" " + predecessor.getLabel().getFullName());
}
}
@@ -152,10 +156,10 @@ public class ControlFlowBlock {
out.append(" @UNKNOWN");
}
out.append("\n");
- for (Statement statement : statements) {
+ for(Statement statement : statements) {
out.append(" " + statement.toString(program, true) + "\n");
}
- if (defaultSuccessor != null) {
+ if(defaultSuccessor != null) {
out.append(" to:");
out.append(defaultSuccessor.getFullName());
out.append("\n");
@@ -165,16 +169,16 @@ public class ControlFlowBlock {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
ControlFlowBlock that = (ControlFlowBlock) o;
- if (!label.equals(that.label)) return false;
- if (statements != null ? !statements.equals(that.statements) : that.statements != null) return false;
- if (defaultSuccessor != null ? !defaultSuccessor.equals(that.defaultSuccessor) : that.defaultSuccessor != null)
+ if(!label.equals(that.label)) return false;
+ if(statements != null ? !statements.equals(that.statements) : that.statements != null) return false;
+ if(defaultSuccessor != null ? !defaultSuccessor.equals(that.defaultSuccessor) : that.defaultSuccessor != null)
return false;
- if (conditionalSuccessor != null ? !conditionalSuccessor.equals(that.conditionalSuccessor) : that.conditionalSuccessor != null)
+ if(conditionalSuccessor != null ? !conditionalSuccessor.equals(that.conditionalSuccessor) : that.conditionalSuccessor != null)
return false;
return callSuccessor != null ? callSuccessor.equals(that.callSuccessor) : that.callSuccessor == null;
}
@@ -191,15 +195,16 @@ public class ControlFlowBlock {
/**
* Get the phi block for the block. If the phi block has not yet been created it is created.
+ *
* @return
*/
@JsonIgnore
public StatementPhiBlock getPhiBlock() {
StatementPhiBlock phiBlock = null;
- if (statements.size() > 0 && statements.get(0) instanceof StatementPhiBlock) {
+ if(statements.size() > 0 && statements.get(0) instanceof StatementPhiBlock) {
phiBlock = (StatementPhiBlock) statements.get(0);
}
- if (phiBlock == null) {
+ if(phiBlock == null) {
phiBlock = new StatementPhiBlock();
statements.add(0, phiBlock);
}
@@ -207,8 +212,8 @@ public class ControlFlowBlock {
}
public boolean hasPhiBlock() {
- if (statements.size() > 0) {
- if (statements.get(0) instanceof StatementPhiBlock) {
+ if(statements.size() > 0) {
+ if(statements.get(0) instanceof StatementPhiBlock) {
return true;
}
}
@@ -216,20 +221,21 @@ public class ControlFlowBlock {
}
- /** Get all successors of the block
+ /**
+ * Get all successors of the block
*
* @return All successors
*/
@JsonIgnore
public Collection getSuccessors() {
List successors = new ArrayList<>();
- if (defaultSuccessor != null) {
+ if(defaultSuccessor != null) {
successors.add(defaultSuccessor);
}
- if (conditionalSuccessor != null) {
+ if(conditionalSuccessor != null) {
successors.add(conditionalSuccessor);
}
- if (callSuccessor != null) {
+ if(callSuccessor != null) {
successors.add(callSuccessor);
}
return successors;
diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java
index 8e851c313..978d17f1e 100644
--- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java
+++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraph.java
@@ -50,9 +50,9 @@ public class ControlFlowGraph {
@JsonIgnore
public Collection getAllBlocks() {
- if (sequence != null) {
+ if(sequence != null) {
ArrayList blocks = new ArrayList<>();
- for (LabelRef labelRef : sequence) {
+ for(LabelRef labelRef : sequence) {
blocks.add(getBlock(labelRef));
}
return blocks;
@@ -72,11 +72,11 @@ public class ControlFlowGraph {
* @return The assignment. null if the variable is not assigned. The variable is assigned by a Phi-statement instead.
*/
public StatementAssignment getAssignment(VariableRef variable) {
- for (ControlFlowBlock block : getAllBlocks()) {
- for (Statement statement : block.getStatements()) {
- if (statement instanceof StatementAssignment) {
+ for(ControlFlowBlock block : getAllBlocks()) {
+ for(Statement statement : block.getStatements()) {
+ if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
- if (assignment.getlValue().equals(variable)) {
+ if(assignment.getlValue().equals(variable)) {
return assignment;
}
}
@@ -92,15 +92,15 @@ public class ControlFlowGraph {
* @return The block containing the assignment. null if the variable is not assigned.
*/
public ControlFlowBlock getAssignmentBlock(VariableRef variable) {
- for (ControlFlowBlock block : getAllBlocks()) {
- for (Statement statement : block.getStatements()) {
- if (statement instanceof StatementAssignment) {
+ for(ControlFlowBlock block : getAllBlocks()) {
+ for(Statement statement : block.getStatements()) {
+ if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
- if (assignment.getlValue().equals(variable)) {
+ if(assignment.getlValue().equals(variable)) {
return block;
}
} else if(statement instanceof StatementPhiBlock) {
- for (StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
+ for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
if(phiVariable.getVariable().equals(variable)) {
return block;
}
@@ -113,7 +113,7 @@ public class ControlFlowGraph {
public ControlFlowBlock getDefaultSuccessor(ControlFlowBlock block) {
- if (block.getDefaultSuccessor() != null) {
+ if(block.getDefaultSuccessor() != null) {
return blocks.get(block.getDefaultSuccessor());
} else {
return null;
@@ -121,7 +121,7 @@ public class ControlFlowGraph {
}
public ControlFlowBlock getCallSuccessor(ControlFlowBlock block) {
- if (block.getCallSuccessor() != null) {
+ if(block.getCallSuccessor() != null) {
return blocks.get(block.getCallSuccessor());
} else {
return null;
@@ -129,7 +129,7 @@ public class ControlFlowGraph {
}
public ControlFlowBlock getConditionalSuccessor(ControlFlowBlock block) {
- if (block.getConditionalSuccessor() != null) {
+ if(block.getConditionalSuccessor() != null) {
return blocks.get(block.getConditionalSuccessor());
} else {
return null;
@@ -139,14 +139,14 @@ public class ControlFlowGraph {
public List getPredecessors(ControlFlowBlock block) {
ArrayList predecessorBlocks = new ArrayList<>();
- for (ControlFlowBlock other : getAllBlocks()) {
- if (block.getLabel().equals(other.getDefaultSuccessor())) {
+ for(ControlFlowBlock other : getAllBlocks()) {
+ if(block.getLabel().equals(other.getDefaultSuccessor())) {
predecessorBlocks.add(other);
}
- if (block.getLabel().equals(other.getConditionalSuccessor())) {
+ if(block.getLabel().equals(other.getConditionalSuccessor())) {
predecessorBlocks.add(other);
}
- if (block.getLabel().equals(other.getCallSuccessor())) {
+ if(block.getLabel().equals(other.getCallSuccessor())) {
predecessorBlocks.add(other);
}
}
@@ -164,9 +164,9 @@ public class ControlFlowGraph {
@JsonIgnore
public ControlFlowBlock getMainBlock() {
- for (ControlFlowBlock block : getAllBlocks()) {
+ for(ControlFlowBlock block : getAllBlocks()) {
LabelRef label = block.getLabel();
- if (label.getFullName().equals("main")) {
+ if(label.getFullName().equals("main")) {
return block;
}
}
@@ -180,7 +180,7 @@ public class ControlFlowGraph {
public String toString(Program program) {
StringBuffer out = new StringBuffer();
- for (ControlFlowBlock block : getAllBlocks()) {
+ for(ControlFlowBlock block : getAllBlocks()) {
out.append(block.toString(program));
}
return out.toString();
@@ -188,13 +188,13 @@ public class ControlFlowGraph {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
ControlFlowGraph that = (ControlFlowGraph) o;
- if (!blocks.equals(that.blocks)) return false;
- if (!firstBlockRef.equals(that.firstBlockRef)) return false;
+ if(!blocks.equals(that.blocks)) return false;
+ if(!firstBlockRef.equals(that.firstBlockRef)) return false;
return sequence != null ? sequence.equals(that.sequence) : that.sequence == null;
}
@@ -213,9 +213,9 @@ public class ControlFlowGraph {
* @return The statement
*/
public Statement getStatementByIndex(int statementIdx) {
- for (ControlFlowBlock block : getAllBlocks()) {
- for (Statement statement : block.getStatements()) {
- if (statementIdx == statement.getIndex()) {
+ for(ControlFlowBlock block : getAllBlocks()) {
+ for(Statement statement : block.getStatements()) {
+ if(statementIdx == statement.getIndex()) {
return statement;
}
}
@@ -231,8 +231,8 @@ public class ControlFlowGraph {
*/
public List getScopeBlocks(ScopeRef scope) {
ArrayList scopeBlocks = new ArrayList<>();
- for (ControlFlowBlock block : getAllBlocks()) {
- if (block.getScope().equals(scope)) {
+ for(ControlFlowBlock block : getAllBlocks()) {
+ if(block.getScope().equals(scope)) {
scopeBlocks.add(block);
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphBaseVisitor.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphBaseVisitor.java
index 3e813a3b6..66935f3eb 100644
--- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphBaseVisitor.java
+++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphBaseVisitor.java
@@ -7,14 +7,14 @@ public class ControlFlowGraphBaseVisitor {
public T visitGraph(ControlFlowGraph graph) {
Collection blocks = graph.getAllBlocks();
- for (ControlFlowBlock block : blocks) {
+ for(ControlFlowBlock block : blocks) {
this.visitBlock(block);
}
return null;
}
public T visitBlock(ControlFlowBlock block) {
- for (Statement statement : block.getStatements()) {
+ for(Statement statement : block.getStatements()) {
this.visitStatement(statement);
}
return null;
@@ -42,7 +42,7 @@ public class ControlFlowGraphBaseVisitor {
} else if(statement instanceof StatementAsm) {
return visitAsm((StatementAsm) statement);
} else {
- throw new RuntimeException("Unhandled statement type "+statement);
+ throw new RuntimeException("Unhandled statement type " + statement);
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java
index ece1c5a69..a4a958019 100644
--- a/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java
+++ b/src/main/java/dk/camelot64/kickc/model/ControlFlowGraphCopyVisitor.java
@@ -33,9 +33,9 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor();
- for (ControlFlowBlock origBlock : origGraph.getAllBlocks()) {
+ for(ControlFlowBlock origBlock : origGraph.getAllBlocks()) {
ControlFlowBlock copyBlock = visitBlock(origBlock);
- if (copyBlock != null) {
+ if(copyBlock != null) {
copyBlockMap.put(copyBlock.getLabel(), copyBlock);
}
}
@@ -52,20 +52,20 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor origBlockStatements = origBlock.getStatements();
- for (Statement origStatement : origBlockStatements) {
+ for(Statement origStatement : origBlockStatements) {
Statement copyStatement = visitStatement(origStatement);
- if (copyStatement != null) {
+ if(copyStatement != null) {
this.copyBlock.addStatement(copyStatement);
}
}
// Handle successors
- if (origBlock.getDefaultSuccessor() != null) {
+ if(origBlock.getDefaultSuccessor() != null) {
this.copyBlock.setDefaultSuccessor(origBlock.getDefaultSuccessor());
}
- if (origBlock.getConditionalSuccessor() != null) {
+ if(origBlock.getConditionalSuccessor() != null) {
this.copyBlock.setConditionalSuccessor(origBlock.getConditionalSuccessor());
}
- if (origBlock.getCallSuccessor() != null) {
+ if(origBlock.getCallSuccessor() != null) {
this.copyBlock.setCallSuccessor(origBlock.getCallSuccessor());
}
ControlFlowBlock result = this.copyBlock;
@@ -120,10 +120,10 @@ public class ControlFlowGraphCopyVisitor extends ControlFlowGraphBaseVisitor
* Definition: Block d dominates block i if all paths from entry to block i includes block d
*
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
- * */
+ */
public class DominatorsBlock {
/**
@@ -37,7 +38,7 @@ public class DominatorsBlock {
* @param dominators The dominators to add
*/
public void addAll(Collection dominators) {
- for (LabelRef dominator : dominators) {
+ for(LabelRef dominator : dominators) {
add(dominator);
}
@@ -51,9 +52,9 @@ public class DominatorsBlock {
*/
public void intersect(DominatorsBlock other) {
Iterator iterator = dominators.iterator();
- while (iterator.hasNext()) {
+ while(iterator.hasNext()) {
LabelRef dominator = iterator.next();
- if (!other.contains(dominator)) {
+ if(!other.contains(dominator)) {
iterator.remove();
}
}
@@ -75,8 +76,8 @@ public class DominatorsBlock {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
DominatorsBlock that = (DominatorsBlock) o;
@@ -91,7 +92,7 @@ public class DominatorsBlock {
@Override
public String toString() {
StringBuilder out = new StringBuilder();
- for (LabelRef dominator : dominators) {
+ for(LabelRef dominator : dominators) {
out.append(dominator);
out.append(" ");
}
diff --git a/src/main/java/dk/camelot64/kickc/model/DominatorsGraph.java b/src/main/java/dk/camelot64/kickc/model/DominatorsGraph.java
index 654cfca39..2130fb9c9 100644
--- a/src/main/java/dk/camelot64/kickc/model/DominatorsGraph.java
+++ b/src/main/java/dk/camelot64/kickc/model/DominatorsGraph.java
@@ -3,13 +3,13 @@ package dk.camelot64.kickc.model;
import java.util.LinkedHashMap;
import java.util.Map;
-/** Dominators for a control flow graph.
+/**
+ * Dominators for a control flow graph.
*
* Definition: Block d dominates block i if all paths from entry to block i includes block d
*
* See http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
- *
- * */
+ */
public class DominatorsGraph {
/**
@@ -47,7 +47,7 @@ public class DominatorsGraph {
/**
* Set the dominators for a specific block
*
- * @param block The block
+ * @param block The block
* @param dominators The new dominators
*/
public void setDominators(LabelRef block, DominatorsBlock dominators) {
@@ -57,7 +57,7 @@ public class DominatorsGraph {
@Override
public String toString() {
StringBuilder out = new StringBuilder();
- for (LabelRef block : blockDominators.keySet()) {
+ for(LabelRef block : blockDominators.keySet()) {
DominatorsBlock dominators = getDominators(block);
out.append(block);
out.append(" dominated by ");
diff --git a/src/main/java/dk/camelot64/kickc/model/LValue.java b/src/main/java/dk/camelot64/kickc/model/LValue.java
index a98c937e9..37b2f53b2 100644
--- a/src/main/java/dk/camelot64/kickc/model/LValue.java
+++ b/src/main/java/dk/camelot64/kickc/model/LValue.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.model;
-/** Assignable value (capable of being on the left part of an assignment)*/
+/** Assignable value (capable of being on the left part of an assignment) */
public interface LValue extends RValue {
/**
diff --git a/src/main/java/dk/camelot64/kickc/model/Label.java b/src/main/java/dk/camelot64/kickc/model/Label.java
index 29756c032..20d3d6ffd 100644
--- a/src/main/java/dk/camelot64/kickc/model/Label.java
+++ b/src/main/java/dk/camelot64/kickc/model/Label.java
@@ -47,10 +47,10 @@ public class Label implements Symbol {
@Override
public int getScopeDepth() {
- if(scope==null) {
+ if(scope == null) {
return 0;
} else {
- return scope.getScopeDepth()+1;
+ return scope.getScopeDepth() + 1;
}
}
@@ -70,13 +70,13 @@ public class Label implements Symbol {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
Label label = (Label) o;
- if (intermediate != label.intermediate) return false;
- if (!name.equals(label.name)) return false;
+ if(intermediate != label.intermediate) return false;
+ if(!name.equals(label.name)) return false;
return getFullName().equals(label.getFullName());
}
@@ -94,10 +94,10 @@ public class Label implements Symbol {
@Override
public String toString(Program program) {
- if(program ==null) {
+ if(program == null) {
return getFullName();
- } else {
- return "("+getType().getTypeName() + ") "+getFullName();
+ } else {
+ return "(" + getType().getTypeName() + ") " + getFullName();
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/LabelRef.java b/src/main/java/dk/camelot64/kickc/model/LabelRef.java
index 32b00b9c2..7b2b5d83c 100644
--- a/src/main/java/dk/camelot64/kickc/model/LabelRef.java
+++ b/src/main/java/dk/camelot64/kickc/model/LabelRef.java
@@ -3,7 +3,7 @@ package dk.camelot64.kickc.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
-/** A reference to a label */
+/** A reference to a label */
public class LabelRef extends SymbolRef {
@JsonCreator
diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRange.java b/src/main/java/dk/camelot64/kickc/model/LiveRange.java
index 154c38746..cb69cfe17 100644
--- a/src/main/java/dk/camelot64/kickc/model/LiveRange.java
+++ b/src/main/java/dk/camelot64/kickc/model/LiveRange.java
@@ -16,6 +16,154 @@ public class LiveRange {
*/
private List intervals;
+ public LiveRange() {
+ this.intervals = new ArrayList<>();
+ }
+
+ /**
+ * Add a statement to the live range
+ *
+ * @param statement The statement to add
+ * @return true if the live range was modified by the addition. false otherwise
+ */
+ public boolean add(Statement statement) {
+ return add(getIndex(statement));
+ }
+
+ private Integer getIndex(Statement statement) {
+ Integer index = statement.getIndex();
+ if(index == null) {
+ throw new RuntimeException("Statement index not defined! Live Ranges only work after defining statement indexes (Pass3LiveRangesAnalysis.generateStatementIndices).");
+ }
+ return index;
+ }
+
+ /**
+ * Get the number of statements in the live range.
+ *
+ * @return The number of statements in the live range.
+ */
+ public int size() {
+ int s = 0;
+ for(LiveInterval interval : intervals) {
+ s += interval.size();
+ }
+ return s;
+ }
+
+ /**
+ * Add an index to the live range
+ *
+ * @param index The index to add
+ * @return true if the live range was modified. false otherwise
+ */
+ public boolean add(int index) {
+ for(int i = 0; i < intervals.size(); i++) {
+ LiveInterval interval = intervals.get(i);
+ if(index < interval.firstStatementIdx - 1) {
+ // Add new interval before the current interval
+ intervals.add(i, new LiveInterval(index, index));
+ return true;
+ } else if(index == interval.firstStatementIdx - 1) {
+ // Extend the current interval downward
+ interval.firstStatementIdx = index;
+ return true;
+ } else if(index <= interval.lastStatementIdx) {
+ // Already inside the interval
+ return false;
+ } else if(index == interval.lastStatementIdx + 1) {
+ // Extend current interval upward - and check if next interval should be merged
+ interval.lastStatementIdx = index;
+ if(i < intervals.size() - 1) {
+ LiveInterval nextInterval = intervals.get(i + 1);
+ if(nextInterval.firstStatementIdx == index + 1) {
+ // Merge intervals
+ interval.lastStatementIdx = nextInterval.lastStatementIdx;
+ intervals.remove(i + 1);
+ }
+ }
+ return true;
+ }
+ }
+ // Not added yet - add a new interval at the end
+ intervals.add(new LiveInterval(index, index));
+ return true;
+ }
+
+ /**
+ * Determines if this live range overlaps another live range
+ *
+ * @param other The other live range
+ * @return true if there is an overlap
+ */
+ public boolean overlaps(LiveRange other) {
+ if(this.getMaxIndex() == -1 || other.getMaxIndex() == -1) {
+ return false;
+ }
+ int maxIdx = getMaxIndex();
+ for(int i = 0; i <= maxIdx; i++) {
+ if(contains(i) && other.contains(i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds another live range to this one - extending this live range to include the other one.
+ *
+ * @param other The live range to add
+ */
+ public void add(LiveRange other) {
+ int otherMaxIndex = other.getMaxIndex();
+ for(int i = 0; i <= otherMaxIndex; i++) {
+ if(other.contains(i)) {
+ add(i);
+ }
+ }
+ }
+
+ /**
+ * Determines if the live range contains a statement
+ *
+ * @param statement The statement to examine
+ * @return true if the live range contains the statement
+ */
+ public boolean contains(Statement statement) {
+ return contains(getIndex(statement));
+ }
+
+ /**
+ * Determines if the live range contains an index
+ *
+ * @param index
+ * @return true if the live range contains the index
+ */
+ private boolean contains(int index) {
+ for(LiveInterval interval : intervals) {
+ if(interval.lastStatementIdx >= index) {
+ if(interval.firstStatementIdx <= index) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get the maximal index contained in the live range
+ *
+ * @return The max index. -1 if the range is empty.
+ */
+ int getMaxIndex() {
+ if(intervals.isEmpty()) {
+ return -1;
+ }
+ return intervals.get(intervals.size() - 1).lastStatementIdx;
+ }
+
public static class LiveInterval {
/**
@@ -48,157 +196,16 @@ public class LiveRange {
return lastStatementIdx;
}
- /** Get the number of statements in the live interval.
+ /**
+ * Get the number of statements in the live interval.
*
* @return The number of statements in the live interval.
*/
public int size() {
- return lastStatementIdx-firstStatementIdx+1;
+ return lastStatementIdx - firstStatementIdx + 1;
}
}
- public LiveRange() {
- this.intervals = new ArrayList<>();
- }
-
- /**
- * Add a statement to the live range
- *
- * @param statement The statement to add
- * @return true if the live range was modified by the addition. false otherwise
- */
- public boolean add(Statement statement) {
- return add(getIndex(statement));
- }
-
- private Integer getIndex(Statement statement) {
- Integer index = statement.getIndex();
- if (index == null) {
- throw new RuntimeException("Statement index not defined! Live Ranges only work after defining statement indexes (Pass3LiveRangesAnalysis.generateStatementIndices).");
- }
- return index;
- }
-
- /** Get the number of statements in the live range.
- *
- * @return The number of statements in the live range.
- */
- public int size() {
- int s = 0;
- for (LiveInterval interval : intervals) {
- s += interval.size();
- }
- return s;
- }
-
-
- /**
- * Add an index to the live range
- * @param index The index to add
- * @return true if the live range was modified. false otherwise
- */
- public boolean add(int index) {
- for (int i = 0; i < intervals.size(); i++) {
- LiveInterval interval = intervals.get(i);
- if (index < interval.firstStatementIdx - 1) {
- // Add new interval before the current interval
- intervals.add(i, new LiveInterval(index, index));
- return true;
- } else if(index == interval.firstStatementIdx - 1) {
- // Extend the current interval downward
- interval.firstStatementIdx = index;
- return true;
- } else if(index <= interval.lastStatementIdx) {
- // Already inside the interval
- return false;
- } else if(index == interval.lastStatementIdx+1) {
- // Extend current interval upward - and check if next interval should be merged
- interval.lastStatementIdx = index;
- if(i=index) {
- if(interval.firstStatementIdx<=index) {
- return true;
- } else {
- return false;
- }
- }
- }
- return false;
- }
-
- /**
- * Get the maximal index contained in the live range
- * @return The max index. -1 if the range is empty.
- */
- int getMaxIndex() {
- if(intervals.isEmpty()) {
- return -1;
- }
- return intervals.get(intervals.size()-1).lastStatementIdx;
- }
-
}
diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClass.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClass.java
index a33a370b2..0efb9f633 100644
--- a/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClass.java
+++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClass.java
@@ -46,7 +46,7 @@ public class LiveRangeEquivalenceClass {
}
LiveRangeVariables liveRanges = set.getProgram().getLiveRangeVariables();
LiveRange varLiveRange = liveRanges.getLiveRange(variable);
- if (liveRange.overlaps(varLiveRange)) {
+ if(liveRange.overlaps(varLiveRange)) {
throw new RuntimeException("Compilation error! Variable live range overlaps live range equivalence class live range. " + variable);
}
liveRange.add(varLiveRange);
@@ -75,15 +75,15 @@ public class LiveRangeEquivalenceClass {
public void addAll(LiveRangeEquivalenceClass other) {
liveRange.add(other.liveRange);
variables.addAll(other.variables);
- for (VariableRef variable : other.variables) {
+ for(VariableRef variable : other.variables) {
set.setVarClass(variable, this);
}
}
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
LiveRangeEquivalenceClass that = (LiveRangeEquivalenceClass) o;
return variables.equals(that.variables);
}
@@ -100,11 +100,11 @@ public class LiveRangeEquivalenceClass {
public String toString(boolean includeRegister) {
StringBuilder s = new StringBuilder();
- if(includeRegister && register!=null) {
+ if(includeRegister && register != null) {
s.append(register.toString()).append(" ");
}
s.append("[ ");
- for (VariableRef variable : variables) {
+ for(VariableRef variable : variables) {
s.append(variable.toString());
s.append(" ");
}
diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClassSet.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClassSet.java
index f2edbae16..bc681f999 100644
--- a/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClassSet.java
+++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeEquivalenceClassSet.java
@@ -10,21 +10,19 @@ import java.util.Map;
*/
public class LiveRangeEquivalenceClassSet {
+ /**
+ * Maps variables to their containing class.
+ */
+ Map varClass;
/**
* The containing program.
*/
private Program program;
-
/**
* The equivalence classes of the set.
*/
private List equivalenceClasses;
- /**
- * Maps variables to their containing class.
- */
- Map varClass;
-
public LiveRangeEquivalenceClassSet(Program program) {
this.program = program;
this.equivalenceClasses = new ArrayList<>();
@@ -49,7 +47,7 @@ public class LiveRangeEquivalenceClassSet {
*/
public LiveRangeEquivalenceClass getOrCreateEquivalenceClass(VariableRef variable) {
LiveRangeEquivalenceClass equivalenceClass = getEquivalenceClass(variable);
- if (equivalenceClass != null) {
+ if(equivalenceClass != null) {
return equivalenceClass;
}
// Not found - create it
@@ -62,6 +60,7 @@ public class LiveRangeEquivalenceClassSet {
/**
* Consolidates two live range equivalence calsses into one.
* All variables and live ranges from the other class is added to the first one - and the other one is deleted.
+ *
* @param equivalenceClass The first live range equivalence class.
* @param otherEquivalenceClass The other live range equivalence class, that is added to the first and deleted.
*/
@@ -73,7 +72,7 @@ public class LiveRangeEquivalenceClassSet {
/**
* Informs the set that class of a variable has ben set - called by add/remove methods inside LiveRangeEquivalenceClass
*
- * @param variable The variable
+ * @param variable The variable
* @param equivalenceClass The class
*/
void setVarClass(VariableRef variable, LiveRangeEquivalenceClass equivalenceClass) {
@@ -102,9 +101,9 @@ public class LiveRangeEquivalenceClassSet {
* Store the register allocation of the live range equivalence classes into the variables in the symbol table (program scope).
*/
public void storeRegisterAllocation() {
- for (LiveRangeEquivalenceClass equivalenceClass : getEquivalenceClasses()) {
+ for(LiveRangeEquivalenceClass equivalenceClass : getEquivalenceClasses()) {
Registers.Register register = equivalenceClass.getRegister();
- for (VariableRef variable : equivalenceClass.getVariables()) {
+ for(VariableRef variable : equivalenceClass.getVariables()) {
Variable var = program.getSymbolInfos().getVariable(variable);
var.setAllocation(register);
}
diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java
index 6088d1538..8d3329566 100644
--- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java
+++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariables.java
@@ -1,8 +1,11 @@
package dk.camelot64.kickc.model;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
-/** Live ranges for all variables.
+/**
+ * Live ranges for all variables.
* Created by {@link dk.camelot64.kickc.passes.Pass3CallGraphAnalysis}
*/
public class LiveRangeVariables {
@@ -16,7 +19,8 @@ public class LiveRangeVariables {
this.program = program;
}
- /** Add a single statement to the live range of a variable.
+ /**
+ * Add a single statement to the live range of a variable.
*
* @param variable The variable
* @param statement The statement to add
@@ -24,7 +28,7 @@ public class LiveRangeVariables {
*/
public boolean addAlive(VariableRef variable, Statement statement) {
LiveRange liveRange = liveRanges.get(variable);
- if (liveRange == null) {
+ if(liveRange == null) {
liveRange = new LiveRange();
liveRanges.put(variable, liveRange);
}
@@ -33,11 +37,12 @@ public class LiveRangeVariables {
/**
* Add an empty alive range for a variable
+ *
* @param variable The variable
*/
public void addEmptyAlive(VariableRef variable) {
LiveRange liveRange = liveRanges.get(variable);
- if (liveRange == null) {
+ if(liveRange == null) {
liveRange = new LiveRange();
liveRanges.put(variable, liveRange);
}
@@ -45,12 +50,13 @@ public class LiveRangeVariables {
/**
* Get all variables alive at a specific statement
+ *
* @param statement The statement
* @return List of all live variables.
*/
public List getAlive(Statement statement) {
ArrayList aliveVars = new ArrayList<>();
- for (VariableRef variable : liveRanges.keySet()) {
+ for(VariableRef variable : liveRanges.keySet()) {
LiveRange liveRange = liveRanges.get(variable);
if(liveRange.contains(statement)) {
aliveVars.add(variable);
@@ -61,6 +67,7 @@ public class LiveRangeVariables {
/**
* Get the alive range of a variable
+ *
* @param variable The variable reference
* @return The alive range for the variable
*/
diff --git a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java
index d7094027f..f845ece9b 100644
--- a/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java
+++ b/src/main/java/dk/camelot64/kickc/model/LiveRangeVariablesEffective.java
@@ -34,13 +34,84 @@ public class LiveRangeVariablesEffective {
this.procedureCallPaths = procedureCallPaths;
this.referenceInfo = referenceInfo;
this.statementsLiveVariables = new LinkedHashMap<>();
- for (ControlFlowBlock block : program.getGraph().getAllBlocks()) {
- for (Statement statement : block.getStatements()) {
+ for(ControlFlowBlock block : program.getGraph().getAllBlocks()) {
+ for(Statement statement : block.getStatements()) {
statementsLiveVariables.put(statement.getIndex(), liveRangeVariables.getAlive(statement));
}
}
}
+ /**
+ * Get all variables potentially alive at a statement.
+ * If the statement is inside a method this also includes all variables alive at the exit of any call.
+ *
+ *
+ * @param statement The statement to examine
+ * @return All variables potentially alive at the statement
+ */
+ public Collection getAliveEffective(Statement statement) {
+ Set effectiveAliveTotal = new LinkedHashSet<>();
+ AliveCombinations aliveCombinations = getAliveCombinations(statement);
+ for(CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
+ Collection alive = aliveCombinations.getEffectiveAliveAtStmt(callPath);
+ effectiveAliveTotal.addAll(alive);
+ }
+ return effectiveAliveTotal;
+ }
+
+ /**
+ * Get all combinations of variables alive at a statement.
+ * If the statement is inside a method the different combinations in the result arises from different calls of the method
+ * (recursively up til the main()-method.)
+ * Each combination includes all variables alive at the exit of any surrounding call.
+ * Also includes variable aliases that are part of the parameter assignments to the calls on the path.
+ *
+ *
+ * @param statement The statement to examine
+ * @return All combinations of variables alive at the statement
+ */
+ public AliveCombinations getAliveCombinations(Statement statement) {
+ Collection aliveAtStmt = statementsLiveVariables.get(statement.getIndex());
+ CallPaths callPaths;
+ Collection referencedInProcedure;
+ ControlFlowBlock block = program.getStatementInfos().getBlock(statement);
+ ScopeRef scopeRef = block.getScope();
+ Scope scope = program.getScope().getScope(scopeRef);
+ if(scope instanceof Procedure) {
+ Procedure procedure = (Procedure) scope;
+ callPaths = procedureCallPaths.get(procedure.getRef());
+ referencedInProcedure = referenceInfo.getReferencedVars(procedure.getRef().getLabelRef());
+ } else {
+ callPaths = new CallPaths(Procedure.ROOT);
+ referencedInProcedure = new ArrayList<>();
+ }
+ Pass2AliasElimination.Aliases callAliases = null;
+ // Examine if the statement is a parameter assignment before a call
+ LabelRef callSuccessor = block.getCallSuccessor();
+ if(callSuccessor != null) {
+ ProcedureRef calledRef = new ProcedureRef(callSuccessor.getFullName());
+ CallPaths calledRefs = procedureCallPaths.get(calledRef);
+ for(CallPath calledPath : calledRefs.getCallPaths()) {
+ List path = calledPath.getPath();
+ CallGraph.CallBlock.Call lastCall = path.get(path.size() - 1);
+ Integer lastCallStatementIdx = lastCall.getCallStatementIdx();
+ LabelRef lastCallBlockRef = program.getStatementInfos().getBlockRef(lastCallStatementIdx);
+ if(lastCallBlockRef.equals(block.getLabel())) {
+ if(callAliases == null) {
+ // Found a matching call!
+ callAliases = calledPath.getInnerAliases();
+ } else {
+ // Found another matching call!
+ callAliases = new Pass2AliasElimination.Aliases(callAliases);
+ callAliases.addAll(calledPath.getInnerAliases());
+ }
+ }
+ }
+ }
+
+ return new AliveCombinations(callPaths, referencedInProcedure, aliveAtStmt, callAliases);
+ }
+
/**
* All call-paths leading into a specific procedure.
*/
@@ -104,6 +175,7 @@ public class LiveRangeVariablesEffective {
/**
* The path from main() to the procedure. First element is the call to main(), last element is the call to the procedure.
+ *
* @return Tha call path
*/
public List getPath() {
@@ -112,6 +184,7 @@ public class LiveRangeVariablesEffective {
/**
* Alive variables on the call-path. Based on alive vars at each call in the path.
+ *
* @return The alive variables
*/
public Collection getAlive() {
@@ -120,6 +193,7 @@ public class LiveRangeVariablesEffective {
/**
* Alias variables from the entire call-path. Any variables alias-assigned as part of a call on the path (in parameter assignment or phi block).
+ *
* @return The aliases
*/
public Pass2AliasElimination.Aliases getPathAliases() {
@@ -128,6 +202,7 @@ public class LiveRangeVariablesEffective {
/**
* Alias variables for the innermost call. Variables alias-assigned as part of the innermost call on the path (in parameter assignment or phi block).
+ *
* @return The aliases
*/
public Pass2AliasElimination.Aliases getInnerAliases() {
@@ -135,78 +210,6 @@ public class LiveRangeVariablesEffective {
}
}
-
- /**
- * Get all variables potentially alive at a statement.
- * If the statement is inside a method this also includes all variables alive at the exit of any call.
- *
- *
- * @param statement The statement to examine
- * @return All variables potentially alive at the statement
- */
- public Collection getAliveEffective(Statement statement) {
- Set effectiveAliveTotal = new LinkedHashSet<>();
- AliveCombinations aliveCombinations = getAliveCombinations(statement);
- for (CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
- Collection alive = aliveCombinations.getEffectiveAliveAtStmt(callPath);
- effectiveAliveTotal.addAll(alive);
- }
- return effectiveAliveTotal;
- }
-
- /**
- * Get all combinations of variables alive at a statement.
- * If the statement is inside a method the different combinations in the result arises from different calls of the method
- * (recursively up til the main()-method.)
- * Each combination includes all variables alive at the exit of any surrounding call.
- * Also includes variable aliases that are part of the parameter assignments to the calls on the path.
- *
- *
- * @param statement The statement to examine
- * @return All combinations of variables alive at the statement
- */
- public AliveCombinations getAliveCombinations(Statement statement) {
- Collection aliveAtStmt = statementsLiveVariables.get(statement.getIndex());
- CallPaths callPaths;
- Collection referencedInProcedure;
- ControlFlowBlock block = program.getStatementInfos().getBlock(statement);
- ScopeRef scopeRef = block.getScope();
- Scope scope = program.getScope().getScope(scopeRef);
- if (scope instanceof Procedure) {
- Procedure procedure = (Procedure) scope;
- callPaths = procedureCallPaths.get(procedure.getRef());
- referencedInProcedure = referenceInfo.getReferencedVars(procedure.getRef().getLabelRef());
- } else {
- callPaths = new CallPaths(Procedure.ROOT);
- referencedInProcedure = new ArrayList<>();
- }
- Pass2AliasElimination.Aliases callAliases = null;
- // Examine if the statement is a parameter assignment before a call
- LabelRef callSuccessor = block.getCallSuccessor();
- if(callSuccessor !=null) {
- ProcedureRef calledRef = new ProcedureRef(callSuccessor.getFullName());
- CallPaths calledRefs = procedureCallPaths.get(calledRef);
- for (CallPath calledPath : calledRefs.getCallPaths()) {
- List path = calledPath.getPath();
- CallGraph.CallBlock.Call lastCall = path.get(path.size() - 1);
- Integer lastCallStatementIdx = lastCall.getCallStatementIdx();
- LabelRef lastCallBlockRef = program.getStatementInfos().getBlockRef(lastCallStatementIdx);
- if(lastCallBlockRef.equals(block.getLabel())) {
- if (callAliases == null) {
- // Found a matching call!
- callAliases = calledPath.getInnerAliases();
- } else {
- // Found another matching call!
- callAliases = new Pass2AliasElimination.Aliases(callAliases);
- callAliases.addAll(calledPath.getInnerAliases());
- }
- }
- }
- }
-
- return new AliveCombinations(callPaths, referencedInProcedure, aliveAtStmt, callAliases);
- }
-
/**
* Combinations of variables effectively alive at a specific statement.
* If the statement is inside a method the combinations are the live variables inside the method combined with each calling statements alive vars.
@@ -244,6 +247,7 @@ public class LiveRangeVariablesEffective {
/**
* Get all variables effective alive at the statement for a specific call path.
+ *
* @param callPath The call path (returned from getCallPaths)
* @return All variables effectively alive at the statement on the call-path
*/
@@ -259,7 +263,7 @@ public class LiveRangeVariablesEffective {
}
public Pass2AliasElimination.Aliases getEffectiveAliasesAtStmt(CallPath callPath) {
- if(callAliases==null) {
+ if(callAliases == null) {
return callPath.getPathAliases();
} else {
Pass2AliasElimination.Aliases aliases = new Pass2AliasElimination.Aliases();
diff --git a/src/main/java/dk/camelot64/kickc/model/LvalueIntermediate.java b/src/main/java/dk/camelot64/kickc/model/LvalueIntermediate.java
index 65051c5ca..a7c4932df 100644
--- a/src/main/java/dk/camelot64/kickc/model/LvalueIntermediate.java
+++ b/src/main/java/dk/camelot64/kickc/model/LvalueIntermediate.java
@@ -15,13 +15,13 @@ public class LvalueIntermediate implements LValue {
return variable;
}
+ public void setVariable(VariableRef variable) {
+ this.variable = variable;
+ }
+
@Override
public String toString(Program program) {
return "lval" + "(" + variable.toString(program) + ")";
}
- public void setVariable(VariableRef variable) {
- this.variable = variable;
- }
-
}
diff --git a/src/main/java/dk/camelot64/kickc/model/NaturalLoop.java b/src/main/java/dk/camelot64/kickc/model/NaturalLoop.java
index b9639bce9..7a9a1e27f 100644
--- a/src/main/java/dk/camelot64/kickc/model/NaturalLoop.java
+++ b/src/main/java/dk/camelot64/kickc/model/NaturalLoop.java
@@ -64,19 +64,19 @@ public class NaturalLoop {
out.append("Loop head: ")
.append(head)
.append(" tails: ");
- for (LabelRef tail : tails) {
+ for(LabelRef tail : tails) {
out.append(tail).append(" ");
}
out.append("blocks: ");
- if (blocks != null) {
- for (LabelRef block : blocks) {
+ if(blocks != null) {
+ for(LabelRef block : blocks) {
out.append(block.toString()).append(" ");
}
} else {
out.append("null");
}
- if(depth!=null) {
- out.append(" depth: "+depth);
+ if(depth != null) {
+ out.append(" depth: " + depth);
}
return out.toString();
}
@@ -88,8 +88,8 @@ public class NaturalLoop {
* @return true if this loop contains the other loop
*/
public boolean nests(NaturalLoop other) {
- for (LabelRef otherBlock : other.getBlocks()) {
- if (!blocks.contains(otherBlock)) {
+ for(LabelRef otherBlock : other.getBlocks()) {
+ if(!blocks.contains(otherBlock)) {
return false;
}
}
@@ -98,6 +98,7 @@ public class NaturalLoop {
/**
* Add more tails to the loop
+ *
* @param tails The tails to add
*/
public void addTails(Set tails) {
@@ -106,6 +107,7 @@ public class NaturalLoop {
/**
* Add more blocks to the loop
+ *
* @param blocks The blocks to add
*/
public void addBlocks(Set blocks) {
@@ -122,13 +124,13 @@ public class NaturalLoop {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
NaturalLoop that = (NaturalLoop) o;
- if (head != null ? !head.equals(that.head) : that.head != null) return false;
- if (tails != null ? !tails.equals(that.tails) : that.tails != null) return false;
+ if(head != null ? !head.equals(that.head) : that.head != null) return false;
+ if(tails != null ? !tails.equals(that.tails) : that.tails != null) return false;
return blocks != null ? blocks.equals(that.blocks) : that.blocks == null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/NaturalLoopSet.java b/src/main/java/dk/camelot64/kickc/model/NaturalLoopSet.java
index c84a3ab12..191d9115c 100644
--- a/src/main/java/dk/camelot64/kickc/model/NaturalLoopSet.java
+++ b/src/main/java/dk/camelot64/kickc/model/NaturalLoopSet.java
@@ -2,10 +2,11 @@ package dk.camelot64.kickc.model;
import java.util.*;
-/** A set of natural loops in a control flow graph.
+/**
+ * A set of natural loops in a control flow graph.
*
For definitions and more see http://www.cs.colostate.edu/~cs553/ClassNotes/lecture09-control-dominators.ppt.pdf
*
Created by {@link dk.camelot64.kickc.passes.Pass3LoopAnalysis}
- * */
+ */
public class NaturalLoopSet {
private List loops;
@@ -25,6 +26,7 @@ public class NaturalLoopSet {
/**
* Get all the loops
+ *
* @return The loops
*/
public List getLoops() {
@@ -34,7 +36,7 @@ public class NaturalLoopSet {
@Override
public String toString() {
StringBuilder out = new StringBuilder();
- for (NaturalLoop loop : loops) {
+ for(NaturalLoop loop : loops) {
out.append(loop.toString());
out.append("\n");
}
@@ -43,11 +45,12 @@ public class NaturalLoopSet {
/**
* Get all blocks that are heads of a loop
+ *
* @return The labels for all blocks that are head of a loop.
*/
public Set getLoopHeads() {
LinkedHashSet heads = new LinkedHashSet<>();
- for (NaturalLoop loop : loops) {
+ for(NaturalLoop loop : loops) {
heads.add(loop.getHead());
}
return heads;
@@ -55,12 +58,13 @@ public class NaturalLoopSet {
/**
* Get all loops with a given loop head
+ *
* @param loopHead The loop head
* @return Set with all loops that have the given head
*/
public Set getLoopsFromHead(LabelRef loopHead) {
LinkedHashSet result = new LinkedHashSet<>();
- for (NaturalLoop loop : loops) {
+ for(NaturalLoop loop : loops) {
if(loopHead.equals(loop.getHead())) {
result.add(loop);
}
@@ -76,8 +80,8 @@ public class NaturalLoopSet {
*/
public Collection getLoopsContainingBlock(LabelRef block) {
ArrayList containing = new ArrayList<>();
- for (NaturalLoop loop : loops) {
- for (LabelRef loopBlock : loop.getBlocks()) {
+ for(NaturalLoop loop : loops) {
+ for(LabelRef loopBlock : loop.getBlocks()) {
if(block.equals(loopBlock)) {
containing.add(loop);
break;
@@ -90,6 +94,7 @@ public class NaturalLoopSet {
/**
* Remove a loop from the set
+ *
* @param loop The loop to remove
*/
public void remove(NaturalLoop loop) {
@@ -98,8 +103,8 @@ public class NaturalLoopSet {
public int getMaxLoopDepth(LabelRef block) {
int maxDepth = 0;
- for (NaturalLoop loop : getLoopsContainingBlock(block)) {
- if(loop.getDepth()>maxDepth) {
+ for(NaturalLoop loop : getLoopsContainingBlock(block)) {
+ if(loop.getDepth() > maxDepth) {
maxDepth = loop.getDepth();
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/Operator.java b/src/main/java/dk/camelot64/kickc/model/Operator.java
index 1ab1646e8..188a0a406 100644
--- a/src/main/java/dk/camelot64/kickc/model/Operator.java
+++ b/src/main/java/dk/camelot64/kickc/model/Operator.java
@@ -5,14 +5,45 @@ package dk.camelot64.kickc.model;
*/
public class Operator {
+ public static final Operator INCREMENT = new Operator("++", "_inc_", Type.UNARY, 1);
+ public static final Operator DECREMENT = new Operator("--", "_dec_", Type.UNARY, 1);
+ public static final Operator POS = new Operator("+", "_pos_", Type.UNARY, 2);
+ public static final Operator NEG = new Operator("-", "_neg_", Type.UNARY, 2);
+ public static final Operator BOOL_NOT = new Operator("~", "_not_", Type.UNARY, 2);
+ public static final Operator NOT = new Operator("!", "_not_", Type.UNARY, 2);
+ public static final Operator DEREF = new Operator("*", "_deref_", Type.UNARY, 2);
+ public static final Operator WORD = new Operator("w=", "_word_", Type.BINARY, 2);
+ public static final Operator DEREF_IDX = new Operator("*idx", "_derefidx_", Type.BINARY, 2);
+ public static final Operator SET_LOWBYTE = new Operator("lo=", "_setlo_", Type.BINARY, 2);
+ public static final Operator SET_HIBYTE = new Operator("hi=", "_sethi_", Type.BINARY, 2);
+ public static final Operator CAST_BYTE = new Operator("((byte))", "_byte_", Type.UNARY, 2);
+ public static final Operator CAST_SBYTE = new Operator("((signed byte))", "_sbyte_", Type.UNARY, 2);
+ public static final Operator CAST_WORD = new Operator("((word))", "_word_", Type.UNARY, 2);
+ public static final Operator CAST_SWORD = new Operator("((signed word))", "_sword_", Type.UNARY, 2);
+ public static final Operator CAST_PTRBY = new Operator("((byte*))", "_ptrby_", Type.UNARY, 2);
+ public static final Operator MULTIPLY = new Operator("*", "_mul_", Type.BINARY, 3);
+ public static final Operator DIVIDE = new Operator("/", "_div_", Type.BINARY, 3);
+ public static final Operator PLUS = new Operator("+", "_plus_", Type.BINARY, 4);
+ public static final Operator MINUS = new Operator("-", "_minus_", Type.BINARY, 4);
+ public static final Operator SHIFT_LEFT = new Operator("<<", "_rol_", Type.BINARY, 5);
+ public static final Operator SHIFT_RIGHT = new Operator(">>", "_ror_", Type.BINARY, 5);
+ public static final Operator LOWBYTE = new Operator("<", "_lo_", Type.UNARY, 6);
+ public static final Operator HIBYTE = new Operator(">", "_hi_", Type.UNARY, 6);
+ public static final Operator LT = new Operator("<", "_lt_", Type.BINARY, 7);
+ public static final Operator LE = new Operator("<=", "_le_", Type.BINARY, 7);
+ public static final Operator GT = new Operator(">", "_gt_", Type.BINARY, 7);
+ public static final Operator GE = new Operator(">=", "_ge_", Type.BINARY, 7);
+ public static final Operator EQ = new Operator("==", "_eq_", Type.BINARY, 8);
+ public static final Operator NEQ = new Operator("!=", "_neq_", Type.BINARY, 8);
+ public static final Operator BOOL_AND = new Operator("&", "_band_", Type.BINARY, 9);
+ public static final Operator BOOL_XOR = new Operator("^", "_bxor_", Type.BINARY, 10);
+ public static final Operator BOOL_OR = new Operator("|", "_bor_", Type.BINARY, 11);
+ public static final Operator LOGIC_AND = new Operator("&&", "_and_", Type.BINARY, 12);
+ public static final Operator LOGIC_OR = new Operator("||", "_or_", Type.BINARY, 13);
private String operator;
-
private int precedence;
-
private Type type;
-
private String asmOperator;
-
public Operator(String operator, String asmOperator, Type type, int precedence) {
this.operator = operator;
this.precedence = precedence;
@@ -21,7 +52,7 @@ public class Operator {
}
public static Operator getBinary(String op) {
- switch (op) {
+ switch(op) {
case "+":
return PLUS;
case "-":
@@ -68,7 +99,7 @@ public class Operator {
}
public static Operator getUnary(String op) {
- switch (op) {
+ switch(op) {
case "+":
return POS;
case "-":
@@ -93,15 +124,15 @@ public class Operator {
}
public static Operator getCastUnary(SymbolType castType) {
- if (SymbolType.BYTE.equals(castType)) {
+ if(SymbolType.BYTE.equals(castType)) {
return CAST_BYTE;
- } else if (SymbolType.SBYTE.equals(castType)) {
+ } else if(SymbolType.SBYTE.equals(castType)) {
return CAST_SBYTE;
- } else if (SymbolType.WORD.equals(castType)) {
+ } else if(SymbolType.WORD.equals(castType)) {
return CAST_WORD;
- } else if (SymbolType.SWORD.equals(castType)) {
+ } else if(SymbolType.SWORD.equals(castType)) {
return CAST_SWORD;
- } else if (castType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) castType).getElementType())) {
+ } else if(castType instanceof SymbolTypePointer && SymbolType.BYTE.equals(((SymbolTypePointer) castType).getElementType())) {
return CAST_PTRBY;
} else {
throw new RuntimeException("Unknown cast type " + castType);
@@ -109,46 +140,6 @@ public class Operator {
}
}
- public enum Type {
- UNARY, BINARY
- }
-
- public static final Operator INCREMENT = new Operator("++", "_inc_", Type.UNARY, 1);
- public static final Operator DECREMENT = new Operator("--", "_dec_", Type.UNARY, 1);
- public static final Operator POS = new Operator("+", "_pos_", Type.UNARY, 2);
- public static final Operator NEG = new Operator("-", "_neg_", Type.UNARY, 2);
- public static final Operator BOOL_NOT = new Operator("~", "_not_", Type.UNARY, 2);
- public static final Operator NOT = new Operator("!", "_not_", Type.UNARY, 2);
- public static final Operator DEREF = new Operator("*", "_deref_", Type.UNARY, 2);
- public static final Operator WORD = new Operator("w=", "_word_", Type.BINARY, 2);
- public static final Operator DEREF_IDX = new Operator("*idx", "_derefidx_", Type.BINARY, 2);
- public static final Operator SET_LOWBYTE = new Operator("lo=", "_setlo_", Type.BINARY, 2);
- public static final Operator SET_HIBYTE = new Operator("hi=", "_sethi_", Type.BINARY, 2);
- public static final Operator CAST_BYTE = new Operator("((byte))", "_byte_", Type.UNARY, 2);
- public static final Operator CAST_SBYTE = new Operator("((signed byte))", "_sbyte_", Type.UNARY, 2);
- public static final Operator CAST_WORD = new Operator("((word))", "_word_", Type.UNARY, 2);
- public static final Operator CAST_SWORD = new Operator("((signed word))", "_sword_", Type.UNARY, 2);
- public static final Operator CAST_PTRBY = new Operator("((byte*))", "_ptrby_", Type.UNARY, 2);
- public static final Operator MULTIPLY = new Operator("*", "_mul_", Type.BINARY, 3);
- public static final Operator DIVIDE = new Operator("/", "_div_", Type.BINARY, 3);
- public static final Operator PLUS = new Operator("+", "_plus_", Type.BINARY, 4);
- public static final Operator MINUS = new Operator("-", "_minus_", Type.BINARY, 4);
- public static final Operator SHIFT_LEFT = new Operator("<<", "_rol_", Type.BINARY, 5);
- public static final Operator SHIFT_RIGHT = new Operator(">>", "_ror_", Type.BINARY, 5);
- public static final Operator LOWBYTE = new Operator("<", "_lo_", Type.UNARY, 6);
- public static final Operator HIBYTE = new Operator(">", "_hi_", Type.UNARY, 6);
- public static final Operator LT = new Operator("<", "_lt_", Type.BINARY, 7);
- public static final Operator LE = new Operator("<=", "_le_", Type.BINARY, 7);
- public static final Operator GT = new Operator(">", "_gt_", Type.BINARY, 7);
- public static final Operator GE = new Operator(">=", "_ge_", Type.BINARY, 7);
- public static final Operator EQ = new Operator("==", "_eq_", Type.BINARY, 8);
- public static final Operator NEQ = new Operator("!=", "_neq_", Type.BINARY, 8);
- public static final Operator BOOL_AND = new Operator("&", "_band_", Type.BINARY, 9);
- public static final Operator BOOL_XOR = new Operator("^", "_bxor_", Type.BINARY, 10);
- public static final Operator BOOL_OR = new Operator("|", "_bor_", Type.BINARY, 11);
- public static final Operator LOGIC_AND = new Operator("&&", "_and_", Type.BINARY, 12);
- public static final Operator LOGIC_OR = new Operator("||", "_or_", Type.BINARY, 13);
-
public String getOperator() {
return operator;
}
@@ -172,11 +163,11 @@ public class Operator {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
Operator operator1 = (Operator) o;
- if (precedence != operator1.precedence) return false;
- if (!operator.equals(operator1.operator)) return false;
+ if(precedence != operator1.precedence) return false;
+ if(!operator.equals(operator1.operator)) return false;
return type == operator1.type;
}
@@ -188,4 +179,8 @@ public class Operator {
return result;
}
+ public enum Type {
+ UNARY, BINARY
+ }
+
}
diff --git a/src/main/java/dk/camelot64/kickc/model/PhiTransitions.java b/src/main/java/dk/camelot64/kickc/model/PhiTransitions.java
index b6c447fe8..58446e8cc 100644
--- a/src/main/java/dk/camelot64/kickc/model/PhiTransitions.java
+++ b/src/main/java/dk/camelot64/kickc/model/PhiTransitions.java
@@ -25,7 +25,7 @@ public class PhiTransitions {
this.program = program;
this.toBlock = toBlock;
this.transitions = new LinkedHashMap<>();
- if (toBlock.hasPhiBlock()) {
+ if(toBlock.hasPhiBlock()) {
this.phiBlock = toBlock.getPhiBlock();
List predecessors = new ArrayList<>(program.getGraph().getPredecessors(toBlock));
Collections.sort(predecessors, new Comparator() {
@@ -34,7 +34,7 @@ public class PhiTransitions {
return o1.getLabel().getFullName().compareTo(o2.getLabel().getFullName());
}
});
- for (ControlFlowBlock predecessor : predecessors) {
+ for(ControlFlowBlock predecessor : predecessors) {
PhiTransition transition = findTransition(predecessor);
transitions.put(predecessor, transition);
}
@@ -51,10 +51,10 @@ public class PhiTransitions {
private PhiTransition findTransition(ControlFlowBlock fromBlock) {
PhiTransition transition = new PhiTransition(fromBlock);
boolean isCallTransition = toBlock.getLabel().equals(fromBlock.getCallSuccessor());
- if (!isCallTransition) {
+ if(!isCallTransition) {
// If the transition is not a call - then attempt to join with other equal transition(s)
- for (PhiTransition candidate : transitions.values()) {
- if (candidate.equalAssignments(transition)) {
+ for(PhiTransition candidate : transitions.values()) {
+ if(candidate.equalAssignments(transition)) {
candidate.addFromBlock(fromBlock);
return candidate;
}
@@ -80,11 +80,12 @@ public class PhiTransitions {
/**
* Get a phi transition from it's phi transition ID.
+ *
* @param transitionId The ID to look for
* @return The transition with the given ID, or nulll if not found.
*/
public PhiTransition getTransition(String transitionId) {
- for (PhiTransition phiTransition : transitions.values()) {
+ for(PhiTransition phiTransition : transitions.values()) {
if(transitionId.equals(phiTransition.getTransitionId())) {
return phiTransition;
}
@@ -117,10 +118,10 @@ public class PhiTransitions {
private void initAssignments(ControlFlowBlock fromBlock) {
this.assignments = new ArrayList<>();
- if (phiBlock != null) {
+ if(phiBlock != null) {
List phiVariables = new ArrayList<>(phiBlock.getPhiVariables());
Collections.reverse(phiVariables);
- for (StatementPhiBlock.PhiVariable phiVariable : phiVariables) {
+ for(StatementPhiBlock.PhiVariable phiVariable : phiVariables) {
List phiRValues = new ArrayList<>(phiVariable.getValues());
Collections.sort(phiRValues, new Comparator() {
@Override
@@ -128,8 +129,8 @@ public class PhiTransitions {
return o1.getPredecessor().getFullName().compareTo(o2.getPredecessor().getFullName());
}
});
- for (StatementPhiBlock.PhiRValue phiRValue : phiRValues) {
- if (phiRValue.getPredecessor().equals(fromBlock.getLabel())) {
+ for(StatementPhiBlock.PhiRValue phiRValue : phiRValues) {
+ if(phiRValue.getPredecessor().equals(fromBlock.getLabel())) {
this.assignments.add(new PhiTransition.PhiAssignment(phiVariable, phiRValue, nextIdx++));
}
}
@@ -139,13 +140,14 @@ public class PhiTransitions {
/**
* Get a string ID uniquely identifying the PHI transition within the program
+ *
* @return Transition ID
*/
public String getTransitionId() {
StringBuilder id = new StringBuilder();
id.append("phi:");
boolean first = true;
- for (ControlFlowBlock fromBlock : fromBlocks) {
+ for(ControlFlowBlock fromBlock : fromBlocks) {
if(!first) {
id.append("/");
}
@@ -180,28 +182,28 @@ public class PhiTransitions {
*/
public boolean equalAssignments(PhiTransition other) {
List otherAssignments = other.getAssignments();
- if (assignments.size() != otherAssignments.size()) {
+ if(assignments.size() != otherAssignments.size()) {
return false;
}
- for (int i = 0; i < assignments.size(); i++) {
+ for(int i = 0; i < assignments.size(); i++) {
PhiTransition.PhiAssignment assignment = assignments.get(i);
PhiTransition.PhiAssignment otherAssignment = otherAssignments.get(i);
- if (assignment.getVariable() != null && otherAssignment.getVariable() != null) {
+ if(assignment.getVariable() != null && otherAssignment.getVariable() != null) {
Variable var = program.getSymbolInfos().getVariable(assignment.getVariable());
Variable otherVar = program.getSymbolInfos().getVariable(otherAssignment.getVariable());
- if (!var.getAllocation().equals(otherVar.getAllocation())) {
+ if(!var.getAllocation().equals(otherVar.getAllocation())) {
return false;
}
- } else if (!assignment.getVariable().equals(otherAssignment.getVariable())) {
+ } else if(!assignment.getVariable().equals(otherAssignment.getVariable())) {
return false;
}
- if (assignment.getrValue() instanceof VariableRef && otherAssignment.getrValue() instanceof VariableRef) {
+ if(assignment.getrValue() instanceof VariableRef && otherAssignment.getrValue() instanceof VariableRef) {
Variable var = program.getSymbolInfos().getVariable((VariableRef) assignment.getrValue());
Variable otherVar = program.getSymbolInfos().getVariable((VariableRef) otherAssignment.getrValue());
- if (!var.getAllocation().equals(otherVar.getAllocation())) {
+ if(!var.getAllocation().equals(otherVar.getAllocation())) {
return false;
}
- } else if (!assignment.getrValue().equals(otherAssignment.getrValue())) {
+ } else if(!assignment.getrValue().equals(otherAssignment.getrValue())) {
return false;
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/PointerDereferenceIndexed.java b/src/main/java/dk/camelot64/kickc/model/PointerDereferenceIndexed.java
index caded679f..967782625 100644
--- a/src/main/java/dk/camelot64/kickc/model/PointerDereferenceIndexed.java
+++ b/src/main/java/dk/camelot64/kickc/model/PointerDereferenceIndexed.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.model;
-/** A dereferenced variable pointer plus an index (used for array writes)*/
+/** A dereferenced variable pointer plus an index (used for array writes) */
public class PointerDereferenceIndexed implements PointerDereference {
private RValue pointer;
@@ -35,7 +35,7 @@ public class PointerDereferenceIndexed implements PointerDereference {
@Override
public String toString(Program program) {
- return "*(" + pointer.toString(program) + " + " +index.toString(program) + ')';
+ return "*(" + pointer.toString(program) + " + " + index.toString(program) + ')';
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/PointerDereferenceSimple.java b/src/main/java/dk/camelot64/kickc/model/PointerDereferenceSimple.java
index 5acfa6bee..9f22bb9f8 100644
--- a/src/main/java/dk/camelot64/kickc/model/PointerDereferenceSimple.java
+++ b/src/main/java/dk/camelot64/kickc/model/PointerDereferenceSimple.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.model;
-/** A dereferenced pointer (based on a variable or a constant pointer)*/
+/** A dereferenced pointer (based on a variable or a constant pointer) */
public class PointerDereferenceSimple implements PointerDereference {
private RValue pointer;
diff --git a/src/main/java/dk/camelot64/kickc/model/Procedure.java b/src/main/java/dk/camelot64/kickc/model/Procedure.java
index 033669eb8..914fb5faa 100644
--- a/src/main/java/dk/camelot64/kickc/model/Procedure.java
+++ b/src/main/java/dk/camelot64/kickc/model/Procedure.java
@@ -11,11 +11,10 @@ import java.util.List;
/** Symbol describing a procedure/function */
public class Procedure extends Scope {
+ public static final ProcedureRef ROOT = new ProcedureRef("");
private final SymbolType returnType;
private List parameterNames;
- public static final ProcedureRef ROOT = new ProcedureRef("");
-
public Procedure(String name, SymbolType returnType, Scope parentScope) {
super(name, parentScope);
this.returnType = returnType;
@@ -42,14 +41,6 @@ public class Procedure extends Scope {
this.parameterNames = parameterNames;
}
- public void setParameters(List parameters) {
- this.parameterNames = new ArrayList<>();
- for (Variable parameter : parameters) {
- add(parameter);
- parameterNames.add(parameter.getLocalName());
- }
- }
-
@JsonIgnore
public Label getLabel() {
return new Label(getFullName(), getScope(), false);
@@ -62,12 +53,20 @@ public class Procedure extends Scope {
@JsonIgnore
public List getParameters() {
ArrayList parameters = new ArrayList<>();
- for (String name : parameterNames) {
+ for(String name : parameterNames) {
parameters.add(this.getVariable(name));
}
return parameters;
}
+ public void setParameters(List parameters) {
+ this.parameterNames = new ArrayList<>();
+ for(Variable parameter : parameters) {
+ add(parameter);
+ parameterNames.add(parameter.getLocalName());
+ }
+ }
+
@Override
public String getFullName() {
return super.getFullName();
@@ -94,13 +93,13 @@ public class Procedure extends Scope {
@Override
public String toString(Program program) {
StringBuilder res = new StringBuilder();
- res.append("("+getType().getTypeName() + ") ");
+ res.append("(" + getType().getTypeName() + ") ");
res.append(getFullName());
res.append("(");
boolean first = true;
- if(parameterNames !=null) {
- for (Variable parameter : getParameters()) {
- if (!first) res.append(" , ");
+ if(parameterNames != null) {
+ for(Variable parameter : getParameters()) {
+ if(!first) res.append(" , ");
first = false;
res.append(parameter.toString(program));
}
@@ -116,13 +115,13 @@ public class Procedure extends Scope {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- if (!super.equals(o)) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+ if(!super.equals(o)) return false;
Procedure procedure = (Procedure) o;
- if (returnType != null ? !returnType.equals(procedure.returnType) : procedure.returnType != null) return false;
+ if(returnType != null ? !returnType.equals(procedure.returnType) : procedure.returnType != null) return false;
return parameterNames != null ? parameterNames.equals(procedure.parameterNames) : procedure.parameterNames == null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ProcedureModifiedVars.java b/src/main/java/dk/camelot64/kickc/model/ProcedureModifiedVars.java
index c053a3a08..1370d0820 100644
--- a/src/main/java/dk/camelot64/kickc/model/ProcedureModifiedVars.java
+++ b/src/main/java/dk/camelot64/kickc/model/ProcedureModifiedVars.java
@@ -1,6 +1,7 @@
package dk.camelot64.kickc.model;
-import java.util.*;
+import java.util.Map;
+import java.util.Set;
/**
* Contains all variables modified inside procedures. Contain the unversioned VariableRefs.
@@ -20,9 +21,9 @@ public class ProcedureModifiedVars {
public String toString(Program program) {
StringBuilder out = new StringBuilder();
- for (ProcedureRef procedureRef : modified.keySet()) {
- for (VariableRef variableRef : getModifiedVars(procedureRef)) {
- out.append(procedureRef.getFullName()).append(" modifies "+variableRef.getFullName()).append("\n");
+ for(ProcedureRef procedureRef : modified.keySet()) {
+ for(VariableRef variableRef : getModifiedVars(procedureRef)) {
+ out.append(procedureRef.getFullName()).append(" modifies " + variableRef.getFullName()).append("\n");
}
}
return out.toString();
diff --git a/src/main/java/dk/camelot64/kickc/model/ProcedureRef.java b/src/main/java/dk/camelot64/kickc/model/ProcedureRef.java
index 4b8350dba..a402695bc 100644
--- a/src/main/java/dk/camelot64/kickc/model/ProcedureRef.java
+++ b/src/main/java/dk/camelot64/kickc/model/ProcedureRef.java
@@ -8,12 +8,13 @@ import com.fasterxml.jackson.annotation.JsonProperty;
public class ProcedureRef extends ScopeRef {
@JsonCreator
- public ProcedureRef( @JsonProperty("fullName") String fullName) {
+ public ProcedureRef(@JsonProperty("fullName") String fullName) {
super(fullName);
}
/**
* Get the label of the block where the procedure code starts
+ *
* @return The label of the code block
*/
@JsonIgnore
@@ -23,10 +24,11 @@ public class ProcedureRef extends ScopeRef {
/**
* Get the label of the block containing the final procedure return
+ *
* @return The label of the code block
*/
@JsonIgnore
public LabelRef getReturnBlock() {
- return new LabelRef(getFullName()+"::"+SymbolRef.PROCEXIT_BLOCK_NAME);
+ return new LabelRef(getFullName() + "::" + SymbolRef.PROCEXIT_BLOCK_NAME);
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/Program.java b/src/main/java/dk/camelot64/kickc/model/Program.java
index 6469f084d..f2e191d53 100644
--- a/src/main/java/dk/camelot64/kickc/model/Program.java
+++ b/src/main/java/dk/camelot64/kickc/model/Program.java
@@ -29,14 +29,14 @@ public class Program {
private ProcedureModifiedVars procedureModifiedVars;
/** Information about calls. */
private CallGraph callGraph;
- /** Information about dominators of all blocks*/
+ /** Information about dominators of all blocks */
private DominatorsGraph dominators;
/** Information about loops. */
private NaturalLoopSet loopSet;
/** Which block is each statement a part of. */
private StatementInfos statementInfos;
- /** Cached information about symbols. Contains a symbol table cache for fast access.*/
+ /** Cached information about symbols. Contains a symbol table cache for fast access. */
private SymbolInfos symbolInfos;
/** The variables referenced by blocks/statements. */
private VariableReferenceInfos variableReferenceInfos;
@@ -92,14 +92,14 @@ public class Program {
this.graph = graph;
}
- public void setProcedureModifiedVars(ProcedureModifiedVars procedureModifiedVars) {
- this.procedureModifiedVars = procedureModifiedVars;
- }
-
public ProcedureModifiedVars getProcedureModifiedVars() {
return procedureModifiedVars;
}
+ public void setProcedureModifiedVars(ProcedureModifiedVars procedureModifiedVars) {
+ this.procedureModifiedVars = procedureModifiedVars;
+ }
+
public AsmProgram getAsm() {
return asm;
}
@@ -116,22 +116,22 @@ public class Program {
this.callGraph = callGraph;
}
- public void setDominators(DominatorsGraph dominators) {
- this.dominators = dominators;
- }
-
public DominatorsGraph getDominators() {
return dominators;
}
- public void setLoopSet(NaturalLoopSet loopSet) {
- this.loopSet = loopSet;
+ public void setDominators(DominatorsGraph dominators) {
+ this.dominators = dominators;
}
public NaturalLoopSet getLoopSet() {
return loopSet;
}
+ public void setLoopSet(NaturalLoopSet loopSet) {
+ this.loopSet = loopSet;
+ }
+
public VariableReferenceInfos getVariableReferenceInfos() {
return variableReferenceInfos;
}
@@ -156,14 +156,14 @@ public class Program {
this.symbolInfos = symbolInfos;
}
- public void setLiveRangeVariables(LiveRangeVariables liveRangeVariables) {
- this.liveRangeVariables = liveRangeVariables;
- }
-
public LiveRangeVariables getLiveRangeVariables() {
return liveRangeVariables;
}
+ public void setLiveRangeVariables(LiveRangeVariables liveRangeVariables) {
+ this.liveRangeVariables = liveRangeVariables;
+ }
+
public LiveRangeVariablesEffective getLiveRangeVariablesEffective() {
return liveRangeVariablesEffective;
}
@@ -172,38 +172,38 @@ public class Program {
this.liveRangeVariablesEffective = liveRangeVariablesEffective;
}
- public void setLiveRangeEquivalenceClassSet(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
- this.liveRangeEquivalenceClassSet = liveRangeEquivalenceClassSet;
- }
-
public LiveRangeEquivalenceClassSet getLiveRangeEquivalenceClassSet() {
return liveRangeEquivalenceClassSet;
}
- public void setVariableRegisterWeights(VariableRegisterWeights variableRegisterWeights) {
- this.variableRegisterWeights = variableRegisterWeights;
+ public void setLiveRangeEquivalenceClassSet(LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet) {
+ this.liveRangeEquivalenceClassSet = liveRangeEquivalenceClassSet;
}
public VariableRegisterWeights getVariableRegisterWeights() {
return variableRegisterWeights;
}
- public void setRegisterPotentials(RegisterPotentials registerPotentials) {
- this.registerPotentials = registerPotentials;
+ public void setVariableRegisterWeights(VariableRegisterWeights variableRegisterWeights) {
+ this.variableRegisterWeights = variableRegisterWeights;
}
public RegisterPotentials getRegisterPotentials() {
return registerPotentials;
}
- public void setRegisterUpliftProgram(RegisterUpliftProgram registerUpliftProgram) {
- this.registerUpliftProgram = registerUpliftProgram;
+ public void setRegisterPotentials(RegisterPotentials registerPotentials) {
+ this.registerPotentials = registerPotentials;
}
public RegisterUpliftProgram getRegisterUpliftProgram() {
return registerUpliftProgram;
}
+ public void setRegisterUpliftProgram(RegisterUpliftProgram registerUpliftProgram) {
+ this.registerUpliftProgram = registerUpliftProgram;
+ }
+
public CompileLog getLog() {
return log;
}
@@ -215,13 +215,13 @@ public class Program {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
Program program = (Program) o;
- if (scope != null ? !scope.equals(program.scope) : program.scope != null) return false;
- if (graph != null ? !graph.equals(program.graph) : program.graph != null) return false;
+ if(scope != null ? !scope.equals(program.scope) : program.scope != null) return false;
+ if(graph != null ? !graph.equals(program.graph) : program.graph != null) return false;
return asm != null ? asm.equals(program.asm) : program.asm == null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ProgramScope.java b/src/main/java/dk/camelot64/kickc/model/ProgramScope.java
index 4572b8c25..a2c7234bb 100644
--- a/src/main/java/dk/camelot64/kickc/model/ProgramScope.java
+++ b/src/main/java/dk/camelot64/kickc/model/ProgramScope.java
@@ -38,9 +38,9 @@ public class ProgramScope extends Scope {
LiveRangeEquivalenceClassSet liveRangeEquivalenceClassSet = program.getLiveRangeEquivalenceClassSet();
StringBuilder out = new StringBuilder();
out.append(super.toString(program, symbolClass));
- if(liveRangeEquivalenceClassSet!=null) {
+ if(liveRangeEquivalenceClassSet != null) {
out.append("\n");
- for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
+ for(LiveRangeEquivalenceClass liveRangeEquivalenceClass : liveRangeEquivalenceClassSet.getEquivalenceClasses()) {
out.append(liveRangeEquivalenceClass);
out.append("\n");
}
diff --git a/src/main/java/dk/camelot64/kickc/model/RValue.java b/src/main/java/dk/camelot64/kickc/model/RValue.java
index e34477b7c..81f9d8481 100644
--- a/src/main/java/dk/camelot64/kickc/model/RValue.java
+++ b/src/main/java/dk/camelot64/kickc/model/RValue.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.model;
-/** A value usable as part of a calculation (ib the right side of an assignment)*/
+/** A value usable as part of a calculation (ib the right side of an assignment) */
public interface RValue extends Value {
}
diff --git a/src/main/java/dk/camelot64/kickc/model/RegisterCombination.java b/src/main/java/dk/camelot64/kickc/model/RegisterCombination.java
index 543b976e1..dfb63713c 100644
--- a/src/main/java/dk/camelot64/kickc/model/RegisterCombination.java
+++ b/src/main/java/dk/camelot64/kickc/model/RegisterCombination.java
@@ -3,7 +3,7 @@ package dk.camelot64.kickc.model;
import java.util.LinkedHashMap;
import java.util.Map;
-/** A combination of register/ZP assignments for a set of equivalence classes */
+/** A combination of register/ZP assignments for a set of equivalence classes */
public class RegisterCombination {
/** The registers allocated to each equivalence class. */
@@ -26,9 +26,9 @@ public class RegisterCombination {
* (does not update the allocation in the equivalence classes).
*/
public void allocate(Program program) {
- for (LiveRangeEquivalenceClass equivalenceClass : allocation.keySet()) {
+ for(LiveRangeEquivalenceClass equivalenceClass : allocation.keySet()) {
Registers.Register register = allocation.get(equivalenceClass);
- for (VariableRef variable : equivalenceClass.getVariables()) {
+ for(VariableRef variable : equivalenceClass.getVariables()) {
Variable var = program.getSymbolInfos().getVariable(variable);
var.setAllocation(register);
}
@@ -39,7 +39,7 @@ public class RegisterCombination {
* Store the combination in the equivalence classes.
*/
public void store(LiveRangeEquivalenceClassSet equivalenceClassSet) {
- for (LiveRangeEquivalenceClass equivalenceClass : allocation.keySet()) {
+ for(LiveRangeEquivalenceClass equivalenceClass : allocation.keySet()) {
VariableRef variable = equivalenceClass.getVariables().get(0);
LiveRangeEquivalenceClass globalEquivalenceClass = equivalenceClassSet.getEquivalenceClass(variable);
Registers.Register register = allocation.get(equivalenceClass);
@@ -50,7 +50,7 @@ public class RegisterCombination {
@Override
public String toString() {
StringBuilder out = new StringBuilder();
- for (LiveRangeEquivalenceClass equivalenceClass : allocation.keySet()) {
+ for(LiveRangeEquivalenceClass equivalenceClass : allocation.keySet()) {
Registers.Register register = allocation.get(equivalenceClass);
out.append(register.toString()).append(" ").append(equivalenceClass.toString(false)).append(" ");
}
diff --git a/src/main/java/dk/camelot64/kickc/model/RegisterCombinationIterator.java b/src/main/java/dk/camelot64/kickc/model/RegisterCombinationIterator.java
index 5cf84bc6f..d3d3e9b68 100644
--- a/src/main/java/dk/camelot64/kickc/model/RegisterCombinationIterator.java
+++ b/src/main/java/dk/camelot64/kickc/model/RegisterCombinationIterator.java
@@ -30,7 +30,7 @@ public class RegisterCombinationIterator implements Iterator registers = registerPotentials.getPotentialRegisters(equivalenceClass);
numIterations = numIterations * registers.size();
}
@@ -41,7 +41,7 @@ public class RegisterCombinationIterator implements Iterator potentials = registerPotentials.getPotentialRegisters(equivalenceClass);
int registerIdx = (combinationIdRest % potentials.size());
Registers.Register register = potentials.get(registerIdx);
diff --git a/src/main/java/dk/camelot64/kickc/model/RegisterPotentials.java b/src/main/java/dk/camelot64/kickc/model/RegisterPotentials.java
index 0bf27b661..d607e5dda 100644
--- a/src/main/java/dk/camelot64/kickc/model/RegisterPotentials.java
+++ b/src/main/java/dk/camelot64/kickc/model/RegisterPotentials.java
@@ -33,12 +33,12 @@ public class RegisterPotentials {
@Override
public String toString() {
StringBuilder out = new StringBuilder();
- for (LiveRangeEquivalenceClass liveRangeEquivalenceClass : potentials.keySet()) {
+ for(LiveRangeEquivalenceClass liveRangeEquivalenceClass : potentials.keySet()) {
out.append("Potential registers ");
out.append(liveRangeEquivalenceClass.toString());
out.append(" : ");
List registers = potentials.get(liveRangeEquivalenceClass);
- for (Registers.Register register : registers) {
+ for(Registers.Register register : registers) {
out.append(register.toString());
out.append(" , ");
}
@@ -49,11 +49,11 @@ public class RegisterPotentials {
public void addPotentialRegister(LiveRangeEquivalenceClass equivalenceClass, Registers.Register register) {
List registers = potentials.get(equivalenceClass);
- if(registers==null) {
- registers= new ArrayList<>();
+ if(registers == null) {
+ registers = new ArrayList<>();
potentials.put(equivalenceClass, registers);
}
- if (!registers.contains(register)) {
+ if(!registers.contains(register)) {
registers.add(register);
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/RegisterUpliftProgram.java b/src/main/java/dk/camelot64/kickc/model/RegisterUpliftProgram.java
index bca41314c..cfe3ceaf5 100644
--- a/src/main/java/dk/camelot64/kickc/model/RegisterUpliftProgram.java
+++ b/src/main/java/dk/camelot64/kickc/model/RegisterUpliftProgram.java
@@ -30,7 +30,7 @@ public class RegisterUpliftProgram {
public String toString(VariableRegisterWeights variableRegisterWeights) {
StringBuilder out = new StringBuilder();
- for (RegisterUpliftScope upliftScope : registerUpliftScopes) {
+ for(RegisterUpliftScope upliftScope : registerUpliftScopes) {
out.append(upliftScope.toString(variableRegisterWeights)).append("\n");
}
return out.toString();
diff --git a/src/main/java/dk/camelot64/kickc/model/RegisterUpliftScope.java b/src/main/java/dk/camelot64/kickc/model/RegisterUpliftScope.java
index 2f798a4a4..fcbe6c638 100644
--- a/src/main/java/dk/camelot64/kickc/model/RegisterUpliftScope.java
+++ b/src/main/java/dk/camelot64/kickc/model/RegisterUpliftScope.java
@@ -2,7 +2,10 @@ package dk.camelot64.kickc.model;
import com.ibm.icu.text.NumberFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
/** Register Uplift information for a single scope. */
public class RegisterUpliftScope {
@@ -20,10 +23,6 @@ public class RegisterUpliftScope {
this.equivalenceClasses = new ArrayList<>();
}
- public void setEquivalenceClasses(List equivalenceClasses) {
- this.equivalenceClasses = equivalenceClasses;
- }
-
public ScopeRef getScopeRef() {
return scopeRef;
}
@@ -32,11 +31,15 @@ public class RegisterUpliftScope {
return equivalenceClasses;
}
+ public void setEquivalenceClasses(List equivalenceClasses) {
+ this.equivalenceClasses = equivalenceClasses;
+ }
+
public String toString(VariableRegisterWeights weights) {
StringBuilder out = new StringBuilder();
out.append("Uplift Scope [" + scopeRef.toString() + "] ");
- for (LiveRangeEquivalenceClass equivalenceClass : equivalenceClasses) {
- if (weights != null) {
+ for(LiveRangeEquivalenceClass equivalenceClass : equivalenceClasses) {
+ if(weights != null) {
NumberFormat fmt = NumberFormat.getInstance(Locale.ENGLISH);
fmt.setMaximumFractionDigits(2);
out.append(fmt.format(weights.getTotalWeight(equivalenceClass)) + ": ");
@@ -53,6 +56,7 @@ public class RegisterUpliftScope {
/**
* Get all register allocation combinations using the passed potential registers
+ *
* @param registerPotentials The potential registers to use for each live range equivalence class
* @return Iterator of all combinations
*/
diff --git a/src/main/java/dk/camelot64/kickc/model/Registers.java b/src/main/java/dk/camelot64/kickc/model/Registers.java
index 202e88c0c..670ad439d 100644
--- a/src/main/java/dk/camelot64/kickc/model/Registers.java
+++ b/src/main/java/dk/camelot64/kickc/model/Registers.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.model;
-/** The different registers available for a program */
+/** The different registers available for a program */
public class Registers {
@@ -71,10 +71,10 @@ public class Registers {
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
@@ -150,10 +150,10 @@ public class Registers {
@Override
public boolean equals(Object obj) {
- if (this == obj) {
+ if(this == obj) {
return true;
}
- if (obj == null || getClass() != obj.getClass()) {
+ if(obj == null || getClass() != obj.getClass()) {
return false;
}
return true;
@@ -253,7 +253,7 @@ public class Registers {
@Override
public String toString(Program program) {
- return "const "+constantValue.toString(program);
+ return "const " + constantValue.toString(program);
}
@Override
@@ -263,8 +263,8 @@ public class Registers {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
RegisterConstant that = (RegisterConstant) o;
return constantValue != null ? constantValue.equals(that.constantValue) : that.constantValue == null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/Scope.java b/src/main/java/dk/camelot64/kickc/model/Scope.java
index eb20833ad..4280069ae 100644
--- a/src/main/java/dk/camelot64/kickc/model/Scope.java
+++ b/src/main/java/dk/camelot64/kickc/model/Scope.java
@@ -34,7 +34,7 @@ public abstract class Scope implements Symbol {
this.symbols = symbols;
this.intermediateVarCount = intermediateVarCount;
this.intermediateLabelCount = intermediateLabelCount;
- for (Symbol symbol : symbols.values()) {
+ for(Symbol symbol : symbols.values()) {
symbol.setScope(this);
}
}
@@ -45,6 +45,16 @@ public abstract class Scope implements Symbol {
this.symbols = new LinkedHashMap<>();
}
+ public static String getFullName(Symbol symbol) {
+ if(symbol.getScope() != null) {
+ String scopeName = symbol.getScope().getFullName();
+ if(scopeName.length() > 0) {
+ return scopeName + "::" + symbol.getLocalName();
+ }
+ }
+ return symbol.getLocalName();
+ }
+
public HashMap getSymbols() {
return symbols;
}
@@ -59,16 +69,6 @@ public abstract class Scope implements Symbol {
return getFullName(this);
}
- public static String getFullName(Symbol symbol) {
- if (symbol.getScope() != null) {
- String scopeName = symbol.getScope().getFullName();
- if (scopeName.length() > 0) {
- return scopeName + "::" + symbol.getLocalName();
- }
- }
- return symbol.getLocalName();
- }
-
public ScopeRef getRef() {
return new ScopeRef(this);
}
@@ -79,6 +79,11 @@ public abstract class Scope implements Symbol {
return parentScope;
}
+ @Override
+ public void setScope(Scope scope) {
+ this.parentScope = scope;
+ }
+
@Override
@JsonIgnore
public abstract SymbolType getType();
@@ -86,7 +91,7 @@ public abstract class Scope implements Symbol {
@Override
@JsonIgnore
public int getScopeDepth() {
- if (parentScope == null) {
+ if(parentScope == null) {
return 0;
} else {
return parentScope.getScopeDepth() + 1;
@@ -94,7 +99,7 @@ public abstract class Scope implements Symbol {
}
public Symbol add(Symbol symbol) {
- if (symbols.get(symbol.getLocalName()) != null) {
+ if(symbols.get(symbol.getLocalName()) != null) {
throw new RuntimeException("Symbol already declared " + symbol.getLocalName());
}
symbols.put(symbol.getLocalName(), symbol);
@@ -120,12 +125,13 @@ public abstract class Scope implements Symbol {
/**
* Get all versions of an unversioned variable
+ *
* @param unversioned The unversioned variable
* @return All versions of the variable
*/
public Collection getVersions(VariableUnversioned unversioned) {
LinkedHashSet versions = new LinkedHashSet<>();
- for (Symbol symbol : symbols.values()) {
+ for(Symbol symbol : symbols.values()) {
if(symbol instanceof VariableVersion) {
if(((VariableVersion) symbol).isVersioned()) {
if(((VariableVersion) symbol).getVersionOf().equals(unversioned)) {
@@ -137,7 +143,6 @@ public abstract class Scope implements Symbol {
return versions;
}
-
public String allocateIntermediateVariableName() {
return "$" + intermediateVarCount++;
}
@@ -148,11 +153,11 @@ public abstract class Scope implements Symbol {
public Symbol getSymbol(String name) {
int pos = name.indexOf("::");
- if (pos >= 0) {
+ if(pos >= 0) {
String scopeName = name.substring(0, pos);
String rest = name.substring(pos + 2);
Symbol scopeSym = getSymbol(scopeName);
- if (scopeSym instanceof Scope) {
+ if(scopeSym instanceof Scope) {
return ((Scope) scopeSym).getSymbol(rest);
} else {
return null;
@@ -160,8 +165,8 @@ public abstract class Scope implements Symbol {
}
} else {
Symbol symbol = symbols.get(name);
- if (symbol == null) {
- if (parentScope != null) {
+ if(symbol == null) {
+ if(parentScope != null) {
symbol = parentScope.getSymbol(name);
}
}
@@ -188,11 +193,11 @@ public abstract class Scope implements Symbol {
@JsonIgnore
public Collection getAllVariables(boolean includeSubScopes) {
Collection vars = new ArrayList<>();
- for (Symbol symbol : symbols.values()) {
- if (symbol instanceof Variable) {
+ for(Symbol symbol : symbols.values()) {
+ if(symbol instanceof Variable) {
vars.add((Variable) symbol);
}
- if (includeSubScopes && symbol instanceof Scope) {
+ if(includeSubScopes && symbol instanceof Scope) {
Scope subScope = (Scope) symbol;
vars.addAll(subScope.getAllVariables(true));
}
@@ -203,11 +208,11 @@ public abstract class Scope implements Symbol {
public Collection getAllConstants(boolean includeSubScopes) {
Collection vars = new ArrayList<>();
- for (Symbol symbol : symbols.values()) {
- if (symbol instanceof ConstantVar) {
+ for(Symbol symbol : symbols.values()) {
+ if(symbol instanceof ConstantVar) {
vars.add((ConstantVar) symbol);
}
- if (includeSubScopes && symbol instanceof Scope) {
+ if(includeSubScopes && symbol instanceof Scope) {
Scope subScope = (Scope) symbol;
vars.addAll(subScope.getAllConstants(true));
}
@@ -216,19 +221,19 @@ public abstract class Scope implements Symbol {
return vars;
}
-
/**
* Get all scopes contained in the scope. This does not include this scope itself.
+ *
* @param includeSubScopes Include sub-scopes og sub-scopes
* @return The scopes
*/
@JsonIgnore
public Collection getAllScopes(boolean includeSubScopes) {
Collection scopes = new ArrayList<>();
- for (Symbol symbol : symbols.values()) {
- if (symbol instanceof Scope) {
+ for(Symbol symbol : symbols.values()) {
+ if(symbol instanceof Scope) {
scopes.add((Scope) symbol);
- if (includeSubScopes) {
+ if(includeSubScopes) {
Scope subScope = (Scope) symbol;
scopes.addAll(subScope.getAllScopes(true));
}
@@ -239,15 +244,14 @@ public abstract class Scope implements Symbol {
public Collection getAllProcedures(boolean includeSubScopes) {
Collection procedures = new ArrayList<>();
- for (Scope scope : getAllScopes(includeSubScopes)) {
- if (scope instanceof Procedure) {
+ for(Scope scope : getAllScopes(includeSubScopes)) {
+ if(scope instanceof Procedure) {
procedures.add((Procedure) scope);
}
}
return procedures;
}
-
public Label addLabel(String name) {
Label symbol = new Label(name, this, false);
add(symbol);
@@ -271,7 +275,7 @@ public abstract class Scope implements Symbol {
public Procedure addProcedure(String name, SymbolType type) {
Symbol symbol = symbols.get(name);
- if (symbol != null) {
+ if(symbol != null) {
throw new RuntimeException("Error! Symbol already defined " + symbol);
}
Procedure procedure = new Procedure(name, type, this);
@@ -281,7 +285,7 @@ public abstract class Scope implements Symbol {
public Procedure getProcedure(String name) {
Symbol symbol = getSymbol(name);
- if (symbol != null && symbol instanceof Procedure) {
+ if(symbol != null && symbol instanceof Procedure) {
return (Procedure) symbol;
} else {
return null;
@@ -289,19 +293,18 @@ public abstract class Scope implements Symbol {
}
public Scope getScope(ScopeRef scopeRef) {
- if (scopeRef.getFullName().equals("") && this instanceof ProgramScope) {
+ if(scopeRef.getFullName().equals("") && this instanceof ProgramScope) {
// Special case for the outer program scope
return this;
}
Symbol symbol = getSymbol(scopeRef);
- if (symbol instanceof Scope) {
+ if(symbol instanceof Scope) {
return (Scope) symbol;
} else {
return null;
}
}
-
public Procedure getProcedure(ProcedureRef ref) {
return (Procedure) getSymbol(ref);
}
@@ -313,35 +316,35 @@ public abstract class Scope implements Symbol {
Set names = symbols.keySet();
List sortedNames = new ArrayList<>(names);
Collections.sort(sortedNames);
- for (String name : sortedNames) {
+ for(String name : sortedNames) {
Symbol symbol = symbols.get(name);
- if (symbol instanceof Scope) {
+ if(symbol instanceof Scope) {
res.append(((Scope) symbol).toString(program, symbolClass));
} else {
- if (symbolClass == null || symbolClass.isInstance(symbol)) {
+ if(symbolClass == null || symbolClass.isInstance(symbol)) {
res.append(symbol.toString(program));
- if (symbol instanceof Variable) {
+ if(symbol instanceof Variable) {
Variable var = (Variable) symbol;
String asmName = var.getAsmName();
- if (asmName != null) {
+ if(asmName != null) {
res.append(" " + asmName);
}
Registers.Register register = var.getAllocation();
- if (register != null) {
+ if(register != null) {
res.append(" " + register);
}
}
- if (symbol instanceof Variable && registerWeights != null) {
+ if(symbol instanceof Variable && registerWeights != null) {
Variable var = (Variable) symbol;
Double weight = registerWeights.getWeight(var.getRef());
- if (weight != null) {
+ if(weight != null) {
res.append(" " + weight);
}
}
- if (symbol instanceof ConstantVar) {
+ if(symbol instanceof ConstantVar) {
ConstantVar constantVar = (ConstantVar) symbol;
String asmName = constantVar.getAsmName();
- if (asmName != null) {
+ if(asmName != null) {
res.append(" " + asmName);
}
res.append(" = " + constantVar.getValue().toString(program));
@@ -358,32 +361,27 @@ public abstract class Scope implements Symbol {
return symbols.values();
}
- @Override
- public void setScope(Scope scope) {
- this.parentScope = scope;
- }
-
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
Scope scope = (Scope) o;
- if (intermediateVarCount != scope.intermediateVarCount) {
+ if(intermediateVarCount != scope.intermediateVarCount) {
return false;
}
- if (intermediateLabelCount != scope.intermediateLabelCount) {
+ if(intermediateLabelCount != scope.intermediateLabelCount) {
return false;
}
- if (!name.equals(scope.name)) {
+ if(!name.equals(scope.name)) {
return false;
}
- if (!symbols.equals(scope.symbols)) {
+ if(!symbols.equals(scope.symbols)) {
return false;
}
return true;
diff --git a/src/main/java/dk/camelot64/kickc/model/ScopeRef.java b/src/main/java/dk/camelot64/kickc/model/ScopeRef.java
index 738797510..b9bb3419b 100644
--- a/src/main/java/dk/camelot64/kickc/model/ScopeRef.java
+++ b/src/main/java/dk/camelot64/kickc/model/ScopeRef.java
@@ -3,7 +3,7 @@ package dk.camelot64.kickc.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
-/** A reference to a scope */
+/** A reference to a scope */
public class ScopeRef extends SymbolRef {
/** The ROOT scope of the program. */
diff --git a/src/main/java/dk/camelot64/kickc/model/Statement.java b/src/main/java/dk/camelot64/kickc/model/Statement.java
index 36d3ed65b..85ff16dbf 100644
--- a/src/main/java/dk/camelot64/kickc/model/Statement.java
+++ b/src/main/java/dk/camelot64/kickc/model/Statement.java
@@ -23,9 +23,9 @@ public interface Statement {
String toString(Program program, boolean aliveInfo);
- /** Set the index of the statement. Indexes are used during live range analysis. */
- void setIndex(Integer idx);
-
/** Get the index of the statement. Indexes are used during live range analysis. */
Integer getIndex();
+
+ /** Set the index of the statement. Indexes are used during live range analysis. */
+ void setIndex(Integer idx);
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementAssignment.java b/src/main/java/dk/camelot64/kickc/model/StatementAssignment.java
index aa4030b01..91f666d70 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementAssignment.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementAssignment.java
@@ -97,24 +97,24 @@ public class StatementAssignment extends StatementBase implements StatementLValu
public String toString(Program program, boolean aliveInfo) {
return
super.idxString() +
- lValue.toString(program) + " ← " +
- (rValue1==null?"":rValue1.toString(program)+" ") +
- (operator==null?"":operator+" ") +
+ lValue.toString(program) + " ← " +
+ (rValue1 == null ? "" : rValue1.toString(program) + " ") +
+ (operator == null ? "" : operator + " ") +
rValue2.toString(program) +
- (aliveInfo?super.aliveString(program):"");
+ (aliveInfo ? super.aliveString(program) : "");
}
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- if (!super.equals(o)) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+ if(!super.equals(o)) return false;
StatementAssignment that = (StatementAssignment) o;
- if (!lValue.equals(that.lValue)) return false;
- if (rValue1 != null ? !rValue1.equals(that.rValue1) : that.rValue1 != null) return false;
- if (operator != null ? !operator.equals(that.operator) : that.operator != null) return false;
+ if(!lValue.equals(that.lValue)) return false;
+ if(rValue1 != null ? !rValue1.equals(that.rValue1) : that.rValue1 != null) return false;
+ if(operator != null ? !operator.equals(that.operator) : that.operator != null) return false;
return rValue2 != null ? rValue2.equals(that.rValue2) : that.rValue2 == null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementBase.java b/src/main/java/dk/camelot64/kickc/model/StatementBase.java
index 6b4baa2eb..dbcbb641e 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementBase.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementBase.java
@@ -3,7 +3,7 @@ package dk.camelot64.kickc.model;
import java.util.Collection;
import java.util.List;
-/** Statement base class implementing shared properties and logic */
+/** Statement base class implementing shared properties and logic */
public abstract class StatementBase implements Statement {
private Integer index;
@@ -24,8 +24,8 @@ public abstract class StatementBase implements Statement {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
StatementBase that = (StatementBase) o;
return index != null ? index.equals(that.index) : that.index == null;
}
@@ -36,7 +36,7 @@ public abstract class StatementBase implements Statement {
}
public String idxString() {
- return index==null?"":("["+index+"] ");
+ return index == null ? "" : ("[" + index + "] ");
}
@Override
@@ -45,17 +45,17 @@ public abstract class StatementBase implements Statement {
}
public String aliveString(Program program) {
- if(program==null || program.getLiveRangeVariables()==null) {
+ if(program == null || program.getLiveRangeVariables() == null) {
return "";
}
LiveRangeVariables liveRanges = program.getLiveRangeVariables();
StringBuilder alive = new StringBuilder();
alive.append(getAliveString(liveRanges.getAlive(this)));
LiveRangeVariablesEffective liveRangeVariablesEffective = program.getLiveRangeVariablesEffective();
- if(liveRangeVariablesEffective!=null) {
+ if(liveRangeVariablesEffective != null) {
LiveRangeVariablesEffective.AliveCombinations aliveCombinations = liveRangeVariablesEffective.getAliveCombinations(this);
alive.append(" ( ");
- for (LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
+ for(LiveRangeVariablesEffective.CallPath callPath : aliveCombinations.getCallPaths().getCallPaths()) {
alive.append(getCallPathString(callPath.getPath()));
alive.append(getAliveString(aliveCombinations.getEffectiveAliveAtStmt(callPath)));
alive.append(" ");
@@ -68,7 +68,7 @@ public abstract class StatementBase implements Statement {
private String getCallPathString(List path) {
StringBuilder out = new StringBuilder();
boolean first = true;
- for (CallGraph.CallBlock.Call call : path) {
+ for(CallGraph.CallBlock.Call call : path) {
if(!first) {
out.append("::");
}
@@ -81,7 +81,7 @@ public abstract class StatementBase implements Statement {
private String getAliveString(Collection alive) {
StringBuilder str = new StringBuilder();
str.append(" [ ");
- for (VariableRef variableRef : alive) {
+ for(VariableRef variableRef : alive) {
str.append(variableRef.getFullName());
str.append(" ");
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementCall.java b/src/main/java/dk/camelot64/kickc/model/StatementCall.java
index a03a0630f..44db887ad 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementCall.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementCall.java
@@ -100,22 +100,22 @@ public class StatementCall extends StatementBase implements StatementLValue {
public String toString(Program program, boolean aliveInfo) {
StringBuilder res = new StringBuilder();
res.append(super.idxString());
- if (lValue != null) {
+ if(lValue != null) {
res.append(lValue.toString(program));
res.append(" ← ");
}
res.append("call ");
- if (procedure != null) {
+ if(procedure != null) {
res.append(procedure.getFullName() + " ");
} else {
res.append(procedureName + " ");
}
- if (parameters != null) {
- for (RValue parameter : parameters) {
+ if(parameters != null) {
+ for(RValue parameter : parameters) {
res.append(parameter.toString(program) + " ");
}
}
- if (parametersByAssignment) {
+ if(parametersByAssignment) {
res.append("param-assignment");
}
if(aliveInfo) {
@@ -126,16 +126,16 @@ public class StatementCall extends StatementBase implements StatementLValue {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- if (!super.equals(o)) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+ if(!super.equals(o)) return false;
StatementCall that = (StatementCall) o;
- if (parametersByAssignment != that.parametersByAssignment) return false;
- if (lValue != null ? !lValue.equals(that.lValue) : that.lValue != null) return false;
- if (!procedureName.equals(that.procedureName)) return false;
- if (procedure != null ? !procedure.equals(that.procedure) : that.procedure != null) return false;
+ if(parametersByAssignment != that.parametersByAssignment) return false;
+ if(lValue != null ? !lValue.equals(that.lValue) : that.lValue != null) return false;
+ if(!procedureName.equals(that.procedureName)) return false;
+ if(procedure != null ? !procedure.equals(that.procedure) : that.procedure != null) return false;
return parameters != null ? parameters.equals(that.parameters) : that.parameters == null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementConditionalJump.java b/src/main/java/dk/camelot64/kickc/model/StatementConditionalJump.java
index 65a85ce79..d60abb87e 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementConditionalJump.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementConditionalJump.java
@@ -10,7 +10,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* if ( Yj ) goto XX
*
* The condition may be a single boolean variable, or a comparison between two variables (==, <>, <, >, <=, >= )
- *
*/
public class StatementConditionalJump extends StatementBase {
@@ -53,30 +52,30 @@ public class StatementConditionalJump extends StatementBase {
return rValue1;
}
- public Operator getOperator() {
- return operator;
- }
-
- public RValue getrValue2() {
- return rValue2;
- }
-
- public LabelRef getDestination() {
- return destination;
- }
-
public void setrValue1(RValue rValue1) {
this.rValue1 = rValue1;
}
+ public Operator getOperator() {
+ return operator;
+ }
+
public void setOperator(Operator operator) {
this.operator = operator;
}
+ public RValue getrValue2() {
+ return rValue2;
+ }
+
public void setrValue2(RValue rValue2) {
this.rValue2 = rValue2;
}
+ public LabelRef getDestination() {
+ return destination;
+ }
+
public void setDestination(LabelRef destination) {
this.destination = destination;
}
@@ -86,7 +85,7 @@ public class StatementConditionalJump extends StatementBase {
StringBuilder out = new StringBuilder();
out.append(super.idxString());
out.append("if(");
- if(rValue1!=null) {
+ if(rValue1 != null) {
out.append(rValue1.toString(program));
out.append(operator.getOperator());
}
@@ -101,15 +100,15 @@ public class StatementConditionalJump extends StatementBase {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- if (!super.equals(o)) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+ if(!super.equals(o)) return false;
StatementConditionalJump that = (StatementConditionalJump) o;
- if (rValue1 != null ? !rValue1.equals(that.rValue1) : that.rValue1 != null) return false;
- if (operator != null ? !operator.equals(that.operator) : that.operator != null) return false;
- if (rValue2 != null ? !rValue2.equals(that.rValue2) : that.rValue2 != null) return false;
+ if(rValue1 != null ? !rValue1.equals(that.rValue1) : that.rValue1 != null) return false;
+ if(operator != null ? !operator.equals(that.operator) : that.operator != null) return false;
+ if(rValue2 != null ? !rValue2.equals(that.rValue2) : that.rValue2 != null) return false;
return destination.equals(that.destination);
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementInfos.java b/src/main/java/dk/camelot64/kickc/model/StatementInfos.java
index 331ddddf0..5ca6c38b0 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementInfos.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementInfos.java
@@ -22,6 +22,7 @@ public class StatementInfos {
/**
* Get the label of the block containing a statement
+ *
* @param stmtIdx The statement index
* @return The block label
*/
@@ -31,6 +32,7 @@ public class StatementInfos {
/**
* Get the label of the block containing a statement
+ *
* @param stmt The statement
* @return The block label
*/
@@ -40,6 +42,7 @@ public class StatementInfos {
/**
* Get the block containing a statement
+ *
* @param stmt The statement
* @return The containing block
*/
@@ -49,6 +52,7 @@ public class StatementInfos {
/**
* Get the block containing a statement
+ *
* @param stmtIdx The statement index
* @return The containing block
*/
@@ -58,6 +62,7 @@ public class StatementInfos {
/**
* Get statement from index
+ *
* @param Statement index
* @return The statement with the passed index
*/
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementJump.java b/src/main/java/dk/camelot64/kickc/model/StatementJump.java
index 5874bdb66..f64ee7dd0 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementJump.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementJump.java
@@ -25,7 +25,7 @@ public class StatementJump extends StatementBase {
@Override
public String toString(Program program, boolean aliveInfo) {
- return super.idxString() + "goto " + destination.getFullName()+ (aliveInfo?super.aliveString(program):"");
+ return super.idxString() + "goto " + destination.getFullName() + (aliveInfo ? super.aliveString(program) : "");
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementLabel.java b/src/main/java/dk/camelot64/kickc/model/StatementLabel.java
index a681430c2..e4f73bbc0 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementLabel.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementLabel.java
@@ -18,7 +18,7 @@ public class StatementLabel extends StatementBase {
@Override
public String toString(Program program, boolean aliveInfo) {
- return super.idxString() + label.getFullName() + ":"+(aliveInfo?super.aliveString(program):"");
+ return super.idxString() + label.getFullName() + ":" + (aliveInfo ? super.aliveString(program) : "");
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementPhiBlock.java b/src/main/java/dk/camelot64/kickc/model/StatementPhiBlock.java
index 13537d04d..c0873465b 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementPhiBlock.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementPhiBlock.java
@@ -4,7 +4,9 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
/**
* The Phi Block initializing the necessary SSA-variables of a predecessor.
@@ -38,7 +40,7 @@ public class StatementPhiBlock extends StatementBase {
@JsonIgnore
public List getVariables() {
ArrayList vars = new ArrayList<>();
- for (PhiVariable phiVariable : phiVariables) {
+ for(PhiVariable phiVariable : phiVariables) {
vars.add(phiVariable.getVariable());
}
return vars;
@@ -46,8 +48,8 @@ public class StatementPhiBlock extends StatementBase {
}
public PhiVariable getPhiVariable(VariableRef variable) {
- for (PhiVariable phiVariable : phiVariables) {
- if (phiVariable.getVariable().equals(variable)) {
+ for(PhiVariable phiVariable : phiVariables) {
+ if(phiVariable.getVariable().equals(variable)) {
return phiVariable;
}
}
@@ -67,7 +69,7 @@ public class StatementPhiBlock extends StatementBase {
StringBuilder s = new StringBuilder();
List variables = new ArrayList<>(phiVariables);
Collections.reverse(variables);
- if(phiVariables.size()==0) {
+ if(phiVariables.size() == 0) {
s.append(super.idxString());
s.append("phi()");
if(aliveInfo) {
@@ -75,16 +77,16 @@ public class StatementPhiBlock extends StatementBase {
}
s.append("\n ");
}
- for (PhiVariable phiVariable : variables) {
+ for(PhiVariable phiVariable : variables) {
s.append(super.idxString());
s.append(phiVariable.getVariable().toString(program));
s.append(" ← phi(");
- for (PhiRValue phiRValue : phiVariable.getValues()) {
+ for(PhiRValue phiRValue : phiVariable.getValues()) {
s.append(" ");
s.append(phiRValue.getPredecessor().toString(null));
s.append("/");
RValue rValue = phiRValue.getrValue();
- s.append(rValue==null?"null":rValue.toString(program));
+ s.append(rValue == null ? "null" : rValue.toString(program));
}
s.append(" )");
if(aliveInfo) {
@@ -92,7 +94,7 @@ public class StatementPhiBlock extends StatementBase {
}
s.append("\n ");
}
- if(s.length()>0) {
+ if(s.length() > 0) {
return s.toString().substring(0, s.length() - 3);
} else {
return s.toString();
@@ -112,9 +114,9 @@ public class StatementPhiBlock extends StatementBase {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- if (!super.equals(o)) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+ if(!super.equals(o)) return false;
StatementPhiBlock phiBlock = (StatementPhiBlock) o;
@@ -167,18 +169,17 @@ public class StatementPhiBlock extends StatementBase {
this.variable = variable;
}
- public void setValues(List values) {
- this.values = values;
- }
-
public List getValues() {
return values;
}
+ public void setValues(List values) {
+ this.values = values;
+ }
public RValue getrValue(LabelRef predecessor) {
- for (PhiRValue phiRValue : values) {
- if (phiRValue.getPredecessor().equals(predecessor)) {
+ for(PhiRValue phiRValue : values) {
+ if(phiRValue.getPredecessor().equals(predecessor)) {
return phiRValue.getrValue();
}
}
@@ -193,8 +194,8 @@ public class StatementPhiBlock extends StatementBase {
* @return The rValue assigned to the phi variable when entering from the passed block.
*/
public PhiRValue getPhirValue(LabelRef predecessor) {
- for (PhiRValue phiRValue : values) {
- if (phiRValue.getPredecessor().equals(predecessor)) {
+ for(PhiRValue phiRValue : values) {
+ if(phiRValue.getPredecessor().equals(predecessor)) {
return phiRValue;
}
}
@@ -215,12 +216,12 @@ public class StatementPhiBlock extends StatementBase {
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
PhiVariable that = (PhiVariable) o;
- if (!variable.equals(that.variable)) return false;
+ if(!variable.equals(that.variable)) return false;
return values.equals(that.values);
}
@@ -263,6 +264,10 @@ public class StatementPhiBlock extends StatementBase {
return predecessor;
}
+ public void setPredecessor(LabelRef predecessor) {
+ this.predecessor = predecessor;
+ }
+
public RValue getrValue() {
return rValue;
}
@@ -271,18 +276,14 @@ public class StatementPhiBlock extends StatementBase {
this.rValue = rValue;
}
- public void setPredecessor(LabelRef predecessor) {
- this.predecessor = predecessor;
- }
-
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
PhiRValue phiRValue = (PhiRValue) o;
- if (!predecessor.equals(phiRValue.predecessor)) return false;
+ if(!predecessor.equals(phiRValue.predecessor)) return false;
return rValue != null ? rValue.equals(phiRValue.rValue) : phiRValue.rValue == null;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementProcedureBegin.java b/src/main/java/dk/camelot64/kickc/model/StatementProcedureBegin.java
index f6d4c5650..a172922c8 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementProcedureBegin.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementProcedureBegin.java
@@ -7,11 +7,6 @@ public class StatementProcedureBegin extends StatementBase {
private Strategy strategy;
- public static enum Strategy {
- PASS_BY_REGISTER,
- INLINE
- }
-
public StatementProcedureBegin(ProcedureRef procedure) {
super(null);
this.procedure = procedure;
@@ -31,7 +26,12 @@ public class StatementProcedureBegin extends StatementBase {
@Override
public String toString(Program program, boolean aliveInfo) {
- return super.idxString() + "proc " + procedure.toString(program) + (aliveInfo?super.aliveString(program):"");
+ return super.idxString() + "proc " + procedure.toString(program) + (aliveInfo ? super.aliveString(program) : "");
+ }
+
+ public static enum Strategy {
+ PASS_BY_REGISTER,
+ INLINE
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementProcedureEnd.java b/src/main/java/dk/camelot64/kickc/model/StatementProcedureEnd.java
index a7bcdb3af..f61520dbb 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementProcedureEnd.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementProcedureEnd.java
@@ -18,6 +18,6 @@ public class StatementProcedureEnd extends StatementBase {
@Override
public String toString(Program program, boolean aliveInfo) {
- return super.idxString() + "endproc // " + procedure.getFullName() + "()"+(aliveInfo?super.aliveString(program):"");
+ return super.idxString() + "endproc // " + procedure.getFullName() + "()" + (aliveInfo ? super.aliveString(program) : "");
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementReturn.java b/src/main/java/dk/camelot64/kickc/model/StatementReturn.java
index f18c684f2..e39bb5f51 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementReturn.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementReturn.java
@@ -36,14 +36,14 @@ public class StatementReturn extends StatementBase {
@Override
public String toString(Program program, boolean aliveInfo) {
- return super.idxString() + "return " + (value == null ? "" : value.toString(program)) + (aliveInfo?super.aliveString(program):"");
+ return super.idxString() + "return " + (value == null ? "" : value.toString(program)) + (aliveInfo ? super.aliveString(program) : "");
}
@Override
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- if (!super.equals(o)) return false;
+ if(this == o) return true;
+ if(o == null || getClass() != o.getClass()) return false;
+ if(!super.equals(o)) return false;
StatementReturn that = (StatementReturn) o;
diff --git a/src/main/java/dk/camelot64/kickc/model/StatementSequence.java b/src/main/java/dk/camelot64/kickc/model/StatementSequence.java
index 57e7f0691..a93cded01 100644
--- a/src/main/java/dk/camelot64/kickc/model/StatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/model/StatementSequence.java
@@ -22,11 +22,11 @@ public class StatementSequence {
public String toString(Program program) {
StringBuffer out = new StringBuffer();
- for (Statement statement : statements) {
+ for(Statement statement : statements) {
if(!(statement instanceof StatementLabel) && !(statement instanceof StatementProcedureBegin) && !(statement instanceof StatementProcedureEnd)) {
out.append(" ");
}
- out.append(statement.toString(program, true)+"\n");
+ out.append(statement.toString(program, true) + "\n");
}
return out.toString();
}
diff --git a/src/main/java/dk/camelot64/kickc/model/Symbol.java b/src/main/java/dk/camelot64/kickc/model/Symbol.java
index 03081bc6d..2ca755057 100644
--- a/src/main/java/dk/camelot64/kickc/model/Symbol.java
+++ b/src/main/java/dk/camelot64/kickc/model/Symbol.java
@@ -16,10 +16,10 @@ public interface Symbol extends Value {
@JsonIgnore
Scope getScope();
+ void setScope(Scope scope);
+
@JsonIgnore
int getScopeDepth();
- void setScope(Scope scope);
-
SymbolRef getRef();
}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolRef.java b/src/main/java/dk/camelot64/kickc/model/SymbolRef.java
index f3557a913..108d058e8 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolRef.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolRef.java
@@ -26,10 +26,10 @@ public class SymbolRef implements Value {
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
@@ -45,12 +45,12 @@ public class SymbolRef implements Value {
@Override
public String toString(Program program) {
- if (program == null) {
+ if(program == null) {
return fullName;
} else {
try {
return program.getScope().getSymbol(fullName).toString(program);
- } catch (NullPointerException e) {
+ } catch(NullPointerException e) {
throw e;
}
}
@@ -60,10 +60,10 @@ public class SymbolRef implements Value {
public int getScopeDepth() {
int depth = 0;
char[] chars = fullName.toCharArray();
- for (char c : chars) {
- if(c==':') depth++;
+ for(char c : chars) {
+ if(c == ':') depth++;
}
- return depth/2;
+ return depth / 2;
}
@JsonIgnore
@@ -75,7 +75,7 @@ public class SymbolRef implements Value {
public boolean isIntermediate() {
if(
fullName.contains(BEGIN_BLOCK_NAME) ||
- fullName.contains(END_BLOCK_NAME) ) return false;
+ fullName.contains(END_BLOCK_NAME)) return false;
return fullName.contains("$") || fullName.contains("@");
}
@@ -87,17 +87,17 @@ public class SymbolRef implements Value {
@JsonIgnore
public String getLocalName() {
int lastScopeIdx = fullName.lastIndexOf("::");
- if(lastScopeIdx==-1) {
+ if(lastScopeIdx == -1) {
return fullName;
} else {
- return fullName.substring(lastScopeIdx+2);
+ return fullName.substring(lastScopeIdx + 2);
}
}
@JsonIgnore
public String getScopeNames() {
int lastScopeIdx = fullName.lastIndexOf("::");
- if(lastScopeIdx==-1) {
+ if(lastScopeIdx == -1) {
return "";
} else {
return fullName.substring(0, lastScopeIdx);
@@ -112,7 +112,7 @@ public class SymbolRef implements Value {
public String getFullNameUnversioned() {
if(isVersion()) {
return fullName.substring(0, fullName.indexOf("#"));
- } else {
+ } else {
return fullName;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/SymbolType.java
index 0c887062d..c08020ff6 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolType.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolType.java
@@ -10,8 +10,8 @@ public interface SymbolType {
SymbolTypeInteger BYTE = new SymbolTypeInteger("byte", 0, 255);
/** Signed byte (8 bits). */
SymbolTypeInteger SBYTE = new SymbolTypeInteger("signed byte", -128, 127);
- /** Unsigned word (2 bytes, 16 bits). */
- SymbolTypeInteger WORD = new SymbolTypeInteger("word", 0, 65_535);
+ /** Unsigned word (2 bytes, 16 bits). */
+ SymbolTypeInteger WORD = new SymbolTypeInteger("word", 0, 65_535);
/** Signed word (2 bytes, 16 bits). */
SymbolTypeInteger SWORD = new SymbolTypeInteger("signed word", -32_768, 32_767);
/** String value (treated like byte* ). */
@@ -27,32 +27,35 @@ public interface SymbolType {
/** An unresolved type. Will be infered later. */
SymbolTypeBasic VAR = new SymbolTypeBasic("var");
- /**
- * Get the name of the type
- * @return The type name
- */
- String getTypeName();
-
/**
* Get a simple symbol type from the type name.
+ *
* @param name The type name.
* @return The simple symbol type
*/
static SymbolType get(String name) {
- switch (name) {
- case "byte": return BYTE;
- case "signed byte": return SBYTE;
- case "word": return WORD;
- case "signed word": return SWORD;
- case "string": return STRING;
- case "boolean": return BOOLEAN;
- case "void": return VOID;
+ switch(name) {
+ case "byte":
+ return BYTE;
+ case "signed byte":
+ return SBYTE;
+ case "word":
+ return WORD;
+ case "signed word":
+ return SWORD;
+ case "string":
+ return STRING;
+ case "boolean":
+ return BOOLEAN;
+ case "void":
+ return VOID;
}
return null;
}
/**
* Get all integer types.
+ *
* @return All integeer types
*/
static Collection getIntegerTypes() {
@@ -66,6 +69,7 @@ public interface SymbolType {
/**
* Is the type {@link #BYTE} or compatible {@link SymbolTypeInline}
+ *
* @param type The type to examine
* @return true if the type is BYTE compatible
*/
@@ -81,6 +85,7 @@ public interface SymbolType {
/**
* Is the type {@link #SBYTE} or compatible {@link SymbolTypeInline}
+ *
* @param type The type to examine
* @return true if the type is SBYTE compatible
*/
@@ -96,6 +101,7 @@ public interface SymbolType {
/**
* Is the type {@link #WORD} or compatible {@link SymbolTypeInline}
+ *
* @param type The type to examine
* @return true if the type is WORD compatible
*/
@@ -111,6 +117,7 @@ public interface SymbolType {
/**
* Is the type {@link #SWORD} or compatible {@link SymbolTypeInline}
+ *
* @param type The type to examine
* @return true if the type is SWORD compatible
*/
@@ -124,4 +131,11 @@ public interface SymbolType {
}
}
+ /**
+ * Get the name of the type
+ *
+ * @return The type name
+ */
+ String getTypeName();
+
}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java
index c31d4245d..fcd9a6f60 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeBasic.java
@@ -15,10 +15,10 @@ public class SymbolTypeBasic implements SymbolType {
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java
index a10fdcaea..42b6b1600 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInference.java
@@ -14,8 +14,8 @@ public class SymbolTypeInference {
* Infer the type of a unary operator on a value
*
* @param programScope The program scope usable for accessing the symbol table
- * @param operator The unary operator
- * @param rValue The value
+ * @param operator The unary operator
+ * @param rValue The value
* @return The type of the resulting value
*/
public static SymbolType inferType(ProgramScope programScope, Operator operator, RValue rValue) {
@@ -179,7 +179,7 @@ public class SymbolTypeInference {
return SymbolType.STRING;
} else if(type1.equals(SymbolType.STRING) && type2 instanceof SymbolTypeArray && SymbolType.isByte(((SymbolTypeArray) type2).getElementType())) {
return SymbolType.STRING;
- } else if(type1 instanceof SymbolTypeArray && SymbolType.isByte(((SymbolTypeArray) type1).getElementType()) && type2.equals(SymbolType.STRING) ) {
+ } else if(type1 instanceof SymbolTypeArray && SymbolType.isByte(((SymbolTypeArray) type1).getElementType()) && type2.equals(SymbolType.STRING)) {
return SymbolType.STRING;
} else if(type1 instanceof SymbolTypeArray && type2 instanceof SymbolTypeArray) {
SymbolType elemType1 = ((SymbolTypeArray) type1).getElementType();
@@ -287,7 +287,7 @@ public class SymbolTypeInference {
type = inferTypeList(symbols, (ValueList) rValue);
} else if(rValue instanceof PointerDereference) {
SymbolType pointerType = inferType(symbols, ((PointerDereference) rValue).getPointer());
- if(pointerType instanceof SymbolTypePointer ) {
+ if(pointerType instanceof SymbolTypePointer) {
return ((SymbolTypePointer) pointerType).getElementType();
} else if(pointerType.equals(SymbolType.STRING)) {
return SymbolType.BYTE;
@@ -380,7 +380,7 @@ public class SymbolTypeInference {
if(SymbolType.isByte(((SymbolTypePointer) lValueType).getElementType())) {
return true;
}
- } else if(SymbolType.STRING.equals(lValueType) && rValueType instanceof SymbolTypePointer ) {
+ } else if(SymbolType.STRING.equals(lValueType) && rValueType instanceof SymbolTypePointer) {
if(SymbolType.isByte(((SymbolTypePointer) rValueType).getElementType())) {
return true;
}
@@ -401,7 +401,7 @@ public class SymbolTypeInference {
* Determine is a list of potential inferred types contains a match for another type
*
* @param lValueType The type (rValue) we want to find a match for in the list
- * @param rTypes The list of inferred potential types
+ * @param rTypes The list of inferred potential types
* @return true if the list has a match
*/
private static boolean typeContainsMatch(SymbolType lValueType, Collection rTypes) {
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInline.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInline.java
index e0651c983..b4fe607e9 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInline.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInline.java
@@ -9,6 +9,8 @@ import java.util.Collection;
*/
public class SymbolTypeInline implements SymbolType {
+ /** All numeric types. */
+ public static final SymbolTypeInline NUMERIC = new SymbolTypeInline(Arrays.asList(BYTE, SBYTE, WORD, SWORD));
/**
* All potential types for the inline constant.
*/
@@ -22,15 +24,12 @@ public class SymbolTypeInline implements SymbolType {
return types;
}
- /** All numeric types. */
- public static final SymbolTypeInline NUMERIC = new SymbolTypeInline(Arrays.asList(BYTE, SBYTE, WORD, SWORD) );
-
@Override
public String getTypeName() {
StringBuilder name = new StringBuilder();
boolean first = true;
- for (SymbolType type : types) {
- if (first) {
+ for(SymbolType type : types) {
+ if(first) {
first = false;
} else {
name.append("/");
@@ -42,10 +41,10 @@ public class SymbolTypeInline implements SymbolType {
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
SymbolTypeInline that = (SymbolTypeInline) o;
@@ -64,6 +63,7 @@ public class SymbolTypeInline implements SymbolType {
/**
* Is unsigned byte one of the potential types
+ *
* @return true if unsigned byte is a potential type
*/
public boolean isByte() {
@@ -72,6 +72,7 @@ public class SymbolTypeInline implements SymbolType {
/**
* Is signed byte one of the potential types
+ *
* @return true if signed byte is a potential type
*/
public boolean isSByte() {
@@ -80,6 +81,7 @@ public class SymbolTypeInline implements SymbolType {
/**
* Is unsigned word one of the potential types
+ *
* @return true if unsigned word is a potential type
*/
public boolean isWord() {
@@ -88,6 +90,7 @@ public class SymbolTypeInline implements SymbolType {
/**
* Is signed word one of the potential types
+ *
* @return true if signed word is a potential type
*/
public boolean isSWord() {
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInteger.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInteger.java
index 34abe30fb..5af7057fb 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeInteger.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeInteger.java
@@ -1,6 +1,6 @@
package dk.camelot64.kickc.model;
-/** Integer symbol types (byte, signed byte, word, ...). */
+/** Integer symbol types (byte, signed byte, word, ...). */
public class SymbolTypeInteger implements SymbolType {
private final String typeName;
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypePointer.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypePointer.java
index bfbf48dda..883bf4d4b 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypePointer.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypePointer.java
@@ -26,15 +26,15 @@ public class SymbolTypePointer implements SymbolType {
@Override
@JsonIgnore
public String getTypeName() {
- return elementType.getTypeName()+"*";
+ return elementType.getTypeName() + "*";
}
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeProcedure.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeProcedure.java
index e40bdf9ca..785e13c73 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeProcedure.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeProcedure.java
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
-/** A function returning another type */
+/** A function returning another type */
public class SymbolTypeProcedure implements SymbolType {
private SymbolType returnType;
diff --git a/src/main/java/dk/camelot64/kickc/model/SymbolTypeProgram.java b/src/main/java/dk/camelot64/kickc/model/SymbolTypeProgram.java
index 7190f805d..54d94fcda 100644
--- a/src/main/java/dk/camelot64/kickc/model/SymbolTypeProgram.java
+++ b/src/main/java/dk/camelot64/kickc/model/SymbolTypeProgram.java
@@ -2,7 +2,7 @@ package dk.camelot64.kickc.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
-/** A program */
+/** A program */
public class SymbolTypeProgram implements SymbolType {
public SymbolTypeProgram() {
diff --git a/src/main/java/dk/camelot64/kickc/model/Value.java b/src/main/java/dk/camelot64/kickc/model/Value.java
index 159f9c8ad..0601c78d2 100644
--- a/src/main/java/dk/camelot64/kickc/model/Value.java
+++ b/src/main/java/dk/camelot64/kickc/model/Value.java
@@ -21,9 +21,9 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonSubTypes.Type(value = PointerDereferenceSimple.class, name = "pointer_simple"),
@JsonSubTypes.Type(value = ProgramScope.class, name = "program"),
@JsonSubTypes.Type(value = Procedure.class, name = "procedure")
- })
+})
public interface Value {
- String toString(Program program);
+ String toString(Program program);
}
diff --git a/src/main/java/dk/camelot64/kickc/model/ValueList.java b/src/main/java/dk/camelot64/kickc/model/ValueList.java
index 5e54a3bff..c286a1931 100644
--- a/src/main/java/dk/camelot64/kickc/model/ValueList.java
+++ b/src/main/java/dk/camelot64/kickc/model/ValueList.java
@@ -2,10 +2,12 @@ package dk.camelot64.kickc.model;
import java.util.List;
-/** A list of sub-values. Used for array variable initializers and word from byte constructors
+/**
+ * A list of sub-values. Used for array variable initializers and word from byte constructors
* (in the future also usable for dword from byte, dword from double etc.).
* Compilation execution will resolve into a constant array,
- * constant word or word constructor operator before ASM-generation. */
+ * constant word or word constructor operator before ASM-generation.
+ */
public class ValueList implements RValue {
private List list;
@@ -23,8 +25,8 @@ public class ValueList implements RValue {
StringBuilder out = new StringBuilder();
boolean first = true;
out.append("{ ");
- for (RValue constantValue : list) {
- if (!first) {
+ for(RValue constantValue : list) {
+ if(!first) {
out.append(", ");
}
first = false;
diff --git a/src/main/java/dk/camelot64/kickc/model/Variable.java b/src/main/java/dk/camelot64/kickc/model/Variable.java
index d16829599..c4cde7572 100644
--- a/src/main/java/dk/camelot64/kickc/model/Variable.java
+++ b/src/main/java/dk/camelot64/kickc/model/Variable.java
@@ -51,6 +51,10 @@ public abstract class Variable implements Symbol {
return type;
}
+ public void setType(SymbolType type) {
+ this.type = type;
+ }
+
public void setTypeInferred(SymbolType type) {
this.type = type;
this.inferredType = true;
@@ -64,22 +68,14 @@ public abstract class Variable implements Symbol {
this.inferredType = inferredType;
}
- public void setScope(Scope scope) {
- this.scope = scope;
- }
-
- public void setType(SymbolType type) {
- this.type = type;
+ public String getName() {
+ return name;
}
public void setName(String name) {
this.name = name;
}
- public String getName() {
- return name;
- }
-
public Registers.Register getAllocation() {
return allocation;
}
@@ -102,17 +98,20 @@ public abstract class Variable implements Symbol {
@JsonIgnore
public abstract boolean isIntermediate();
-
public Scope getScope() {
return scope;
}
+ public void setScope(Scope scope) {
+ this.scope = scope;
+ }
+
@Override
public int getScopeDepth() {
- if(scope==null) {
+ if(scope == null) {
return 0;
} else {
- return scope.getScopeDepth()+1;
+ return scope.getScopeDepth() + 1;
}
}
@@ -155,28 +154,28 @@ public abstract class Variable implements Symbol {
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
Variable variable = (Variable) o;
- if (inferredType != variable.inferredType) {
+ if(inferredType != variable.inferredType) {
return false;
}
- if (name != null ? !name.equals(variable.name) : variable.name != null) {
+ if(name != null ? !name.equals(variable.name) : variable.name != null) {
return false;
}
- if (scope != null ? !scope.equals(variable.scope) : variable.scope != null) {
+ if(scope != null ? !scope.equals(variable.scope) : variable.scope != null) {
return false;
}
- if (type != null ? !type.equals(variable.type) : variable.type != null) {
+ if(type != null ? !type.equals(variable.type) : variable.type != null) {
return false;
}
- if (allocation != null ? !allocation.equals(variable.allocation) : variable.allocation != null) {
+ if(allocation != null ? !allocation.equals(variable.allocation) : variable.allocation != null) {
return false;
}
return asmName != null ? asmName.equals(variable.asmName) : variable.asmName == null;
diff --git a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java
index 13e6ee9c0..124006449 100644
--- a/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java
+++ b/src/main/java/dk/camelot64/kickc/model/VariableReferenceInfos.java
@@ -6,7 +6,7 @@ import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
-/** Cached information about which variables are defined/referenced/used in statements / blocks. */
+/** Cached information about which variables are defined/referenced/used in statements / blocks. */
public class VariableReferenceInfos {
/** The congtaining program. */
@@ -33,7 +33,7 @@ public class VariableReferenceInfos {
/** All statements referencing each constant. */
private Map> constRefStmts;
- /** All constants referencing another constant. (maps from a constant to all constants using it in their value)*/
+ /** All constants referencing another constant. (maps from a constant to all constants using it in their value) */
private Map> constRefConsts;
public VariableReferenceInfos(
@@ -57,8 +57,19 @@ public class VariableReferenceInfos {
this.constRefConsts = constRefConsts;
}
+ /**
+ * Get all variables referenced in an rValue
+ *
+ * @param rValue The rValue
+ * @return All referenced variables
+ */
+ public static Collection getReferencedVars(RValue rValue) {
+ return PassNVariableReferenceInfos.getReferencedVars(rValue);
+ }
+
/**
* Get all variables used or defined inside a block and its successors (including any called method)
+ *
* @param labelRef The block to examine
* @return All used variables
*/
@@ -68,6 +79,7 @@ public class VariableReferenceInfos {
/**
* Get all variables used inside a block and its successors (including any called method)
+ *
* @param labelRef The block to examine
* @return All used variables
*/
@@ -77,6 +89,7 @@ public class VariableReferenceInfos {
/**
* Get the variables defined by a statement
+ *
* @param stmt The statement
* @return Variables defined by the statement
*/
@@ -86,6 +99,7 @@ public class VariableReferenceInfos {
/**
* Get the variables referenced (used or defined) in a statement
+ *
* @param statement The statement to examine
* @return The referenced variables
*/
@@ -95,6 +109,7 @@ public class VariableReferenceInfos {
/**
* Get the variables used, but not defined, in a statement
+ *
* @param statement The statement to examine
* @return The used variables (not including defined variables)
*/
@@ -105,27 +120,20 @@ public class VariableReferenceInfos {
return used;
}
- /**
- * Get all variables referenced in an rValue
- * @param rValue The rValue
- * @return All referenced variables
- */
- public static Collection getReferencedVars(RValue rValue) {
- return PassNVariableReferenceInfos.getReferencedVars(rValue);
- }
-
/**
* Determines if a variable is unused
+ *
* @return true if the variable is defined but never referenced
*/
public boolean isUnused(VariableRef variableRef) {
Collection refs = new LinkedHashSet<>(varRefStmts.get(variableRef));
refs.remove(varDefineStmt.get(variableRef));
- return refs.size()==0;
+ return refs.size() == 0;
}
/**
* Determines if a constant is unused
+ *
* @return true if the constant is never referenced
*/
public boolean isUnused(ConstantRef constRef) {
diff --git a/src/main/java/dk/camelot64/kickc/model/VariableRegisterWeights.java b/src/main/java/dk/camelot64/kickc/model/VariableRegisterWeights.java
index 89de874f4..6217875eb 100644
--- a/src/main/java/dk/camelot64/kickc/model/VariableRegisterWeights.java
+++ b/src/main/java/dk/camelot64/kickc/model/VariableRegisterWeights.java
@@ -20,11 +20,11 @@ public class VariableRegisterWeights {
* Add to the weight of a variable
*
* @param variableRef The variable
- * @param w The amount to add to the weight
+ * @param w The amount to add to the weight
*/
public void addWeight(VariableRef variableRef, double w) {
Double weight = this.registerWeights.get(variableRef);
- if (weight == null) {
+ if(weight == null) {
weight = 0.0;
}
weight = weight + w;
@@ -38,7 +38,7 @@ public class VariableRegisterWeights {
public double getTotalWeight(LiveRangeEquivalenceClass equivalenceClass) {
double totalWeight = 0.0;
List vars = equivalenceClass.getVariables();
- for (VariableRef var : vars) {
+ for(VariableRef var : vars) {
Double varWeight = getWeight(var);
totalWeight += varWeight;
}
@@ -47,7 +47,7 @@ public class VariableRegisterWeights {
public double getTotalWeights(RegisterUpliftScope upliftScope) {
double totalWeight = 0.0;
- for (LiveRangeEquivalenceClass equivalenceClass : upliftScope.getEquivalenceClasses()) {
+ for(LiveRangeEquivalenceClass equivalenceClass : upliftScope.getEquivalenceClasses()) {
totalWeight += getTotalWeight(equivalenceClass);
}
return totalWeight;
diff --git a/src/main/java/dk/camelot64/kickc/model/VariableUnversioned.java b/src/main/java/dk/camelot64/kickc/model/VariableUnversioned.java
index 97b1d5a17..7f7f996fa 100644
--- a/src/main/java/dk/camelot64/kickc/model/VariableUnversioned.java
+++ b/src/main/java/dk/camelot64/kickc/model/VariableUnversioned.java
@@ -34,8 +34,8 @@ public class VariableUnversioned extends Variable {
}
public VariableVersion createVersion() {
- VariableVersion version = new VariableVersion(this, this.getNextVersionNumber());
- getScope().add(version);
- return version;
+ VariableVersion version = new VariableVersion(this, this.getNextVersionNumber());
+ getScope().add(version);
+ return version;
}
}
diff --git a/src/main/java/dk/camelot64/kickc/model/VariableVersion.java b/src/main/java/dk/camelot64/kickc/model/VariableVersion.java
index 206ad7ed8..94e37e6fd 100644
--- a/src/main/java/dk/camelot64/kickc/model/VariableVersion.java
+++ b/src/main/java/dk/camelot64/kickc/model/VariableVersion.java
@@ -10,7 +10,7 @@ public class VariableVersion extends Variable {
private String versionOfName;
public VariableVersion(VariableUnversioned versionOf, int version) {
- super(versionOf.getLocalName()+"#"+version, versionOf.getScope(), versionOf.getType());
+ super(versionOf.getLocalName() + "#" + version, versionOf.getScope(), versionOf.getType());
this.setDeclaredAlignment(versionOf.getDeclaredAlignment());
this.versionOfName = versionOf.getLocalName();
}
@@ -49,13 +49,13 @@ public class VariableVersion extends Variable {
@Override
public boolean equals(Object o) {
- if (this == o) {
+ if(this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if(o == null || getClass() != o.getClass()) {
return false;
}
- if (!super.equals(o)) {
+ if(!super.equals(o)) {
return false;
}
diff --git a/src/main/java/dk/camelot64/kickc/passes/AliasReplacer.java b/src/main/java/dk/camelot64/kickc/passes/AliasReplacer.java
index 41e290d8f..767d818e0 100644
--- a/src/main/java/dk/camelot64/kickc/passes/AliasReplacer.java
+++ b/src/main/java/dk/camelot64/kickc/passes/AliasReplacer.java
@@ -24,52 +24,52 @@ public class AliasReplacer implements ValueReplacer.Replacer {
* @return The alias to use. Null if no alias exists.
*/
public static RValue getReplacement(RValue rValue, Map extends SymbolRef, ? extends RValue> aliases) {
- if (rValue instanceof SymbolRef) {
+ if(rValue instanceof SymbolRef) {
RValue alias = aliases.get(rValue);
- if (alias != null) {
- if (alias.equals(rValue)) {
+ if(alias != null) {
+ if(alias.equals(rValue)) {
return alias;
}
RValue replacement = getReplacement(alias, aliases);
- if (replacement != null) {
+ if(replacement != null) {
return replacement;
} else {
return alias;
}
}
- } else if (rValue instanceof ConstantUnary) {
+ } else if(rValue instanceof ConstantUnary) {
ConstantUnary constantUnary = (ConstantUnary) rValue;
ConstantValue alias = (ConstantValue) getReplacement(constantUnary.getOperand(), aliases);
- if (alias != null) {
+ if(alias != null) {
return new ConstantUnary(constantUnary.getOperator(), alias);
}
- } else if (rValue instanceof ConstantBinary) {
+ } else if(rValue instanceof ConstantBinary) {
ConstantBinary constantBinary = (ConstantBinary) rValue;
ConstantValue aliasLeft = (ConstantValue) getReplacement(constantBinary.getLeft(), aliases);
ConstantValue aliasRight = (ConstantValue) getReplacement(constantBinary.getRight(), aliases);
- if (aliasLeft != null || aliasRight != null) {
- if (aliasLeft == null) {
+ if(aliasLeft != null || aliasRight != null) {
+ if(aliasLeft == null) {
aliasLeft = constantBinary.getLeft();
}
- if (aliasRight == null) {
+ if(aliasRight == null) {
aliasRight = constantBinary.getRight();
}
return new ConstantBinary(aliasLeft, constantBinary.getOperator(), aliasRight);
}
- } else if (rValue instanceof ConstantArrayList) {
+ } else if(rValue instanceof ConstantArrayList) {
ConstantArrayList constantArrayList = (ConstantArrayList) rValue;
ArrayList replacementList = new ArrayList<>();
boolean any = false;
- for (ConstantValue elemValue : constantArrayList.getElements()) {
+ for(ConstantValue elemValue : constantArrayList.getElements()) {
RValue elemReplacement = getReplacement(elemValue, aliases);
- if (elemReplacement != null) {
+ if(elemReplacement != null) {
replacementList.add((ConstantValue) elemReplacement);
any = true;
} else {
replacementList.add(elemValue);
}
}
- if (any) {
+ if(any) {
return new ConstantArrayList(replacementList, constantArrayList.getElementType());
}
}
@@ -81,13 +81,14 @@ public class AliasReplacer implements ValueReplacer.Replacer {
/**
* Execute alias replacement on a replaceable value
+ *
* @param replaceable The replaceable value
*/
@Override
public void execute(ValueReplacer.ReplaceableValue replaceable, Statement currentStmt, ListIterator stmtIt, ControlFlowBlock currentBlock) {
- if (replaceable.get() != null) {
+ if(replaceable.get() != null) {
RValue replacement = getReplacement(replaceable.get(), aliases);
- if (replacement != null) {
+ if(replacement != null) {
replaceable.set(replacement);
}
}
diff --git a/src/main/java/dk/camelot64/kickc/passes/ParseTreeConstantEvaluator.java b/src/main/java/dk/camelot64/kickc/passes/ParseTreeConstantEvaluator.java
index 35d6b864b..3eda464ee 100644
--- a/src/main/java/dk/camelot64/kickc/passes/ParseTreeConstantEvaluator.java
+++ b/src/main/java/dk/camelot64/kickc/passes/ParseTreeConstantEvaluator.java
@@ -19,10 +19,99 @@ public class ParseTreeConstantEvaluator extends KickCBaseVisitor
return (new ParseTreeConstantEvaluator()).visit(expr);
}
+ static ConstantValue calculateBinary(Operator operator, ConstantValue c1, ConstantValue c2) {
+ switch(operator.getOperator()) {
+ case "-": {
+ if(c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
+ return new ConstantInteger(getInteger(c1) - getInteger(c2));
+ } else {
+ return new ConstantDouble(getDouble(c1) - getDouble(c2));
+ }
+ }
+ case "+": {
+ if(c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
+ return new ConstantInteger(getInteger(c1) + getInteger(c2));
+ } else {
+ return new ConstantDouble(getDouble(c1) + getDouble(c2));
+ }
+ }
+ case "*": {
+ if(c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
+ return new ConstantInteger(getInteger(c1) * getInteger(c2));
+ } else {
+ return new ConstantDouble(getDouble(c1) * getDouble(c2));
+ }
+ }
+ case "/": {
+ if(c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
+ return new ConstantInteger(getInteger(c1) / getInteger(c2));
+ } else {
+ return new ConstantDouble(getDouble(c1) / getDouble(c2));
+ }
+ }
+ case "*idx": {
+ // Cannot be directly propagated
+ return null;
+ }
+ default:
+ throw new RuntimeException("Unhandled Binary Operator " + operator.getOperator());
+ }
+ }
+
+ private static Integer getInteger(ConstantValue constant) {
+ if(constant instanceof ConstantInteger) {
+ return ((ConstantInteger) constant).getNumber();
+ } else {
+ throw new RuntimeException("Type Mismatch. Constant is not an integer number " + constant);
+ }
+ }
+
+ private static Double getDouble(ConstantValue constant) {
+ if(constant instanceof ConstantDouble) {
+ return ((ConstantDouble) constant).getNumber();
+ } else if(constant instanceof ConstantInteger) {
+ return ((ConstantInteger) constant).getNumber().doubleValue();
+ } else {
+ throw new RuntimeException("Type Mismatch. Constant is not a number " + constant);
+ }
+ }
+
+ public static ConstantValue calculateUnary(Operator operator, ConstantValue c) {
+ switch(operator.getOperator()) {
+ case "-": {
+ if(c instanceof ConstantInteger) {
+ ConstantInteger cInt = (ConstantInteger) c;
+ return new ConstantInteger(-cInt.getNumber());
+ } else if(c instanceof ConstantDouble) {
+ ConstantDouble cDoub = (ConstantDouble) c;
+ return new ConstantDouble(-cDoub.getNumber());
+ } else {
+ throw new RuntimeException("Type mismatch. Unary Minus cannot handle value " + c);
+ }
+ }
+ case "+": {
+ return c;
+ }
+ case "++": {
+ ConstantInteger cInt = (ConstantInteger) c;
+ return new ConstantInteger(cInt.getNumber() + 1);
+ }
+ case "--": {
+ ConstantInteger cInt = (ConstantInteger) c;
+ return new ConstantInteger(cInt.getNumber() - 1);
+ }
+ case "*": { // pointer dereference
+ return null;
+ }
+ default:
+ throw new RuntimeException("Unhandled Unary Operator " + operator.getOperator());
+ }
+ }
+
@Override
public ConstantValue visitExprNumber(KickCParser.ExprNumberContext ctx) {
Number number = NumberParser.parseLiteral(ctx.getText());
- if(number instanceof Integer) {
+ if(number instanceof Integer) {
return new ConstantInteger((Integer) number);
} else {
return new ConstantDouble((Double) number);
@@ -72,7 +161,7 @@ public class ParseTreeConstantEvaluator extends KickCBaseVisitor
@Override
public ConstantValue visitExprUnary(KickCParser.ExprUnaryContext ctx) {
ConstantValue sub = visit(ctx.expr());
- String op = ((TerminalNode)ctx.getChild(0)).getSymbol().getText();
+ String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText();
Operator operator = Operator.getUnary(op);
return calculateUnary(operator, sub);
}
@@ -81,7 +170,7 @@ public class ParseTreeConstantEvaluator extends KickCBaseVisitor
public ConstantValue visitExprBinary(KickCParser.ExprBinaryContext ctx) {
ConstantValue left = this.visit(ctx.expr(0));
ConstantValue right = this.visit(ctx.expr(1));
- String op = ((TerminalNode)ctx.getChild(1)).getSymbol().getText();
+ String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText();
Operator operator = Operator.getBinary(op);
return calculateBinary(operator, left, right);
}
@@ -92,93 +181,4 @@ public class ParseTreeConstantEvaluator extends KickCBaseVisitor
}
}
- static ConstantValue calculateBinary(Operator operator, ConstantValue c1, ConstantValue c2) {
- switch (operator.getOperator()) {
- case "-": {
- if (c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
- return new ConstantInteger(getInteger(c1) - getInteger(c2));
- } else {
- return new ConstantDouble(getDouble(c1) - getDouble(c2));
- }
- }
- case "+": {
- if (c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
- return new ConstantInteger(getInteger(c1) + getInteger(c2));
- } else {
- return new ConstantDouble(getDouble(c1) + getDouble(c2));
- }
- }
- case "*": {
- if (c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
- return new ConstantInteger(getInteger(c1) * getInteger(c2));
- } else {
- return new ConstantDouble(getDouble(c1) * getDouble(c2));
- }
- }
- case "/": {
- if (c1 instanceof ConstantInteger && c2 instanceof ConstantInteger) {
- return new ConstantInteger(getInteger(c1) / getInteger(c2));
- } else {
- return new ConstantDouble(getDouble(c1) / getDouble(c2));
- }
- }
- case "*idx": {
- // Cannot be directly propagated
- return null;
- }
- default:
- throw new RuntimeException("Unhandled Binary Operator " + operator.getOperator());
- }
- }
-
- private static Integer getInteger(ConstantValue constant) {
- if (constant instanceof ConstantInteger) {
- return ((ConstantInteger) constant).getNumber();
- } else {
- throw new RuntimeException("Type Mismatch. Constant is not an integer number " + constant);
- }
- }
-
- private static Double getDouble(ConstantValue constant) {
- if (constant instanceof ConstantDouble) {
- return ((ConstantDouble) constant).getNumber();
- } else if (constant instanceof ConstantInteger) {
- return ((ConstantInteger) constant).getNumber().doubleValue();
- } else {
- throw new RuntimeException("Type Mismatch. Constant is not a number " + constant);
- }
- }
-
- public static ConstantValue calculateUnary(Operator operator, ConstantValue c) {
- switch (operator.getOperator()) {
- case "-": {
- if (c instanceof ConstantInteger) {
- ConstantInteger cInt = (ConstantInteger) c;
- return new ConstantInteger(-cInt.getNumber());
- } else if (c instanceof ConstantDouble) {
- ConstantDouble cDoub = (ConstantDouble) c;
- return new ConstantDouble(-cDoub.getNumber());
- } else {
- throw new RuntimeException("Type mismatch. Unary Minus cannot handle value " + c);
- }
- }
- case "+": {
- return c;
- }
- case "++": {
- ConstantInteger cInt = (ConstantInteger) c;
- return new ConstantInteger(cInt.getNumber()+1);
- }
- case "--": {
- ConstantInteger cInt = (ConstantInteger) c;
- return new ConstantInteger(cInt.getNumber()-1);
- }
- case "*": { // pointer dereference
- return null;
- }
- default:
- throw new RuntimeException("Unhandled Unary Operator " + operator.getOperator());
- }
- }
-
}
diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
index f71902dbd..70ee4c868 100644
--- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
+++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java
@@ -152,7 +152,7 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor