1 pnkfelix 1.1.2.1 // RegFile.java, created Wed Dec 8 16:24:41 1999 by pnkfelix 2 pnkfelix 1.1.2.1 // Copyright (C) 1999 Felix S. Klock II <pnkfelix@mit.edu> 3 pnkfelix 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 pnkfelix 1.1.2.1 package harpoon.Analysis.Instr; 5 pnkfelix 1.1.2.1 6 pnkfelix 1.1.2.1 import harpoon.Temp.Temp; 7 pnkfelix 1.1.2.10 import harpoon.IR.Assem.Instr; 8 pnkfelix 1.1.2.1 import harpoon.Util.Util; 9 pnkfelix 1.1.2.1 10 pnkfelix 1.1.2.1 import java.util.List; 11 pnkfelix 1.1.2.1 import java.util.Map; 12 pnkfelix 1.1.2.2 import java.util.Set; 13 pnkfelix 1.1.2.1 import java.util.HashMap; 14 pnkfelix 1.1.2.2 import java.util.HashSet; 15 pnkfelix 1.1.2.1 import java.util.Collections; 16 pnkfelix 1.1.2.9 import java.util.Collection; 17 pnkfelix 1.1.2.1 import java.util.Iterator; 18 pnkfelix 1.1.2.1 19 pnkfelix 1.1.2.1 /** 20 pnkfelix 1.1.2.1 * <code>RegFile</code> is an abstraction for a register file found in 21 pnkfelix 1.1.2.1 * most processor architectures for storing working sets of data. 22 pnkfelix 1.1.2.1 * 23 pnkfelix 1.1.2.1 * @author Felix S. Klock II <pnkfelix@mit.edu> 24 cananian 1.5 * @version $Id: RegFile.java,v 1.5 2004/02/08 03:19:37 cananian Exp $ 25 pnkfelix 1.1.2.1 */ 26 pnkfelix 1.1.2.1 class RegFile { 27 pnkfelix 1.1.2.6 28 pnkfelix 1.1.2.6 public static final boolean PRINT_USAGE = false; 29 pnkfelix 1.1.2.6 30 pnkfelix 1.1.2.9 private Collection allRegs; 31 pnkfelix 1.1.2.9 32 pnkfelix 1.1.2.8 private Map regToTmp; // Map[ Reg -> Temp ] 33 pnkfelix 1.1.2.10 private Map tmpToRegLst; // Map[ Temp -> (List<Reg>, Instr) ] 34 pnkfelix 1.1.2.1 35 pnkfelix 1.1.2.2 private Set dirtyTemps; // Set of all Temps that have been written 36 pnkfelix 1.1.2.2 37 pnkfelix 1.1.2.1 /** Creates a <code>RegFile</code>. */ 38 pnkfelix 1.1.2.9 public RegFile(Collection allRegisters) { 39 pnkfelix 1.1.2.8 regToTmp = new HashMap(); 40 pnkfelix 1.1.2.2 tmpToRegLst = new HashMap(); 41 pnkfelix 1.1.2.2 dirtyTemps = new HashSet(); 42 pnkfelix 1.1.2.9 allRegs = allRegisters; 43 pnkfelix 1.1.2.1 } 44 pnkfelix 1.1.2.1 45 pnkfelix 1.1.2.2 /** Marks the pseudo register <code>preg</code> as dirty. 46 pnkfelix 1.1.2.7 <BR> <B>requires:</B> <OL> 47 pnkfelix 1.1.2.7 <LI> <code>preg</code> is a pseudo register Temp 48 pnkfelix 1.1.2.7 (not a register) 49 pnkfelix 1.1.2.7 <LI> <code>preg</code> currently is assigned 50 pnkfelix 1.1.2.7 in <code>this</code>. 51 pnkfelix 1.1.2.7 </OL> 52 pnkfelix 1.1.2.2 <BR> <B>modifies:</B> <code>this</code> 53 pnkfelix 1.1.2.2 <BR> <B>effects:</B> marks <code>preg</code> as dirty. 54 pnkfelix 1.1.2.2 <code>preg</code> will remain dirty until it is removed 55 pnkfelix 1.1.2.2 from <code>this</code>. 56 pnkfelix 1.1.2.2 */ 57 pnkfelix 1.1.2.2 public void writeTo(Temp preg) { 58 cananian 1.3.2.1 assert hasAssignment(preg) : (/* "temp: "+preg+ */ 59 pnkfelix 1.1.2.11 " should have an assignment " 60 pnkfelix 1.1.2.11 /* +"in "+this */); 61 pnkfelix 1.1.2.5 62 pnkfelix 1.1.2.6 if (PRINT_USAGE) System.out.println(this+".writeTo: "+preg); 63 pnkfelix 1.1.2.6 64 pnkfelix 1.1.2.5 // FSK: this assertion is too strict, but it might only be 65 pnkfelix 1.1.2.5 // because of a hack in the spec-file. Find out whether we 66 pnkfelix 1.1.2.5 // can make multiple writes illegal 67 cananian 1.3.2.1 // assert !dirtyTemps.contains(preg) : // "should only write to "+preg+" once"; 68 pnkfelix 1.1.2.2 dirtyTemps.add(preg); 69 pnkfelix 1.1.2.2 } 70 pnkfelix 1.1.2.2 71 pnkfelix 1.1.2.2 /** Returns whether the pseudo register is clean. 72 pnkfelix 1.1.2.2 <BR> <B>requires:</B> <code>preg</code> currently is assigned 73 pnkfelix 1.1.2.2 in <code>this</code>. 74 pnkfelix 1.1.2.2 <BR> <B>effects:</B> if the pseudo register <code>preg</code> 75 pnkfelix 1.1.2.2 has been marked as dirty since last being assigned in 76 pnkfelix 1.1.2.2 <code>this</code>, returns False. Else returns True. 77 pnkfelix 1.1.2.2 */ 78 pnkfelix 1.1.2.2 public boolean isClean(Temp preg) { 79 pnkfelix 1.1.2.4 return !isDirty(preg); 80 pnkfelix 1.1.2.2 } 81 pnkfelix 1.1.2.2 82 pnkfelix 1.1.2.2 /** Returns whether the pseudo register is dirty. 83 pnkfelix 1.1.2.2 <BR> <B>requires:</B> <code>preg</code> currently is assigned 84 pnkfelix 1.1.2.2 in <code>this</code>. 85 pnkfelix 1.1.2.2 <BR> <B>effects:</B> if pseudo register <code>preg</code> has 86 pnkfelix 1.1.2.2 been marked as dirty since last being assigned in 87 pnkfelix 1.1.2.2 <code>this</code>, returns True. Else returns False. 88 pnkfelix 1.1.2.2 */ 89 pnkfelix 1.1.2.2 public boolean isDirty(Temp preg) { 90 cananian 1.3.2.1 assert hasAssignment(preg) : (/* "temp: "+preg+ */ 91 pnkfelix 1.1.2.11 " should have an assignment " 92 cananian 1.3.2.1 /* +"in "+this */); 93 pnkfelix 1.1.2.2 return dirtyTemps.contains(preg); 94 pnkfelix 1.1.2.2 } 95 pnkfelix 1.1.2.2 96 pnkfelix 1.1.2.2 public String toString() { 97 pnkfelix 1.1.2.6 return tmpToRegLst.toString(); 98 pnkfelix 1.1.2.6 // return regToTmp.toString(); 99 pnkfelix 1.1.2.6 // return "RegFile"+hashCode(); 100 pnkfelix 1.1.2.2 } 101 pnkfelix 1.1.2.2 102 pnkfelix 1.1.2.3 /** Returns a snapshot of the current mapping from registers to 103 pnkfelix 1.1.2.3 pseudoregisters. 104 pnkfelix 1.1.2.1 <BR> <B>effects:</B> Returns an immutable <code>Map</code> of 105 pnkfelix 1.1.2.1 Register <code>Temp</code>s to Pseudo-Register 106 pnkfelix 1.1.2.1 <code>Temp</code>s, representing the current state of the 107 pnkfelix 1.1.2.1 register file. The <code>Map</code> returned is suitable 108 pnkfelix 1.1.2.1 for use with RegFileInfo. 109 pnkfelix 1.1.2.1 */ 110 pnkfelix 1.1.2.1 public Map getRegToTemp() { 111 pnkfelix 1.1.2.1 // we create a new HashMap so that changes to the current 112 pnkfelix 1.1.2.1 // Register File are not reflected in the returned Map, and we 113 pnkfelix 1.1.2.1 // make it unmodifiable so that it remains immutable. 114 pnkfelix 1.1.2.1 return Collections.unmodifiableMap(new HashMap(regToTmp)); 115 pnkfelix 1.1.2.1 } 116 pnkfelix 1.1.2.1 117 pnkfelix 1.1.2.8 /** Generates a set-view of the pseudo-register <code>Temp</code>s 118 pnkfelix 1.1.2.8 in <code>this</code>. 119 pnkfelix 1.1.2.8 */ 120 pnkfelix 1.1.2.8 public Set tempSet() { 121 pnkfelix 1.1.2.8 return tmpToRegLst.keySet(); 122 pnkfelix 1.1.2.8 } 123 pnkfelix 1.1.2.8 124 pnkfelix 1.1.2.6 /** Returns some pseudo-register associated with <code>reg</code>. 125 pnkfelix 1.1.2.1 If there is no pseudo-register associated with 126 pnkfelix 1.1.2.1 <code>reg</code>, returns <code>null</code>. 127 pnkfelix 1.1.2.1 */ 128 pnkfelix 1.1.2.1 public Temp getTemp(Temp reg) { 129 pnkfelix 1.1.2.1 return (Temp) regToTmp.get(reg); 130 pnkfelix 1.1.2.1 } 131 pnkfelix 1.1.2.10 132 pnkfelix 1.1.2.10 class RegListAndInstr { 133 pnkfelix 1.1.2.10 final List l; final Instr i; 134 pnkfelix 1.1.2.10 RegListAndInstr(List regs, Instr instr) { 135 pnkfelix 1.1.2.10 l = regs; i = instr; 136 pnkfelix 1.1.2.10 } 137 pnkfelix 1.1.2.10 public String toString() { 138 pnkfelix 1.1.2.10 return "( "+(l!=null?l.toString():"") + ", "+ 139 pnkfelix 1.1.2.10 (i!=null?i.toString():"")+" )"; 140 pnkfelix 1.1.2.10 } 141 pnkfelix 1.1.2.10 } 142 pnkfelix 1.1.2.1 143 pnkfelix 1.1.2.10 /** Assigns <code>pseudoReg</code> to <code>regs</code> and 144 pnkfelix 1.1.2.10 <code>src</code>. 145 pnkfelix 1.1.2.1 <BR> <B>requires:</B> <OL> 146 pnkfelix 1.1.2.1 <LI> <code>pseudoReg</code> does not currently have an 147 pnkfelix 1.1.2.1 assignment in <code>this</code>. 148 pnkfelix 1.1.2.1 </OL> 149 pnkfelix 1.1.2.1 <BR> <B>modifies:</B> <code>this</code> 150 pnkfelix 1.1.2.1 <BR> <B>effects:</B> Creates an association between 151 pnkfelix 1.1.2.10 <code>pseudoReg</code> and <code>(regs, src)</code>. 152 pnkfelix 1.1.2.6 <BR> Note: Requirement 1 may seem strange, as its not 153 pnkfelix 1.1.2.6 strictly illegal in a compiler to assign a pseudo register 154 pnkfelix 1.1.2.6 multiple times to different machine registers. 155 pnkfelix 1.1.2.6 But the alternative would require making tmpToRegLst a 156 pnkfelix 1.1.2.6 MultiMap, the semantics of remove(pseudoReg) 157 pnkfelix 1.1.2.1 would have been ugly, and theres no place i know of where 158 pnkfelix 1.1.2.1 it would make sense to assign preg multiple times. 159 pnkfelix 1.1.2.1 */ 160 pnkfelix 1.1.2.10 public void assign(final Temp pseudoReg, final List regs, Instr src) { 161 cananian 1.5 for (Object regO : regs) { 162 cananian 1.5 Temp reg = (Temp) regO; 163 pnkfelix 1.1.2.6 164 pnkfelix 1.1.2.8 165 cananian 1.3.2.1 assert !regToTmp.containsKey(reg) : ("non-empty reg: " /* +reg */); 166 pnkfelix 1.1.2.6 167 pnkfelix 1.1.2.8 regToTmp.put(reg, pseudoReg); 168 pnkfelix 1.1.2.8 // regToTmp.add(reg, pseudoReg); // use if mult. assoc. 169 pnkfelix 1.1.2.1 } 170 pnkfelix 1.1.2.10 RegListAndInstr rli = new RegListAndInstr(regs, src); 171 pnkfelix 1.1.2.1 172 pnkfelix 1.1.2.6 if (tmpToRegLst.containsKey(pseudoReg)) { 173 cananian 1.3.2.1 assert ((RegListAndInstr)tmpToRegLst.get 174 cananian 1.3.2.1 (pseudoReg)).l.equals(regs) : ((true)?"dont assign pregs > once": 175 pnkfelix 1.1.2.6 "dont assign preg:"+pseudoReg+" more than once \n"+ 176 pnkfelix 1.1.2.6 "curr: "+tmpToRegLst.get(pseudoReg)+"\n"+ 177 pnkfelix 1.1.2.10 "next: "+rli); 178 pnkfelix 1.1.2.6 } 179 cananian 1.3.2.1 assert !regs.isEmpty() : "regs should not be empty"; 180 pnkfelix 1.1.2.10 tmpToRegLst.put(pseudoReg, rli); 181 pnkfelix 1.1.2.6 182 pnkfelix 1.1.2.6 if (PRINT_USAGE) System.out.println(this+".assign: "+regs+" <- "+pseudoReg); 183 pnkfelix 1.1.2.1 } 184 pnkfelix 1.1.2.1 185 pnkfelix 1.1.2.8 /** Checks if <code>reg</code> is currently holding a value in 186 pnkfelix 1.1.2.8 <code>this</code>. (Meant mainly for debugging, not for 187 pnkfelix 1.1.2.8 utility) 188 pnkfelix 1.1.2.8 */ 189 pnkfelix 1.1.2.8 public boolean isEmpty(final Temp reg) { 190 pnkfelix 1.1.2.8 return !regToTmp.containsKey(reg); 191 pnkfelix 1.1.2.8 } 192 pnkfelix 1.1.2.8 193 pnkfelix 1.1.2.1 /** Checks if <code>pseudoReg</code> has an register assignment in 194 pnkfelix 1.1.2.1 <code>this</code>. 195 pnkfelix 1.1.2.1 <BR> <B>effects:</B> If <code>pseudoReg</code> currently maps 196 pnkfelix 1.1.2.1 to some <code>List</code> of registers in 197 pnkfelix 1.1.2.1 <code>this</code>, returns <code>true</code>. 198 pnkfelix 1.1.2.1 Else returns <code>false</code>. 199 pnkfelix 1.1.2.1 */ 200 pnkfelix 1.1.2.1 public boolean hasAssignment(final Temp pseudoReg) { 201 pnkfelix 1.1.2.1 return tmpToRegLst.containsKey(pseudoReg); 202 pnkfelix 1.1.2.1 } 203 pnkfelix 1.1.2.1 204 pnkfelix 1.1.2.10 /** Returns the currently assigned register List for 205 pnkfelix 1.1.2.10 <code>pseudoReg</code>. 206 pnkfelix 1.1.2.1 <BR> <B>requires:</B> <code>pseudoReg</code> current has an 207 pnkfelix 1.1.2.1 assignment in <code>this</code>. 208 pnkfelix 1.1.2.1 <BR> <B>effects:</B> Returns the <code>List</code> of register 209 pnkfelix 1.1.2.1 <code>Temp</code>s currently associated with 210 pnkfelix 1.1.2.1 <code>pseudoReg</code> in <code>this</code>. 211 pnkfelix 1.1.2.1 */ 212 pnkfelix 1.1.2.1 public List getAssignment(final Temp pseudoReg) { 213 pnkfelix 1.1.2.10 return ((RegListAndInstr)tmpToRegLst.get(pseudoReg)).l; 214 pnkfelix 1.1.2.1 } 215 pnkfelix 1.1.2.10 216 pnkfelix 1.1.2.10 /** Returns the currently assigned Source for 217 pnkfelix 1.1.2.10 <code>pseudoReg</code>. 218 pnkfelix 1.1.2.10 <BR> <B>requires:</B> <code>pseudoReg</code> current has an 219 pnkfelix 1.1.2.10 assignment in <code>this</code>. 220 pnkfelix 1.1.2.10 <BR> <B>effects:</B> Returns the <code>Instr</code> 221 pnkfelix 1.1.2.10 currently associated with <code>pseudoReg</code> in 222 pnkfelix 1.1.2.10 <code>this</code>. 223 pnkfelix 1.1.2.10 */ 224 pnkfelix 1.1.2.10 public Instr getSource(final Temp pseudoReg) { 225 pnkfelix 1.1.2.10 RegListAndInstr rli = (RegListAndInstr) 226 pnkfelix 1.1.2.10 tmpToRegLst.get(pseudoReg); 227 cananian 1.3.2.1 assert rli != null : (/* "Temp:"+pseudoReg+ */" has no assignment"); 228 pnkfelix 1.1.2.10 return rli.i; 229 pnkfelix 1.1.2.10 } 230 pnkfelix 1.1.2.1 231 pnkfelix 1.1.2.1 /** Removes the assignment for <code>pseudoReg</code>. 232 pnkfelix 1.1.2.1 <BR> <B>requires:</B> <code>pseudoReg</code> currently has an 233 pnkfelix 1.1.2.1 assignment in <code>this</code>. 234 pnkfelix 1.1.2.1 <BR> <B>modifies:</B> <code>this</code> 235 pnkfelix 1.1.2.1 <BR> <B>effects:</B> removes all associations in 236 pnkfelix 1.1.2.1 <code>this</code> between <code>pseudoReg</code> and 237 pnkfelix 1.1.2.1 register <code>Temp</code>s. 238 pnkfelix 1.1.2.1 */ 239 pnkfelix 1.1.2.1 public void remove(final Temp pseudoReg) { 240 pnkfelix 1.1.2.10 List regs = ((RegListAndInstr)tmpToRegLst.remove(pseudoReg)).l; 241 cananian 1.5 for (Object regO : regs) { 242 cananian 1.5 Temp reg = (Temp) regO; 243 pnkfelix 1.1.2.8 regToTmp.remove(reg); 244 pnkfelix 1.1.2.1 } 245 pnkfelix 1.1.2.2 dirtyTemps.remove(pseudoReg); 246 pnkfelix 1.1.2.6 247 pnkfelix 1.1.2.6 if (PRINT_USAGE) System.out.println(this+".remove: "+pseudoReg); 248 pnkfelix 1.1.2.1 } 249 cananian 1.2 }