1 witchel 1.1.2.1 // Code.java, created Fri Jul 30 13:41:35 1999 by pnkfelix 2 witchel 1.1.2.1 // Copyright (C) 1999 Felix S. Klock II <pnkfelix@mit.edu> 3 witchel 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 witchel 1.1.2.1 package harpoon.Backend.MIPS; 5 witchel 1.1.2.1 6 cananian 1.1.2.5 import harpoon.Backend.StrongARM.TwoWordTemp; 7 witchel 1.1.2.1 import harpoon.IR.Tree.CanonicalTreeCode; 8 witchel 1.1.2.1 import harpoon.IR.Assem.Instr; 9 witchel 1.1.2.1 import harpoon.Analysis.Instr.TempInstrPair; 10 witchel 1.1.2.1 import harpoon.Backend.Generic.Frame; 11 witchel 1.1.2.1 import harpoon.ClassFile.HCode; 12 witchel 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 13 witchel 1.1.2.1 import harpoon.ClassFile.HMethod; 14 witchel 1.1.2.1 import harpoon.Temp.Temp; 15 witchel 1.1.2.1 16 witchel 1.1.2.1 import java.util.List; 17 witchel 1.1.2.1 import java.util.HashMap; 18 witchel 1.1.2.1 import java.util.Map; 19 witchel 1.1.2.1 import java.util.Arrays; 20 witchel 1.1.2.1 import java.util.Collections; 21 witchel 1.1.2.1 import java.util.Collection; 22 witchel 1.1.2.1 import java.util.Set; 23 witchel 1.1.2.1 import java.util.HashSet; 24 witchel 1.1.2.1 25 cananian 1.5 import net.cscott.jutil.Util; 26 witchel 1.1.2.1 /** 27 witchel 1.1.2.1 * <code>Code</code> is a code-view for MIPS assembly. 28 witchel 1.1.2.1 * 29 witchel 1.1.2.1 * @author Felix S. Klock II <pnkfelix@mit.edu> 30 cananian 1.5 * @version $Id: Code.java,v 1.5 2004/02/08 01:57:34 cananian Exp $ 31 witchel 1.1.2.1 */ 32 cananian 1.1.2.4 class Code extends harpoon.Backend.Generic.Code { 33 witchel 1.1.2.1 public static final String codename = "mips"; 34 witchel 1.1.2.1 35 witchel 1.1.2.1 private static final boolean DEBUG = false; 36 witchel 1.1.2.1 37 witchel 1.1.2.1 Map tempInstrToRegisterMap; 38 witchel 1.1.2.1 RegFileInfo regFileInfo; 39 witchel 1.1.2.1 40 witchel 1.1.2.1 /** Creates a <code>Code</code>. */ 41 witchel 1.1.2.1 public Code(harpoon.IR.Tree.Code treeCode) { 42 witchel 1.1.2.1 super(treeCode); 43 witchel 1.1.2.1 44 cananian 1.1.2.5 // need to cast the return type to a MIPS.RegFileInfo 45 witchel 1.1.2.1 regFileInfo = (RegFileInfo) this.frame.getRegFileInfo(); 46 cananian 1.3.2.1 assert regFileInfo != null : "Need non-null regfileinfo"; 47 witchel 1.1.2.1 48 witchel 1.1.2.1 tempInstrToRegisterMap = new HashMap(); 49 witchel 1.1.2.1 } 50 witchel 1.1.2.1 51 witchel 1.1.2.1 public String getName() { return codename; } 52 witchel 1.1.2.1 53 witchel 1.1.2.1 /** 54 witchel 1.1.2.1 * Returns a code factory for <code>Code</code>, given a 55 witchel 1.1.2.1 * code factory for <code>CanonicalTreeCode</code>. 56 witchel 1.1.2.1 * <BR> <B>effects:</B> if <code>hcf</code> is a code factory for 57 witchel 1.1.2.1 * <code>CanonicalTreeCode</code>, then creates and returns a code 58 witchel 1.1.2.1 * factory for <code>Code</code>. Else passes 59 witchel 1.1.2.1 * <code>hcf</code> to 60 witchel 1.1.2.1 * <code>CanonicalTreeCode.codeFactory()</code>, and reattempts to 61 witchel 1.1.2.1 * create a code factory for <code>Code</code> from the 62 witchel 1.1.2.1 * code factory returned by <code>CanonicalTreeCode</code>. 63 witchel 1.1.2.1 * @see CanonicalTreeCode#codeFactory(HCodeFactory, Frame) 64 witchel 1.1.2.1 */ 65 witchel 1.1.2.1 public static HCodeFactory codeFactory(final HCodeFactory hcf, 66 witchel 1.1.2.1 final Frame frame) { 67 witchel 1.1.2.1 if(hcf.getCodeName().equals(CanonicalTreeCode.codename)){ 68 witchel 1.1.2.1 return new HCodeFactory() { 69 witchel 1.1.2.1 public HCode convert(HMethod m) { 70 witchel 1.1.2.1 harpoon.IR.Tree.Code tc = 71 witchel 1.1.2.1 (harpoon.IR.Tree.Code) hcf.convert(m); 72 witchel 1.1.2.1 return (tc == null) ? null : new Code(tc); 73 witchel 1.1.2.1 } 74 witchel 1.1.2.1 public void clear(HMethod m) { hcf.clear(m); } 75 witchel 1.1.2.1 public String getCodeName() { return codename; } 76 witchel 1.1.2.1 }; 77 witchel 1.1.2.1 } else { 78 witchel 1.1.2.1 // recursion can be ugly some times. 79 witchel 1.1.2.1 return codeFactory(CanonicalTreeCode. 80 witchel 1.1.2.1 codeFactory(hcf, frame), frame); 81 witchel 1.1.2.1 } 82 witchel 1.1.2.1 } 83 witchel 1.1.2.1 84 pnkfelix 1.1.2.6 public List getRegisters(Instr i, Temp val) { 85 cananian 1.3.2.1 assert i != null : "Code.getRegisters(null, Temp) undefined"; 86 witchel 1.1.2.1 if (val instanceof TwoWordTemp) { 87 witchel 1.1.2.1 TwoWordTemp t = (TwoWordTemp) val; 88 witchel 1.1.2.1 Temp low = get(i, t.getLow()); 89 witchel 1.1.2.1 Temp high = get(i, t.getHigh()); 90 cananian 1.3.2.1 assert low != null : "low register for "+val+" in "+i+ 91 cananian 1.3.2.1 " should not be null"; 92 cananian 1.3.2.1 assert high != null : "high register for "+val+" in "+i+ 93 cananian 1.3.2.1 " should not be null"; 94 witchel 1.1.2.1 return Arrays.asList(new Temp[]{ low, high }); 95 witchel 1.1.2.1 96 witchel 1.1.2.1 } else { 97 pnkfelix 1.1.2.7 Temp t; 98 pnkfelix 1.1.2.7 if ( regFileInfo.isRegister(val) ) { 99 pnkfelix 1.1.2.7 t = val; 100 pnkfelix 1.1.2.7 } else { 101 pnkfelix 1.1.2.7 t = get(i, val); 102 cananian 1.3.2.1 assert t != null : "register for "+val+" in "+i+ 103 cananian 1.3.2.1 " should not be null"; 104 pnkfelix 1.1.2.7 } 105 pnkfelix 1.1.2.6 return Collections.nCopies(1, t); 106 witchel 1.1.2.1 } 107 witchel 1.1.2.1 } 108 witchel 1.1.2.1 109 witchel 1.1.2.1 /** This returns null or a register temp. */ 110 witchel 1.1.2.1 private Temp get(Instr instr, Temp val) { 111 witchel 1.1.2.1 Temp reg = 112 witchel 1.1.2.1 (Temp) tempInstrToRegisterMap.get 113 witchel 1.1.2.1 (new TempInstrPair(instr, val)); 114 witchel 1.1.2.1 if(reg == null) return null; 115 cananian 1.3.2.1 assert regFileInfo.isRegister(reg) : ("Temp: "+reg+" should be a reg in "+ 116 witchel 1.1.2.1 "Instr: "+instr+", Val: "+val); 117 witchel 1.1.2.1 return reg; 118 witchel 1.1.2.1 } 119 witchel 1.1.2.1 120 witchel 1.1.2.1 121 witchel 1.1.2.1 public String getRegisterName(final Instr instr, 122 witchel 1.1.2.1 final Temp val, 123 witchel 1.1.2.1 final String suffix) { 124 witchel 1.1.2.1 String s=null; 125 witchel 1.1.2.1 if (val instanceof TwoWordTemp) { 126 witchel 1.1.2.1 // parse suffix 127 witchel 1.1.2.1 TwoWordTemp t = (TwoWordTemp) val; 128 witchel 1.1.2.1 Temp reg = null; 129 witchel 1.1.2.1 if (suffix.startsWith("l")) { 130 witchel 1.1.2.1 // low 131 witchel 1.1.2.1 reg = get(instr, t.getLow()); 132 witchel 1.1.2.1 } else if (suffix.startsWith("h")) { 133 witchel 1.1.2.1 // high 134 witchel 1.1.2.1 reg = get(instr, t.getHigh()); 135 witchel 1.1.2.1 } else if (suffix.trim().equals("")) { 136 cananian 1.3.2.1 assert false : ("BREAK! empty suffix " + 137 witchel 1.1.2.1 "suffix: " + suffix + "\n" + 138 witchel 1.1.2.1 "instr: " + instr + "\n" + 139 witchel 1.1.2.1 "instr str: " + instr.getAssem() + "\n"+ 140 witchel 1.1.2.1 "temp: " + val); 141 witchel 1.1.2.1 } else { 142 cananian 1.3.2.1 assert false : "BREAK! This parsing needs to be "+ 143 witchel 1.1.2.1 "fixed, strongarm has a lot more cases than this."+ 144 witchel 1.1.2.1 "\n suffix: "+ suffix + "\n" + 145 witchel 1.1.2.1 "Alternatively, the pattern could be trying to "+ 146 witchel 1.1.2.1 "use a TwoWordTemp without the appropriate "+ 147 cananian 1.3.2.1 "double word modifier (l, h) in " + instr; 148 witchel 1.1.2.1 } 149 witchel 1.1.2.1 if(reg != null) { 150 witchel 1.1.2.1 s = reg.name() + suffix.substring(1); 151 witchel 1.1.2.1 } else { 152 witchel 1.1.2.1 s = val.name() + suffix; 153 witchel 1.1.2.1 } 154 witchel 1.1.2.1 } else { // single word; nothing special 155 witchel 1.1.2.1 Temp reg = get(instr, val); 156 witchel 1.1.2.1 157 cananian 1.3.2.1 assert !suffix.startsWith("l") && 158 cananian 1.3.2.1 !suffix.startsWith("h") : "Shouldn't " + 159 witchel 1.1.2.1 "have 'l' or 'h' suffix with Temp: " + 160 witchel 1.1.2.1 val + " Instrs: " + 161 witchel 1.1.2.1 instr.getPrev() + ", " + 162 witchel 1.1.2.1 instr + ", " + 163 cananian 1.3.2.1 instr.getNext(); 164 witchel 1.1.2.1 165 witchel 1.1.2.1 if(reg != null) { 166 witchel 1.1.2.1 s = reg.name() + suffix; 167 witchel 1.1.2.1 } else { 168 witchel 1.1.2.1 s = val.name() + suffix; 169 witchel 1.1.2.1 } 170 witchel 1.1.2.1 } 171 cananian 1.3.2.1 // assert s.indexOf("r0l") == -1 && s.indexOf("r0h") == -1 && 172 cananian 1.3.2.1 // s.indexOf("r1l") == -1 && s.indexOf("r1h") == -1 : // "Improper parsing of " + suffix + " in " + instr + " " + val.getClass().getName(); 173 witchel 1.1.2.1 174 witchel 1.1.2.1 return s; 175 witchel 1.1.2.1 } 176 witchel 1.1.2.1 177 witchel 1.1.2.1 178 witchel 1.1.2.1 // overriding superclass implementation to add 179 witchel 1.1.2.1 // architecture-dependant assertions (in an effort to fail-fast) 180 witchel 1.1.2.1 public String toAssem(Instr instr) { 181 witchel 1.1.2.1 if (DEBUG) { 182 witchel 1.1.2.1 // these constraint checks may be flawed; I'm getting 183 witchel 1.1.2.1 // assertion failures on good code, i think... 184 witchel 1.1.2.1 185 witchel 1.1.2.1 // check that constants are all contained in eight-bit chunks 186 witchel 1.1.2.1 String assem = instr.getAssem(); 187 witchel 1.1.2.1 int begin = assem.lastIndexOf('#'); 188 witchel 1.1.2.1 189 witchel 1.1.2.1 190 witchel 1.1.2.1 if (begin != -1) { 191 witchel 1.1.2.1 int end = assem.length(); 192 witchel 1.1.2.1 final char[] endChars = new char[]{ '\n', '@', ']', ' '}; 193 witchel 1.1.2.1 for(int i=0; i<endChars.length; i++) { 194 witchel 1.1.2.1 int e = assem.lastIndexOf(endChars[i], end); 195 witchel 1.1.2.1 if (e > begin) end = e; 196 witchel 1.1.2.1 // System.out.println(assem.substring(begin+1, end)); 197 witchel 1.1.2.1 } 198 witchel 1.1.2.1 199 witchel 1.1.2.1 String constStr = assem.substring(begin+1, end); 200 witchel 1.1.2.1 int v = 0; 201 witchel 1.1.2.1 try { 202 witchel 1.1.2.1 v = Integer.parseInt(constStr); 203 witchel 1.1.2.1 } catch (NumberFormatException e) { 204 witchel 1.1.2.1 System.out.println("bad const extraction"); 205 witchel 1.1.2.1 System.out.println("\'"+constStr+"\'"); 206 witchel 1.1.2.1 System.out.println(" from "+instr+"("+begin+","+end+")"); 207 cananian 1.3.2.1 assert false; 208 witchel 1.1.2.1 } 209 witchel 1.1.2.1 210 cananian 1.3.2.1 assert isValidConst(v) || isValidConst(-v) : "const form err of "+v+" in "+ 211 cananian 1.3.2.1 instr+"("+begin+","+end+")"; 212 witchel 1.1.2.1 } 213 witchel 1.1.2.1 } // end if(DEBUG) 214 witchel 1.1.2.1 215 witchel 1.1.2.1 return super.toAssem(instr); 216 witchel 1.1.2.1 } 217 witchel 1.1.2.1 218 witchel 1.1.2.1 public static boolean isValidConst(final int val) { 219 witchel 1.1.2.1 // FSK: stealing code from CSA again... 220 witchel 1.1.2.1 int v; 221 witchel 1.1.2.1 int r; 222 witchel 1.1.2.1 223 witchel 1.1.2.1 v = val; 224 witchel 1.1.2.1 r=0; 225 witchel 1.1.2.1 for ( ; v!=0; r++) 226 witchel 1.1.2.1 v &= ~(0xFF << ((Util.ffs(v)-1) & ~1)); 227 witchel 1.1.2.1 return (r <= 1) ; 228 witchel 1.1.2.1 } 229 witchel 1.1.2.1 230 witchel 1.1.2.1 /** Assigns register(s) to the <code>Temp</code> pseudoReg. 231 witchel 1.1.2.1 <BR><B>requires:</B> <code>regs</code> is one of the 232 witchel 1.1.2.1 <code>List</code>s returned by 233 witchel 1.1.2.1 <code>SAFrame.suggestRegAssignment()</code> for 234 witchel 1.1.2.1 <code>pseudoReg</code>. 235 witchel 1.1.2.1 <BR><B>effects:</B> Associates the register <code>Temp</code>s 236 witchel 1.1.2.1 in <code>regs</code> with (<code>instr</code> x 237 witchel 1.1.2.1 <code>pseudoReg</code>) in such a manner that 238 witchel 1.1.2.1 <code>getRegisterName(instr, psuedoReg, suffix)</code> 239 witchel 1.1.2.1 will return the name associated with the appropriate 240 witchel 1.1.2.1 register in <code>regs</code>. 241 witchel 1.1.2.1 */ 242 witchel 1.1.2.1 public void assignRegister(final Instr instr, 243 witchel 1.1.2.1 final Temp pseudoReg, 244 witchel 1.1.2.1 final List regs) { 245 witchel 1.1.2.1 if (pseudoReg instanceof TwoWordTemp) { 246 witchel 1.1.2.1 TwoWordTemp t = (TwoWordTemp) pseudoReg; 247 witchel 1.1.2.1 tempInstrToRegisterMap.put 248 witchel 1.1.2.1 (new TempInstrPair(instr, t.getLow()), regs.get(0)); 249 witchel 1.1.2.1 tempInstrToRegisterMap.put 250 witchel 1.1.2.1 (new TempInstrPair(instr, t.getHigh()), regs.get(1)); 251 witchel 1.1.2.1 } else { 252 witchel 1.1.2.1 tempInstrToRegisterMap.put 253 witchel 1.1.2.1 (new TempInstrPair(instr, pseudoReg), regs.get(0)); 254 witchel 1.1.2.2 } 255 witchel 1.1.2.1 } 256 witchel 1.1.2.1 257 witchel 1.1.2.1 public void removeAssignment(Instr instr, Temp preg) { 258 witchel 1.1.2.1 if (preg instanceof TwoWordTemp) { 259 witchel 1.1.2.1 TwoWordTemp t = (TwoWordTemp) preg; 260 witchel 1.1.2.1 tempInstrToRegisterMap.remove 261 witchel 1.1.2.1 (new TempInstrPair(instr, t.getLow())); 262 witchel 1.1.2.1 tempInstrToRegisterMap.remove 263 witchel 1.1.2.1 (new TempInstrPair(instr, t.getHigh())); 264 witchel 1.1.2.1 } else { 265 witchel 1.1.2.1 tempInstrToRegisterMap.remove 266 witchel 1.1.2.1 (new TempInstrPair(instr, preg)); 267 witchel 1.1.2.1 } 268 witchel 1.1.2.1 } 269 witchel 1.1.2.1 270 witchel 1.1.2.1 271 witchel 1.1.2.1 public boolean registerAssigned(Instr instr, Temp pr) { 272 witchel 1.1.2.1 if (pr instanceof TwoWordTemp) { 273 witchel 1.1.2.1 TwoWordTemp t = (TwoWordTemp) pr; 274 witchel 1.1.2.1 return 275 witchel 1.1.2.1 (tempInstrToRegisterMap. 276 witchel 1.1.2.1 keySet().contains 277 witchel 1.1.2.1 (new TempInstrPair(instr, t.getLow())) 278 witchel 1.1.2.1 && 279 witchel 1.1.2.1 tempInstrToRegisterMap. 280 witchel 1.1.2.1 keySet().contains 281 witchel 1.1.2.1 (new TempInstrPair(instr, t.getHigh()))); 282 witchel 1.1.2.1 } else { 283 witchel 1.1.2.1 return 284 witchel 1.1.2.1 (tempInstrToRegisterMap. 285 witchel 1.1.2.1 keySet().contains 286 witchel 1.1.2.1 (new TempInstrPair(instr, pr))); 287 witchel 1.1.2.1 } 288 witchel 1.1.2.1 } 289 cananian 1.2 }