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     }