diff options
Diffstat (limited to 'Homework/cs5300/compiler/p5-compiler/submit/RegisterAllocator.java')
| -rw-r--r-- | Homework/cs5300/compiler/p5-compiler/submit/RegisterAllocator.java | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/Homework/cs5300/compiler/p5-compiler/submit/RegisterAllocator.java b/Homework/cs5300/compiler/p5-compiler/submit/RegisterAllocator.java new file mode 100644 index 0000000..b0c9d03 --- /dev/null +++ b/Homework/cs5300/compiler/p5-compiler/submit/RegisterAllocator.java @@ -0,0 +1,151 @@ +/* + */ +package submit; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * + * + * + */ +public final class RegisterAllocator { + + // True if t is used + private final boolean[] t = new boolean[10]; + private final boolean[] s = new boolean[8]; + private final Set<String> used = new HashSet<>(); + + public RegisterAllocator() { clearAll(); } + + public String getRegisterOrLoadIntoRegister(MIPSResult result, + StringBuilder code) { + if (result.getRegister() != null) { + return result.getRegister(); + } + String reg = result.getAddress(); + return this.loadIntoRegister(result, code, reg); + } + + public String loadIntoRegister(MIPSResult result, StringBuilder code, + String register) { + return loadIntoRegisterWithOffset(result, code, register, 0); + } + + public String loadIntoRegisterWithOffset(MIPSResult result, + StringBuilder code, String register, + int offset) { + code.append( + String.format("lw %s %d(%s)\n", register, offset, result.getAddress())); + + return register; + } + + public String getT() { + for (int i = 0; i < t.length; ++i) { + if (!t[i]) { + t[i] = true; + String str = "$t" + i; + used.add(str); + return str; + } + } + return null; + } + + // public String getS() { + // for (int i = 0; i < s.length; ++i) { + // if (!s[i]) { + // s[i] = true; + // String str = "$s" + i; + // used.add(str); + // return str; + // } + // } + // return null; + // } + + // Returns the number of bytes used to save the registers + public int saveRestore(StringBuilder code, int baseOffset, boolean s_or_t, + boolean save) { + boolean[] r = s; + String prefix = "$s"; + if (!s_or_t) { + r = t; + prefix = "$t"; + } + String instruction = "sw"; + if (!save) { + instruction = "lw"; + } + int offset = 0; + for (int i = 0; i < r.length; ++i) { + if (r[i]) { + offset -= 4; + String str = prefix + i; + code.append(instruction) + .append(" ") + .append(str) + .append(" ") + .append(offset - baseOffset) + .append("($sp)\n"); + } + } + return -offset; + } + + // public int saveS(StringBuilder code, int baseOffset) { + // return saveRestore(code, baseOffset, true, true); + // } + + public int saveT(StringBuilder code, int baseOffset) { + return saveRestore(code, baseOffset, false, true); + } + + // public int restoreS(StringBuilder code, int baseOffset) { + // return saveRestore(code, baseOffset, true, false); + // } + + public int restoreT(StringBuilder code, int baseOffset) { + return saveRestore(code, baseOffset, false, false); + } + + public List<String> getUsed() { return new ArrayList<>(used); } + + /** + * Any time you call this method you should seriously consider adding a + * corresponding clear() call. + * + * @return + */ + public String getAny() { + // String availS = getS(); + // if (availS != null) { + // return availS; + // } + String t = getT(); + if (t == null) { + throw new RuntimeException("Out of registers"); + } + return t; + } + + public void clear(String reg) { + if (reg.charAt(1) == 's') { + s[Integer.parseInt(reg.substring(2))] = false; + } else if (reg.charAt(1) == 't') { + t[Integer.parseInt(reg.substring(2))] = false; + } else { + throw new RuntimeException("Unexpected register in clear"); + } + } + + public void clearAll() { + Arrays.fill(t, false); + Arrays.fill(s, false); + } +} |
