1 kkz 1.1.2.1 // DataGC.java, created Thu Jan 13 20:55:26 2000 by kkz 2 cananian 1.1.2.15 // Copyright (C) 1999 Karen K. Zee <kkz@alum.mit.edu> 3 kkz 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 kkz 1.1.2.1 package harpoon.Backend.Runtime1; 5 kkz 1.1.2.1 6 kkz 1.1.2.3 import harpoon.Analysis.Maps.Derivation; 7 kkz 1.1.2.1 import harpoon.Backend.Generic.Frame; 8 kkz 1.1.2.1 import harpoon.Backend.Generic.GCInfo; 9 kkz 1.1.2.6 import harpoon.Backend.Generic.GCInfo.DLoc; 10 kkz 1.1.2.1 import harpoon.Backend.Generic.GCInfo.GCPoint; 11 kkz 1.1.2.11 import harpoon.Backend.Generic.GCInfo.WrappedMachineRegLoc; 12 kkz 1.1.2.11 import harpoon.Backend.Generic.GCInfo.WrappedStackOffsetLoc; 13 kkz 1.1.2.3 import harpoon.Backend.Generic.RegFileInfo.CommonLoc; 14 kkz 1.1.2.1 import harpoon.Backend.Generic.RegFileInfo.MachineRegLoc; 15 kkz 1.1.2.2 import harpoon.Backend.Generic.RegFileInfo.StackOffsetLoc; 16 kkz 1.1.2.10 import harpoon.Backend.Maps.BackendDerivation; 17 kkz 1.1.2.1 import harpoon.Backend.Maps.NameMap; 18 kkz 1.1.2.1 import harpoon.ClassFile.HClass; 19 kkz 1.1.2.1 import harpoon.ClassFile.HDataElement; 20 kkz 1.1.2.1 import harpoon.ClassFile.HMethod; 21 kkz 1.1.2.1 import harpoon.IR.Tree.ALIGN; 22 kkz 1.1.2.1 import harpoon.IR.Tree.CONST; 23 kkz 1.1.2.1 import harpoon.IR.Tree.LABEL; 24 kkz 1.1.2.1 import harpoon.IR.Tree.SEGMENT; 25 kkz 1.1.2.1 import harpoon.IR.Tree.Stm; 26 kkz 1.1.2.2 import harpoon.Temp.Label; 27 kkz 1.1.2.1 import harpoon.Util.Util; 28 kkz 1.1.2.1 29 kkz 1.1.2.1 import java.util.ArrayList; 30 kkz 1.1.2.1 import java.util.Arrays; 31 kkz 1.1.2.1 import java.util.List; 32 kkz 1.1.2.2 import java.util.HashMap; 33 kkz 1.1.2.2 import java.util.HashSet; 34 kkz 1.1.2.1 import java.util.Iterator; 35 kkz 1.1.2.1 import java.util.Map; 36 kkz 1.1.2.1 import java.util.Set; 37 kkz 1.1.2.1 import java.util.TreeSet; 38 kkz 1.1.2.1 39 kkz 1.1.2.1 /** 40 kkz 1.1.2.1 * <code>DataGC</code> outputs the tables needed by the garbage collector. 41 kkz 1.1.2.1 * 42 cananian 1.1.2.15 * @author Karen K. Zee <kkz@alum.mit.edu> 43 cananian 1.6 * @version $Id: DataGC.java,v 1.6 2004/02/08 03:20:58 cananian Exp $ 44 kkz 1.1.2.1 */ 45 kkz 1.1.2.1 public class DataGC extends Data { 46 kkz 1.1.2.3 final GCInfo m_gc; 47 kkz 1.1.2.3 final NameMap m_nm; 48 kkz 1.1.2.3 final TreeBuilder m_tb; 49 kkz 1.1.2.6 final int numRegs; 50 cananian 1.5 final boolean pointersAreLong; 51 kkz 1.1.2.1 52 kkz 1.1.2.6 // number of bits in a 32-bit int 53 kkz 1.1.2.6 final int INT_BITS = 32; 54 kkz 1.1.2.6 // size of descriptor in bits 55 kkz 1.1.2.9 final int DESC_BITS = 8; 56 kkz 1.1.2.6 57 kkz 1.1.2.1 /** Creates a <code>DataGC</code>. */ 58 kkz 1.1.2.6 public DataGC(Frame f, HClass hc) { 59 kkz 1.1.2.1 super("gc-data", hc, f); 60 cananian 1.3.2.1 assert f.getGCInfo() != null; 61 kkz 1.1.2.3 this.m_gc = f.getGCInfo(); 62 cananian 1.1.2.16 this.m_nm = f.getRuntime().getNameMap(); 63 cananian 1.1.2.16 this.m_tb = (TreeBuilder) f.getRuntime().getTreeBuilder(); 64 kkz 1.1.2.6 this.numRegs = f.getRegFileInfo().maxRegIndex(); 65 cananian 1.5 this.pointersAreLong = f.pointersAreLong(); 66 kkz 1.1.2.6 this.root = build(); 67 kkz 1.1.2.1 } 68 kkz 1.1.2.6 69 kkz 1.1.2.6 private HDataElement build() { 70 kkz 1.1.2.11 final List stmlist = new ArrayList(); 71 kkz 1.1.2.7 // handle only methods that we've had to generate 72 kkz 1.1.2.7 // GCInfo for and do so in the order saved by GCInfo 73 kkz 1.1.2.11 final List methods = m_gc.getOrderedMethods(hc); 74 kkz 1.1.2.7 if (methods == null) return null; 75 kkz 1.1.2.11 report(methods.toString()); 76 kkz 1.1.2.6 // switch to the GC segment 77 kkz 1.1.2.1 stmlist.add(new SEGMENT(tf, null, SEGMENT.GC)); 78 kkz 1.1.2.6 // align on word-boundary 79 cananian 1.5 stmlist.add(new ALIGN(tf, null, pointersAreLong ? 8 : 4)); 80 kkz 1.1.2.11 for (Iterator it=methods.iterator(); it.hasNext(); ) { 81 kkz 1.1.2.11 Stm output = outputGCData((HMethod)it.next()); 82 kkz 1.1.2.11 if (output != null) 83 kkz 1.1.2.11 stmlist.add(output); 84 kkz 1.1.2.11 } 85 kkz 1.1.2.1 return (HDataElement) Stm.toStm(stmlist); 86 kkz 1.1.2.1 } 87 kkz 1.1.2.6 88 kkz 1.1.2.6 // requires: method for which GC points have been calculated 89 kkz 1.1.2.6 // modifies: basetableMap 90 kkz 1.1.2.6 // effects: returns statements for outputting base table and 91 kkz 1.1.2.6 // puts numeric mapping of stackOffsetLocs into the 92 kkz 1.1.2.6 // basetableMap 93 kkz 1.1.2.6 private Stm outputBaseTable(HMethod hm) { 94 kkz 1.1.2.6 // get ordered list of GC points for this method 95 kkz 1.1.2.3 List gcps = m_gc.gcPoints(hm); 96 kkz 1.1.2.6 // make sure the list is non-null 97 cananian 1.3.2.1 assert gcps != null; 98 kkz 1.1.2.6 // first create base table for stack locations 99 kkz 1.1.2.6 Set basetableSet = new HashSet(); 100 kkz 1.1.2.11 // take union of live WrappedStackOffsetLocs for all GC points 101 kkz 1.1.2.6 for(Iterator it = gcps.iterator(); it.hasNext(); ) 102 kkz 1.1.2.6 basetableSet.addAll(((GCPoint)it.next()).liveStackOffsetLocs()); 103 kkz 1.1.2.6 // make statements 104 kkz 1.1.2.6 List stmlist = new ArrayList(basetableSet.size()+2); 105 kkz 1.1.2.6 // label base table location 106 kkz 1.1.2.6 stmlist.add(new LABEL(tf, null, m_nm.label(hm, "gc_bt"), true)); 107 kkz 1.1.2.6 // number of entries in base table (int) 108 kkz 1.1.2.6 stmlist.add(_DATUM(new CONST(tf, null, basetableSet.size()))); 109 kkz 1.1.2.6 report("Size of base table = " + basetableSet.size()); 110 kkz 1.1.2.6 // clear basetableMap 111 kkz 1.1.2.11 basetableMap = new HashMap(); int i = 0; 112 kkz 1.1.2.11 for(Iterator btIt = basetableSet.iterator(); 113 kkz 1.1.2.11 btIt.hasNext(); ) { 114 kkz 1.1.2.11 // put new entries into basetableMap 115 kkz 1.1.2.11 WrappedStackOffsetLoc wsol = (WrappedStackOffsetLoc)btIt.next(); 116 kkz 1.1.2.6 // output stackOffset (int) 117 kkz 1.1.2.11 stmlist.add(_DATUM(new CONST(tf, null, wsol.stackOffset()))); 118 kkz 1.1.2.11 report("Base table entry: " + wsol.stackOffset()); 119 kkz 1.1.2.11 basetableMap.put(wsol, new Integer(i++)); 120 kkz 1.1.2.2 } 121 kkz 1.1.2.6 return Stm.toStm(stmlist); 122 kkz 1.1.2.6 } 123 kkz 1.1.2.6 private Map basetableMap; 124 kkz 1.1.2.6 125 kkz 1.1.2.6 private Stm outputGCData(HMethod hm) { 126 kkz 1.1.2.11 // get ordered list of GC points for this method 127 kkz 1.1.2.11 final List gcps = m_gc.gcPoints(hm); 128 kkz 1.1.2.11 if (gcps.isEmpty()) return null; 129 kkz 1.1.2.11 final List stmlist = new ArrayList(); 130 kkz 1.1.2.6 // make base table for method 131 kkz 1.1.2.6 stmlist.add(outputBaseTable(hm)); 132 kkz 1.1.2.11 GCPoint prev = null; int i = 0; 133 kkz 1.1.2.6 // make entry for each GC point 134 cananian 1.6 for(Object gcpO : gcps) { 135 cananian 1.6 GCPoint gcp = (GCPoint) gcpO; 136 kkz 1.1.2.6 // add index entry to GC_INDEX segment 137 kkz 1.1.2.6 stmlist.add(new SEGMENT(tf, null, SEGMENT.GC_INDEX)); 138 kkz 1.1.2.6 // location of GC point 139 kkz 1.1.2.11 stmlist.add(_DATUM(gcp.label())); 140 kkz 1.1.2.6 // location of GC data 141 kkz 1.1.2.6 stmlist.add(_DATUM(m_nm.label(hm, "gcp_index_"+i))); 142 kkz 1.1.2.6 // location of GC base table 143 kkz 1.1.2.11 // stmlist.add(_DATUM(m_nm.label(hm, "gc_bt"))); 144 kkz 1.1.2.6 // add data entry to GC segment 145 kkz 1.1.2.6 stmlist.add(new SEGMENT(tf, null, SEGMENT.GC)); 146 kkz 1.1.2.6 // align on word boundary 147 cananian 1.5 stmlist.add(new ALIGN(tf, null, pointersAreLong ? 8 : 4)); 148 kkz 1.1.2.6 // label GC data 149 kkz 1.1.2.6 stmlist.add(new LABEL(tf, null, m_nm.label(hm, "gcp_index_"+i), 150 kkz 1.1.2.6 true)); 151 kkz 1.1.2.6 // output actual data 152 kkz 1.1.2.11 stmlist.add(outputGCPoint(gcp, prev)); 153 kkz 1.1.2.11 // setup for next 154 kkz 1.1.2.11 prev = gcp; i++; 155 kkz 1.1.2.2 } 156 kkz 1.1.2.11 //System.out.println(i+" GC points in "+hm); 157 kkz 1.1.2.6 return Stm.toStm(stmlist); 158 kkz 1.1.2.6 } 159 kkz 1.1.2.6 160 kkz 1.1.2.11 // octal 161 kkz 1.1.2.11 final int NO_LIVE_REGISTERS = 01; 162 kkz 1.1.2.11 final int NO_CHANGE_IN_REGISTERS = 02; 163 kkz 1.1.2.11 final int NO_LIVE_STACK_LOCATIONS = 04; 164 kkz 1.1.2.11 final int NO_CHANGE_IN_STACK_LOCATIONS = 010; 165 kkz 1.1.2.11 final int NO_LIVE_DERIVED_POINTERS = 020; 166 kkz 1.1.2.11 final int NO_CHANGE_IN_DERIVED_POINTERS = 040; 167 kkz 1.1.2.11 final int NO_LIVE_CALLEE_SAVED_REGISTERS = 0100; 168 kkz 1.1.2.11 final int NO_CHANGE_IN_CALLEE_SAVED_REGISTERS = 0200; 169 kkz 1.1.2.11 final int DESCRIPTOR_SIZE = 8; // in bits 170 kkz 1.1.2.6 // requires: current and previous GC point 171 kkz 1.1.2.6 // modifies: nil 172 kkz 1.1.2.6 // effects: returns statements for outputting data relevant 173 kkz 1.1.2.6 // to current GC point 174 kkz 1.1.2.6 private Stm outputGCPoint(GCPoint curr, GCPoint prev) { 175 kkz 1.1.2.6 // output format: bits 31-26 -- descriptor 176 kkz 1.1.2.6 int output = 0; 177 kkz 1.1.2.11 boolean outputRegisters = true; 178 kkz 1.1.2.11 final Set registers = curr.liveMachineRegLocs(); 179 kkz 1.1.2.11 if (registers.isEmpty()) { 180 kkz 1.1.2.11 output |= NO_LIVE_REGISTERS; outputRegisters = false; 181 kkz 1.1.2.6 } else if (prev != null && 182 kkz 1.1.2.11 registers.equals(prev.liveMachineRegLocs())) { 183 kkz 1.1.2.11 output |= NO_CHANGE_IN_REGISTERS; outputRegisters = false; 184 kkz 1.1.2.2 } 185 kkz 1.1.2.6 boolean needStack = true; 186 kkz 1.1.2.6 Set stack = curr.liveStackOffsetLocs(); 187 kkz 1.1.2.6 if (stack.isEmpty()) { 188 kkz 1.1.2.11 output |= NO_LIVE_STACK_LOCATIONS; 189 kkz 1.1.2.6 needStack = false; 190 kkz 1.1.2.6 } else if (prev != null && 191 kkz 1.1.2.6 stack.equals(prev.liveStackOffsetLocs())) { 192 kkz 1.1.2.11 output |= NO_CHANGE_IN_STACK_LOCATIONS; 193 kkz 1.1.2.1 needStack = false; 194 kkz 1.1.2.1 } 195 kkz 1.1.2.6 boolean needDerivs = true; 196 kkz 1.1.2.8 Map regDerivs = curr.regDerivations(); 197 kkz 1.1.2.8 Map stackDerivs = curr.stackDerivations(); 198 kkz 1.1.2.8 if (regDerivs.isEmpty() && stackDerivs.isEmpty()) { 199 kkz 1.1.2.11 output |= NO_LIVE_DERIVED_POINTERS; 200 kkz 1.1.2.6 needDerivs = false; 201 kkz 1.1.2.6 } else if (prev != null && 202 kkz 1.1.2.8 regDerivs.equals(prev.regDerivations()) && 203 kkz 1.1.2.8 stackDerivs.equals(prev.stackDerivations())) { 204 kkz 1.1.2.11 output |= NO_CHANGE_IN_DERIVED_POINTERS; 205 kkz 1.1.2.6 needDerivs = false; 206 kkz 1.1.2.6 } 207 kkz 1.1.2.9 // handle callee-saved registers 208 kkz 1.1.2.9 boolean needCSaved = true; 209 kkz 1.1.2.10 Map cSaved = curr.calleeSaved(); 210 kkz 1.1.2.10 if (cSaved.isEmpty()) { 211 kkz 1.1.2.11 output |= NO_LIVE_CALLEE_SAVED_REGISTERS; 212 kkz 1.1.2.9 needCSaved = false; 213 kkz 1.1.2.10 } else if (prev != null && cSaved.equals(prev.calleeSaved())) { 214 kkz 1.1.2.11 output |= NO_CHANGE_IN_CALLEE_SAVED_REGISTERS; 215 kkz 1.1.2.9 needCSaved = false; 216 kkz 1.1.2.9 } 217 kkz 1.1.2.6 List stmlist = new ArrayList(); 218 kkz 1.1.2.11 if (!outputRegisters && !needStack) 219 kkz 1.1.2.6 // output descriptor (int) 220 kkz 1.1.2.6 stmlist.add(_DATUM(new CONST(tf, null, output))); 221 kkz 1.1.2.6 else 222 kkz 1.1.2.6 // handle both registers and stack together to save bits 223 kkz 1.1.2.11 stmlist.add(outputRS(outputRegisters, needStack, 224 kkz 1.1.2.11 registers, stack, output)); 225 kkz 1.1.2.6 if (needDerivs) 226 kkz 1.1.2.8 stmlist.add(outputDerivs(regDerivs, stackDerivs)); 227 kkz 1.1.2.9 if (needCSaved) 228 kkz 1.1.2.9 stmlist.add(outputCSaved(cSaved)); 229 kkz 1.1.2.1 return Stm.toStm(stmlist); 230 kkz 1.1.2.11 } // outputGCPoint 231 kkz 1.1.2.6 232 kkz 1.1.2.10 // requires: descriptor set in output 233 kkz 1.1.2.6 // modifies: nil 234 kkz 1.1.2.10 // effects: returns statements that output descriptor 235 kkz 1.1.2.6 // plus register data (if needed) and stack data 236 kkz 1.1.2.6 // (if needed) 237 kkz 1.1.2.6 private Stm outputRS(boolean needRegs, boolean needStack, 238 kkz 1.1.2.6 Set regs, Set stack, int output) 239 kkz 1.1.2.6 { 240 kkz 1.1.2.10 // number of bits needed to store the descriptor, 241 kkz 1.1.2.6 // the register bitmap and the stack bitmap 242 kkz 1.1.2.11 final int bits = DESCRIPTOR_SIZE + 243 kkz 1.1.2.13 (needRegs?numRegs:0) + (needStack?basetableMap.size():0); 244 kkz 1.1.2.6 // number of 32-bit integers needed to encode the data 245 kkz 1.1.2.6 final int numInts = (bits + INT_BITS - 1) / INT_BITS; 246 kkz 1.1.2.6 int[] data = new int[numInts]; 247 kkz 1.1.2.10 // remember the descriptor 248 kkz 1.1.2.11 int offset = DESCRIPTOR_SIZE; 249 kkz 1.1.2.10 // get descriptor from output 250 kkz 1.1.2.6 data[0] = output; 251 kkz 1.1.2.6 // do registers first 252 kkz 1.1.2.6 if (needRegs) { 253 kkz 1.1.2.6 for(Iterator it=regs.iterator(); it.hasNext(); ) { 254 kkz 1.1.2.12 int regIndex = ((WrappedMachineRegLoc)it.next()).regIndex(); 255 cananian 1.3.2.1 assert regIndex < numRegs; 256 kkz 1.1.2.6 int i = (regIndex+offset) / INT_BITS; 257 kkz 1.1.2.6 int j = (regIndex+offset) % INT_BITS; 258 cananian 1.3.2.1 assert i < numInts; 259 kkz 1.1.2.6 data[i] |= 1 << (INT_BITS - j - 1); 260 kkz 1.1.2.6 } 261 kkz 1.1.2.6 offset += numRegs; 262 kkz 1.1.2.1 } 263 kkz 1.1.2.6 if (needStack) { 264 kkz 1.1.2.6 for(Iterator it=stack.iterator(); it.hasNext(); ) { 265 kkz 1.1.2.6 int index = ((Integer)basetableMap.get(it.next())).intValue(); 266 kkz 1.1.2.6 int i = (index+offset) / INT_BITS; 267 kkz 1.1.2.6 int j = (index+offset) % INT_BITS; 268 cananian 1.3.2.1 assert i < numInts; 269 kkz 1.1.2.6 data[i] |= 1 << (INT_BITS - j - 1); 270 kkz 1.1.2.6 } 271 kkz 1.1.2.1 } 272 kkz 1.1.2.6 // output accumulated data 273 kkz 1.1.2.2 List stmlist = new ArrayList(); 274 kkz 1.1.2.6 for(int k=0; k < numInts; k++) 275 kkz 1.1.2.2 stmlist.add(_DATUM(new CONST(tf, null, data[k]))); 276 kkz 1.1.2.3 return Stm.toStm(stmlist); 277 kkz 1.1.2.3 } 278 kkz 1.1.2.6 279 kkz 1.1.2.6 // effects: returns statements that output the derivation data 280 kkz 1.1.2.8 private Stm outputDerivs(Map regDerivs, Map stackDerivs) { 281 kkz 1.1.2.3 List stmlist = new ArrayList(); 282 kkz 1.1.2.8 // number of derived pointers in registers 283 kkz 1.1.2.8 stmlist.add(_DATUM(new CONST(tf, null, regDerivs.size()))); 284 kkz 1.1.2.8 // number of derived pointers in stack 285 kkz 1.1.2.8 stmlist.add(_DATUM(new CONST(tf, null, stackDerivs.size()))); 286 kkz 1.1.2.8 // handle derived pointers in registers 287 cananian 1.6 for(Object keyO : regDerivs.keySet()) { 288 cananian 1.6 WrappedMachineRegLoc key = (WrappedMachineRegLoc) keyO; 289 kkz 1.1.2.8 // location of derived pointer (int) 290 kkz 1.1.2.8 stmlist.add(_DATUM(new CONST(tf, null, key.regIndex()))); 291 kkz 1.1.2.8 // derivation information 292 kkz 1.1.2.8 stmlist.add(outputDLoc((GCInfo.DLoc)regDerivs.get(key))); 293 kkz 1.1.2.8 } 294 kkz 1.1.2.8 // handle derived pointers in stack 295 cananian 1.6 for (Object keyO : stackDerivs.keySet()) { 296 cananian 1.6 WrappedStackOffsetLoc key = (WrappedStackOffsetLoc) keyO; 297 kkz 1.1.2.8 // location of derived pointer (int) 298 kkz 1.1.2.8 stmlist.add(_DATUM(new CONST(tf, null, key.stackOffset()))); 299 kkz 1.1.2.8 // derivation information 300 kkz 1.1.2.8 stmlist.add(outputDLoc((GCInfo.DLoc)stackDerivs.get(key))); 301 kkz 1.1.2.8 } 302 kkz 1.1.2.8 return Stm.toStm(stmlist); 303 kkz 1.1.2.8 } 304 kkz 1.1.2.8 private Stm outputDLoc(GCInfo.DLoc dl) { 305 kkz 1.1.2.8 List stmlist = new ArrayList(); 306 kkz 1.1.2.8 // number of base pointers total 307 kkz 1.1.2.8 stmlist.add(_DATUM(new CONST(tf, null, (dl.stackLocs.length + 308 kkz 1.1.2.8 dl.regLocs.length)))); 309 kkz 1.1.2.8 // register bits are laid out in (data, sign) pairs 310 kkz 1.1.2.8 { 311 kkz 1.1.2.8 final int numInts = (2 * numRegs + INT_BITS - 1) / INT_BITS; 312 kkz 1.1.2.8 int[] data = new int[numInts]; 313 kkz 1.1.2.8 for(int index=0; index < dl.regLocs.length; index++) { 314 kkz 1.1.2.8 int regIndex = dl.regLocs[index].regIndex(); 315 kkz 1.1.2.8 int i = (2 * regIndex) / INT_BITS; 316 kkz 1.1.2.8 int j = (2 * regIndex) % INT_BITS; 317 kkz 1.1.2.8 data[i] |= 1 << (INT_BITS - j - 1); 318 kkz 1.1.2.8 data[i] |= 319 kkz 1.1.2.8 (dl.regSigns[index] ? 0 : 1) << (INT_BITS - j - 2); 320 kkz 1.1.2.3 } 321 kkz 1.1.2.8 for(int k=0; k < numInts; k++) 322 kkz 1.1.2.8 stmlist.add(_DATUM(new CONST(tf, null, data[k]))); 323 kkz 1.1.2.8 } 324 kkz 1.1.2.8 // only output if we have non-zero entries 325 kkz 1.1.2.8 if (dl.stackLocs.length != 0) { 326 kkz 1.1.2.8 final int numInts = (dl.stackLocs.length+INT_BITS-1)/INT_BITS; 327 kkz 1.1.2.8 int[] sign = new int[numInts]; 328 kkz 1.1.2.8 for(int index=0; index < dl.stackLocs.length; index++) { 329 kkz 1.1.2.8 int stackOffset = dl.stackLocs[index].stackOffset(); 330 kkz 1.1.2.8 stmlist.add(_DATUM(new CONST(tf, null, stackOffset))); 331 kkz 1.1.2.8 int i = index / INT_BITS; 332 kkz 1.1.2.8 int j = index % INT_BITS; 333 kkz 1.1.2.8 sign[i] |= 334 kkz 1.1.2.8 (dl.stackSigns[index] ? 0 : 1) << (INT_BITS - j - 1); 335 kkz 1.1.2.3 } 336 kkz 1.1.2.8 for(int k=0; k < numInts; k++) 337 kkz 1.1.2.8 stmlist.add(_DATUM(new CONST(tf, null, sign[k]))); 338 kkz 1.1.2.2 } 339 kkz 1.1.2.2 return Stm.toStm(stmlist); 340 kkz 1.1.2.9 } 341 kkz 1.1.2.9 // output information about callee-saved registers 342 kkz 1.1.2.10 private Stm outputCSaved(Map cSaved) { 343 kkz 1.1.2.9 // calculate how many 32-bit ints we need to encode bit field 344 kkz 1.1.2.9 final int numInts = (2 * numRegs + INT_BITS - 1) / INT_BITS; 345 kkz 1.1.2.9 int[] bitfield = new int[numInts]; 346 kkz 1.1.2.10 int[] locations = new int[cSaved.size()]; 347 kkz 1.1.2.9 // output a bit field indicating which entries have data 348 kkz 1.1.2.10 // 00, 10 - no data 349 kkz 1.1.2.10 // 01 - register 350 kkz 1.1.2.10 // 11 - stack 351 cananian 1.6 for(Object keyO : cSaved.keySet()) { 352 cananian 1.6 BackendDerivation.Register key = (BackendDerivation.Register) keyO; 353 kkz 1.1.2.10 CommonLoc location = (CommonLoc)cSaved.get(key); 354 kkz 1.1.2.10 // make sure we have a valid register index 355 cananian 1.3.2.1 assert key.regIndex() < numRegs; 356 kkz 1.1.2.10 int i = (2 * key.regIndex()) / INT_BITS; 357 kkz 1.1.2.10 int j = (2 * key.regIndex()) % INT_BITS; 358 kkz 1.1.2.10 // set the bit for data/no data 359 kkz 1.1.2.10 bitfield[i] |= 1 << (INT_BITS - j - 2); 360 kkz 1.1.2.10 switch(location.kind()) { 361 kkz 1.1.2.10 case StackOffsetLoc.KIND: 362 kkz 1.1.2.10 // set the bit for stack/register 363 kkz 1.1.2.10 bitfield[i] |= 1 << (INT_BITS - j - 1); 364 kkz 1.1.2.10 locations[key.regIndex()] = 365 kkz 1.1.2.10 ((StackOffsetLoc)location).stackOffset(); break; 366 kkz 1.1.2.10 case MachineRegLoc.KIND: 367 kkz 1.1.2.10 locations[key.regIndex()] = 368 kkz 1.1.2.10 ((MachineRegLoc)location).regIndex(); break; 369 kkz 1.1.2.10 default: 370 cananian 1.3.2.1 assert false; 371 kkz 1.1.2.10 } 372 kkz 1.1.2.9 } 373 kkz 1.1.2.10 List stmlist = new ArrayList(); 374 kkz 1.1.2.9 // dump out bitfield 375 kkz 1.1.2.10 for(int k = 0; k < bitfield.length; k++) 376 kkz 1.1.2.9 stmlist.add(_DATUM(new CONST(tf, null, bitfield[k]))); 377 kkz 1.1.2.10 // dump out register and stack locations 378 kkz 1.1.2.10 for(int k = 0; k < locations.length; k++) 379 kkz 1.1.2.10 stmlist.add(_DATUM(new CONST(tf, null, locations[k]))); 380 kkz 1.1.2.9 return Stm.toStm(stmlist); 381 kkz 1.1.2.1 } 382 kkz 1.1.2.11 final private boolean DEBUG = false; 383 kkz 1.1.2.6 // convenient debugging utility 384 kkz 1.1.2.3 private void report(String str) { 385 kkz 1.1.2.3 if (DEBUG) System.out.println(str); 386 kkz 1.1.2.1 } 387 kkz 1.1.2.1 } 388 kkz 1.1.2.1 389 kkz 1.1.2.1 390 kkz 1.1.2.1 391 kkz 1.1.2.1 392 kkz 1.1.2.1 393 kkz 1.1.2.1 394 kkz 1.1.2.1 395 kkz 1.1.2.1 396 kkz 1.1.2.1 397 kkz 1.1.2.1 398 kkz 1.1.2.1 399 cananian 1.2