1 witchel 1.1.2.1 // StackInfo.java, created Mon Aug 21 21:02:54 EDT 2000 by witchel 2 cananian 1.1.2.6 // Copyright (C) 2000 Emmett Witchel <witchel@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 witchel 1.1.2.1 import harpoon.Util.Util; 7 witchel 1.1.2.1 import harpoon.Temp.TempList; 8 witchel 1.1.2.1 import harpoon.Temp.Temp; 9 witchel 1.1.2.1 import harpoon.Temp.LabelList; 10 witchel 1.1.2.1 import harpoon.Temp.Label; 11 witchel 1.1.2.1 import harpoon.IR.Tree.INVOCATION; 12 witchel 1.1.2.2 import harpoon.IR.Tree.METHOD; 13 witchel 1.1.2.1 import harpoon.IR.Tree.Type; 14 witchel 1.1.2.1 import harpoon.IR.Tree.Typed; 15 witchel 1.1.2.1 import harpoon.IR.Tree.PreciselyTyped; 16 witchel 1.1.2.1 import harpoon.IR.Tree.MEM; 17 witchel 1.1.2.1 import harpoon.IR.Tree.NAME; 18 witchel 1.1.2.2 import harpoon.IR.Tree.TEMP; 19 witchel 1.1.2.1 import harpoon.IR.Tree.ExpList; 20 witchel 1.1.2.1 21 witchel 1.1.2.1 import java.util.ArrayList; 22 witchel 1.1.2.1 import java.util.HashMap; 23 witchel 1.1.2.1 import java.io.PrintStream; 24 witchel 1.1.2.1 25 witchel 1.1.2.1 /** 26 witchel 1.1.2.1 * This class encapsulates information about a given stack frame, 27 witchel 1.1.2.1 * e.g., does it grow up or down, where is the return address stored, 28 witchel 1.1.2.1 * that sort of thing. 29 witchel 1.1.2.1 * <p> 30 witchel 1.1.2.1 * INPUT 31 witchel 1.1.2.1 * <p> 32 witchel 1.1.2.1 * <code>callInfo</code> is called up front for every call made by 33 witchel 1.1.2.1 * this frame. This information is necessary for construction of the 34 witchel 1.1.2.1 * MIPS stack frame, but it is not necessary for conventions that use a 35 witchel 1.1.2.1 * non-virtual frame pointer. 36 witchel 1.1.2.1 * <code>regAllocUsedRegs</code> is called after register allocation 37 witchel 1.1.2.1 * to give the stackinfo object knowledge of which callee saved 38 witchel 1.1.2.1 * registers were used. 39 witchel 1.1.2.1 * <code>regAllocLocalWords</code> is called after the register 40 witchel 1.1.2.1 * allocation to give the stackinfo object knowledge of how many temps 41 witchel 1.1.2.1 * the spill code needs. It would be nice to give the types of the 42 witchel 1.1.2.1 * temps to the stackinfo object and let it map temp index to registers 43 witchel 1.1.2.1 * and stack offset, but that is not the current interface to the spill 44 witchel 1.1.2.1 * information. 45 witchel 1.1.2.1 * <p> 46 witchel 1.1.2.1 * OUTPUT 47 witchel 1.1.2.1 * <P> 48 witchel 1.1.2.1 * Lots of useful offsets. 49 witchel 1.1.2.1 * The multi-word (or multi-stack slot) temp support is currently 50 witchel 1.1.2.1 * limited to two word temps. It is ugly, but its not clear that 51 witchel 1.1.2.1 * generalizing the solution is a good thing at this stage. 52 witchel 1.1.2.1 */ 53 witchel 1.1.2.1 54 witchel 1.1.2.1 public class StackInfo { 55 witchel 1.1.2.1 // Values so the stack object can tell the argument loading code 56 witchel 1.1.2.1 // where to load arguments 57 witchel 1.1.2.1 public static final int REGISTER = 0; 58 witchel 1.1.2.1 public static final int STACK = 1; 59 witchel 1.1.2.1 public static final int REGSTACKSPLIT = 2; 60 witchel 1.1.2.5 // Every stack frame is aligned on a 32 byte boundary to facilitate 61 witchel 1.1.2.5 // the tag unchecked load/store optimization 62 witchel 1.1.2.5 public static final int BYTEALIGNMENT = 32; 63 witchel 1.1.2.1 64 witchel 1.1.2.1 private class CallInfo { 65 witchel 1.1.2.1 public CallInfo() { 66 witchel 1.1.2.1 // 8 entries should be sufficient for most calls. 67 witchel 1.1.2.1 arg2word = new ArrayList(8); 68 witchel 1.1.2.1 } 69 witchel 1.1.2.1 public void setArg2Word(int arg, int word) { 70 witchel 1.1.2.1 arg2word.add(new Integer(word)); 71 cananian 1.3.2.1 assert arg == arg2word.size() - 1; 72 witchel 1.1.2.1 } 73 witchel 1.1.2.1 public int getArg2Word(int arg) { 74 cananian 1.3.2.1 assert arg >= 0 && arg < arg2word.size(); 75 witchel 1.1.2.1 Integer i = (Integer)arg2word.get(arg); 76 witchel 1.1.2.1 return i.intValue(); 77 witchel 1.1.2.1 } 78 witchel 1.1.2.1 public int getArg2StackSlot(int arg) { 79 witchel 1.1.2.1 Integer i = (Integer)arg2word.get(arg); 80 witchel 1.1.2.1 return word2StackWords(i.intValue()); 81 witchel 1.1.2.1 } 82 witchel 1.1.2.1 public int nArgs() { 83 witchel 1.1.2.1 // Array has extra entry at the end so we know how big the 84 witchel 1.1.2.1 // last arg is 85 witchel 1.1.2.1 return arg2word.size() - 1; 86 witchel 1.1.2.1 } 87 witchel 1.1.2.1 public void print(PrintStream ps) { 88 witchel 1.1.2.1 ps.print(" len=" + arg2word.size()); 89 witchel 1.1.2.1 for(int i = 0; i < arg2word.size(); ++i) { 90 witchel 1.1.2.1 ps.print(" a" + i + "=" + ((Integer)arg2word.get(i)).intValue()); 91 witchel 1.1.2.1 } 92 witchel 1.1.2.1 ps.println(""); 93 witchel 1.1.2.1 } 94 witchel 1.1.2.1 95 witchel 1.1.2.1 private ArrayList arg2word; 96 witchel 1.1.2.1 private int word2StackWords(int w) { 97 cananian 1.3.2.1 assert w >= 0; 98 witchel 1.1.2.1 if(w < NARGREGS) return 0; 99 witchel 1.1.2.1 return w - NARGREGS; 100 witchel 1.1.2.1 } 101 witchel 1.1.2.1 } 102 witchel 1.1.2.1 103 witchel 1.1.2.1 /** 104 witchel 1.1.2.1 * Each new frame should create a new stack info object. 105 witchel 1.1.2.1 */ 106 witchel 1.1.2.1 public StackInfo(RegFileInfo _regfile) { 107 witchel 1.1.2.1 max_arg_words = 0; 108 witchel 1.1.2.1 locals_done = callee_done = false; 109 witchel 1.1.2.1 regfile = _regfile; 110 witchel 1.1.2.1 fixed_words = 2; // fp and ra 111 witchel 1.1.2.1 inv2info = new HashMap(5); 112 witchel 1.1.2.1 } 113 witchel 1.1.2.1 114 witchel 1.1.2.1 /** 115 witchel 1.1.2.1 * Argument build are is the lowest region on the mips stack, 116 witchel 1.1.2.1 * starting at 0(sp) 117 witchel 1.1.2.1 */ 118 witchel 1.1.2.2 public int argOffset(Object inv, int arg_idx) { 119 witchel 1.1.2.1 CallInfo ci = (CallInfo)inv2info.get(inv); 120 witchel 1.1.2.4 if(trace >= TRACE_FUNCTION) { 121 witchel 1.1.2.4 psout.print("a" + arg_idx + " " 122 witchel 1.1.2.4 + (REGSIZE*ci.getArg2Word(arg_idx)) + "(sp)"); 123 witchel 1.1.2.4 } 124 witchel 1.1.2.1 return REGSIZE * ci.getArg2Word(arg_idx); 125 witchel 1.1.2.1 } 126 witchel 1.1.2.1 /** 127 witchel 1.1.2.1 * Give a higher offset. If you are big endian, this is the least 128 witchel 1.1.2.1 * signifigant word. 129 witchel 1.1.2.1 */ 130 witchel 1.1.2.2 public int argSecondOffset(Object inv, int arg_idx) { 131 witchel 1.1.2.1 CallInfo ci = (CallInfo)inv2info.get(inv); 132 witchel 1.1.2.4 if(trace >= TRACE_FUNCTION) { 133 witchel 1.1.2.4 psout.print("alow" + arg_idx + " " 134 witchel 1.1.2.4 + (REGSIZE*(ci.getArg2Word(arg_idx)+1)) + "(sp)"); 135 witchel 1.1.2.4 } 136 cananian 1.3.2.1 assert ci.getArg2Word(arg_idx) + 1 < ci.getArg2Word(arg_idx + 1); 137 witchel 1.1.2.1 return REGSIZE * (ci.getArg2Word(arg_idx) + 1); 138 witchel 1.1.2.1 } 139 witchel 1.1.2.1 /** 140 witchel 1.1.2.1 * Call this to find out if a given argument is to be passed in a 141 witchel 1.1.2.1 * register, on the stack, or (for multi-word temporaries) split 142 witchel 1.1.2.1 * between register and stack. 143 witchel 1.1.2.1 */ 144 witchel 1.1.2.2 public int argWhere(Object inv, int arg_idx) { 145 witchel 1.1.2.1 CallInfo ci = (CallInfo)inv2info.get(inv); 146 witchel 1.1.2.4 if(trace >= TRACE_FUNCTION) { 147 witchel 1.1.2.4 psout.print("WHERE "); 148 witchel 1.1.2.2 if(inv instanceof INVOCATION) { 149 witchel 1.1.2.2 print(psout, (INVOCATION)inv); 150 witchel 1.1.2.2 } else { 151 cananian 1.3.2.1 assert inv instanceof METHOD; 152 witchel 1.1.2.2 print(psout, (METHOD)inv); 153 witchel 1.1.2.2 } 154 witchel 1.1.2.1 ci.print(psout); 155 witchel 1.1.2.1 psout.print("a" + arg_idx); 156 witchel 1.1.2.1 } 157 witchel 1.1.2.1 if(ci.getArg2Word(arg_idx) < NARGREGS) { 158 witchel 1.1.2.4 if(trace >= TRACE_FUNCTION) psout.println(" REG"); 159 witchel 1.1.2.1 return REGISTER; 160 witchel 1.1.2.1 } 161 witchel 1.1.2.4 if(trace >= TRACE_FUNCTION) psout.println(" STK"); 162 witchel 1.1.2.1 return STACK; 163 witchel 1.1.2.1 } 164 witchel 1.1.2.4 private int argWhereInternal(Object inv, int arg_idx) { 165 witchel 1.1.2.4 int old_trace = trace; 166 witchel 1.1.2.4 int ret; 167 witchel 1.1.2.4 trace = TRACE_NONE; 168 witchel 1.1.2.4 ret = argWhere(inv, arg_idx); 169 witchel 1.1.2.4 trace = old_trace; 170 witchel 1.1.2.4 return ret; 171 witchel 1.1.2.4 } 172 witchel 1.1.2.2 173 witchel 1.1.2.1 /** 174 witchel 1.1.2.1 * Return which argument register this argument goes in 175 witchel 1.1.2.1 */ 176 witchel 1.1.2.2 public Temp argReg(Object inv, int arg_idx) { 177 cananian 1.3.2.1 assert argWhereInternal(inv, arg_idx) == REGISTER; 178 witchel 1.1.2.1 CallInfo ci = (CallInfo)inv2info.get(inv); 179 witchel 1.1.2.1 return idx2ArgReg(ci.getArg2Word(arg_idx)); 180 witchel 1.1.2.1 } 181 witchel 1.1.2.1 /** 182 witchel 1.1.2.1 * Return the second argument register for a two word temporary. 183 witchel 1.1.2.1 */ 184 witchel 1.1.2.2 public Temp argSecondReg(Object inv, int arg_idx) { 185 cananian 1.3.2.1 assert argWhereInternal(inv, arg_idx) == REGISTER; 186 witchel 1.1.2.1 CallInfo ci = (CallInfo)inv2info.get(inv); 187 cananian 1.3.2.1 assert ci.getArg2Word(arg_idx) + 1 < ci.getArg2Word(arg_idx + 1); 188 witchel 1.1.2.1 return idx2ArgReg(ci.getArg2Word(arg_idx) + 1); 189 witchel 1.1.2.1 } 190 witchel 1.1.2.1 191 witchel 1.1.2.1 /** 192 witchel 1.1.2.1 * Functions with the <code>regAlloc</code> prefix are functions 193 witchel 1.1.2.1 * that take information about register allocation to fill out our 194 witchel 1.1.2.1 * model of the stack 195 witchel 1.1.2.1 */ 196 witchel 1.1.2.1 197 witchel 1.1.2.1 /** 198 witchel 1.1.2.1 * Give the stack frame model the array of used callee saved 199 witchel 1.1.2.1 * registers. There should be no duplicates, and you probably want 200 witchel 1.1.2.1 * to sort the list (it probably should be a LinearSet) 201 witchel 1.1.2.1 */ 202 witchel 1.1.2.1 public void regAllocUsedRegs(ArrayList used) { 203 witchel 1.1.2.1 callee_regs = new ArrayList(used); 204 witchel 1.1.2.1 callee_regs.retainAll(regfile.calleeSave()); 205 witchel 1.1.2.1 // These are always dealt with, we don't need extra stack space 206 witchel 1.1.2.1 // for them 207 witchel 1.1.2.1 callee_regs.remove(regfile.SP); 208 witchel 1.1.2.1 callee_regs.remove(regfile.FP); 209 witchel 1.1.2.1 callee_done = true; 210 witchel 1.1.2.1 } 211 witchel 1.1.2.1 /** 212 witchel 1.1.2.1 * Return how many callee saved registers there are for this frame 213 witchel 1.1.2.1 */ 214 witchel 1.1.2.1 public int calleeSaveTotal() { 215 cananian 1.3.2.1 assert callee_done; 216 witchel 1.1.2.1 return callee_regs.size(); 217 witchel 1.1.2.1 } 218 witchel 1.1.2.1 /** 219 witchel 1.1.2.1 * Return the register for this callee saved register index 220 witchel 1.1.2.1 */ 221 witchel 1.1.2.1 public Temp calleeReg(int callee_idx) { 222 cananian 1.3.2.1 assert callee_done; 223 cananian 1.3.2.1 assert callee_idx < callee_regs.size() && callee_idx >= 0 : "Callee idx=" + callee_idx + " Size=" + callee_regs.size(); 224 witchel 1.1.2.1 return (Temp)callee_regs.get(callee_idx); 225 witchel 1.1.2.1 } 226 witchel 1.1.2.1 /** 227 witchel 1.1.2.1 * Return the offset for a given callee saved register index. 228 witchel 1.1.2.1 */ 229 witchel 1.1.2.1 public int calleeSaveOffset(int callee_idx) { 230 cananian 1.3.2.1 assert callee_done; 231 cananian 1.3.2.1 assert callee_idx < callee_regs.size() && callee_idx >= 0; 232 witchel 1.1.2.5 return frameSize() + fp_off - (REGSIZE * (callee_idx + 1)); 233 witchel 1.1.2.1 } 234 witchel 1.1.2.1 /** 235 witchel 1.1.2.1 * On top (highest address) of the MIPS stack frame are the 236 witchel 1.1.2.1 * locals/temporaries This isn't a 237 witchel 1.1.2.1 * great interface, but it is the info we get from RegAlloc. I 238 witchel 1.1.2.1 * would have expected somethine like an ExpList, just like arguments. 239 witchel 1.1.2.1 */ 240 witchel 1.1.2.1 public void regAllocLocalWords(int w) { 241 witchel 1.1.2.1 locals_done = true; 242 witchel 1.1.2.1 local_words = w; 243 witchel 1.1.2.1 } 244 witchel 1.1.2.1 /** 245 witchel 1.1.2.1 * Return the offset for a given local index 246 witchel 1.1.2.1 */ 247 witchel 1.1.2.1 public int localSaveOffset(int local_idx) { 248 cananian 1.3.2.1 assert callee_done && locals_done; 249 cananian 1.3.2.1 assert local_idx < local_words && local_idx >= 0; 250 witchel 1.1.2.5 return frameSize() + fp_off - (REGSIZE * (callee_regs.size() + 1 + 251 witchel 1.1.2.5 local_idx)); 252 witchel 1.1.2.1 } 253 witchel 1.1.2.1 public int getFPOffset() { 254 witchel 1.1.2.1 return frameSize() + fp_off; 255 witchel 1.1.2.1 } 256 witchel 1.1.2.1 public int getRAOffset() { 257 witchel 1.1.2.1 return frameSize() + ra_off; 258 witchel 1.1.2.1 } 259 witchel 1.1.2.1 public int frameSize() { 260 cananian 1.3.2.1 assert locals_done && callee_done; 261 witchel 1.1.2.3 int fs = REGSIZE * (max_arg_words 262 witchel 1.1.2.3 + callee_regs.size() 263 witchel 1.1.2.3 + local_words 264 witchel 1.1.2.3 + fixed_words); 265 witchel 1.1.2.3 if(fs/BYTEALIGNMENT * BYTEALIGNMENT == fs) 266 witchel 1.1.2.3 return fs; 267 witchel 1.1.2.3 else 268 witchel 1.1.2.3 return (fs/BYTEALIGNMENT + 1) * BYTEALIGNMENT; 269 witchel 1.1.2.1 } 270 witchel 1.1.2.1 271 witchel 1.1.2.1 /** 272 witchel 1.1.2.1 * Call <code>callInfo</code> with the destination label and argument list 273 witchel 1.1.2.1 * for all calls made by this activation frame. The stack then 274 witchel 1.1.2.1 * knows about every function it has to call. 275 witchel 1.1.2.1 */ 276 witchel 1.1.2.1 public void callInfo(INVOCATION inv) { 277 witchel 1.1.2.1 ExpList elist = inv.getArgs(); 278 witchel 1.1.2.1 int words = 0; 279 witchel 1.1.2.1 CallInfo ci = new CallInfo(); 280 witchel 1.1.2.1 int narg = 0; 281 witchel 1.1.2.4 if(trace >= TRACE_INTERNAL_CALLS) { 282 witchel 1.1.2.1 print(psout, inv); 283 witchel 1.1.2.1 } 284 witchel 1.1.2.1 for(; elist != null; ++narg, elist = elist.tail) { 285 witchel 1.1.2.1 // Like gcc we don't break doubles into one 286 witchel 1.1.2.1 // register and one stack word 287 witchel 1.1.2.1 if(words == NARGREGS - 1 && nWords(elist.head) == 2) { 288 witchel 1.1.2.1 words ++; 289 witchel 1.1.2.1 } 290 witchel 1.1.2.1 ci.setArg2Word(narg, words); 291 witchel 1.1.2.4 if(trace >= TRACE_INTERNAL_CALLS) { 292 witchel 1.1.2.1 psout.print(" a" + narg + "=" + words); 293 witchel 1.1.2.1 } 294 witchel 1.1.2.1 words += nWords(elist.head); 295 witchel 1.1.2.1 } 296 witchel 1.1.2.1 // Set the value after the last entry so we know the total number 297 witchel 1.1.2.1 ci.setArg2Word(narg, words); 298 witchel 1.1.2.4 if(trace >= TRACE_INTERNAL_CALLS) { 299 witchel 1.1.2.1 psout.print(" a" + narg + "=" + words); 300 witchel 1.1.2.1 psout.println(" END"); 301 witchel 1.1.2.1 } 302 witchel 1.1.2.1 // XXX is this right? If we need any params, leave at least 16 bytes. 303 witchel 1.1.2.4 // If this is the largest call we have seen, then increase max_arg_words 304 witchel 1.1.2.4 if(words > max_arg_words) 305 witchel 1.1.2.1 if(words < 4) 306 witchel 1.1.2.1 max_arg_words = 4; 307 witchel 1.1.2.1 else 308 witchel 1.1.2.1 max_arg_words = words; 309 witchel 1.1.2.1 inv2info.put(inv, ci); 310 witchel 1.1.2.1 } 311 witchel 1.1.2.2 /** 312 witchel 1.1.2.2 * For callee argument information call <code>callInfo</code> with 313 witchel 1.1.2.2 * METHOD object, and we will interpret the parameter list. 314 witchel 1.1.2.2 */ 315 witchel 1.1.2.2 public void callInfo(METHOD meth) { 316 witchel 1.1.2.2 // This code duplicates the algorithm from the INVOCATION 317 witchel 1.1.2.2 // version which annoys me, but merging them would also be 318 witchel 1.1.2.2 // annoying because of the differences between INVOCATION and 319 witchel 1.1.2.2 // METHOD 320 witchel 1.1.2.2 CallInfo ci = new CallInfo(); 321 witchel 1.1.2.2 int words = 0; 322 witchel 1.1.2.4 if(trace >= TRACE_INTERNAL_CALLS) { 323 witchel 1.1.2.2 print(psout, meth); 324 witchel 1.1.2.2 } 325 witchel 1.1.2.2 // skip param[0], which is the explicit 'exceptional return 326 witchel 1.1.2.2 // address' 327 witchel 1.1.2.2 int narg = 0; 328 witchel 1.1.2.2 for(int param_narg = 1; param_narg < meth.getParamsLength(); 329 witchel 1.1.2.2 ++param_narg) { 330 witchel 1.1.2.2 // Like gcc we don't break doubles into one 331 witchel 1.1.2.2 // register and one stack word 332 witchel 1.1.2.2 if(words == NARGREGS - 1 333 witchel 1.1.2.2 && nWords(meth.getParams(param_narg)) == 2) { 334 witchel 1.1.2.2 words ++; 335 witchel 1.1.2.2 } 336 witchel 1.1.2.2 ci.setArg2Word(narg, words); 337 witchel 1.1.2.4 if(trace >= TRACE_INTERNAL_CALLS) { 338 witchel 1.1.2.2 psout.print(" Ma" + narg + "=" + words); 339 witchel 1.1.2.2 } 340 witchel 1.1.2.2 words += nWords(meth.getParams(param_narg)); 341 witchel 1.1.2.2 narg++; 342 witchel 1.1.2.2 } 343 witchel 1.1.2.2 // Set the value after the last entry so we know the total number 344 witchel 1.1.2.2 ci.setArg2Word(narg, words); 345 witchel 1.1.2.4 if(trace >= TRACE_INTERNAL_CALLS) { 346 witchel 1.1.2.2 psout.print(" Ma" + narg + "=" + words); 347 witchel 1.1.2.2 psout.println(" MEND"); 348 witchel 1.1.2.2 } 349 witchel 1.1.2.2 inv2info.put(meth, ci); 350 witchel 1.1.2.2 } 351 witchel 1.1.2.2 352 witchel 1.1.2.1 353 witchel 1.1.2.1 private final int NARGREGS = 4; // how many arg regs 354 witchel 1.1.2.1 private final int REGSIZE = 4; // bytes per reg 355 witchel 1.1.2.1 private final int ra_off = -4; 356 witchel 1.1.2.1 private final int fp_off = -8; 357 witchel 1.1.2.1 358 witchel 1.1.2.1 private int max_arg_words; 359 witchel 1.1.2.1 private HashMap inv2info; 360 witchel 1.1.2.1 private RegFileInfo regfile; 361 witchel 1.1.2.1 private boolean locals_done; 362 witchel 1.1.2.1 private int local_words; 363 witchel 1.1.2.1 private boolean callee_done; 364 witchel 1.1.2.4 private final int TRACE_NONE = 0; 365 witchel 1.1.2.4 private final int TRACE_FUNCTION = 1; 366 witchel 1.1.2.4 private final int TRACE_INTERNAL_CALLS = 2; 367 witchel 1.1.2.4 private int trace = TRACE_NONE; 368 witchel 1.1.2.1 private final PrintStream psout = System.out; 369 witchel 1.1.2.1 private ArrayList callee_regs; 370 witchel 1.1.2.1 private int fixed_words; 371 witchel 1.1.2.1 private void print(PrintStream ps, INVOCATION inv) { 372 witchel 1.1.2.1 if(inv.getFunc() instanceof NAME) 373 witchel 1.1.2.1 ps.print("func=" + (NAME)inv.getFunc()); 374 witchel 1.1.2.1 else if(inv.getFunc() instanceof MEM) 375 witchel 1.1.2.1 ps.print("func=" + (MEM)inv.getFunc()); 376 witchel 1.1.2.1 else 377 witchel 1.1.2.1 ps.print("Ufunc=" + inv.getFunc()); 378 witchel 1.1.2.2 } 379 witchel 1.1.2.2 private void print(PrintStream ps, METHOD meth) { 380 witchel 1.1.2.2 ps.print("meth=" + meth.toString()); 381 witchel 1.1.2.1 } 382 witchel 1.1.2.1 383 witchel 1.1.2.1 private Temp idx2ArgReg(int idx) { 384 cananian 1.3.2.1 assert idx < NARGREGS; 385 witchel 1.1.2.1 switch(idx) { 386 witchel 1.1.2.1 case 0: return regfile.A0; 387 witchel 1.1.2.1 case 1: return regfile.A1; 388 witchel 1.1.2.1 case 2: return regfile.A2; 389 witchel 1.1.2.1 case 3: return regfile.A3; 390 witchel 1.1.2.1 } 391 cananian 1.3.2.1 assert false; 392 witchel 1.1.2.1 return null; 393 witchel 1.1.2.1 } 394 witchel 1.1.2.1 private int nWords(Typed ty) { 395 witchel 1.1.2.1 switch (ty.type()) { 396 witchel 1.1.2.1 case Type.LONG: case Type.DOUBLE: return 2; 397 witchel 1.1.2.1 default: return 1; 398 witchel 1.1.2.1 } 399 witchel 1.1.2.1 } 400 cananian 1.2 }