1 cananian 1.1.2.22  // ToTree.java, created Tue Feb 16 16:46:36 1999 by duncan
   2 cananian 1.1.2.21  // Copyright (C) 1998 Duncan Bryce <duncan@lcs.mit.edu>
   3 cananian 1.1.2.21  // Licensed under the terms of the GNU GPL; see COPYING for details.
   4 duncan   1.1.2.1   package harpoon.IR.Tree;
   5 duncan   1.1.2.1   
   6 cananian 1.1.2.77  import harpoon.Analysis.AllocationInformationMap.AllocationPropertiesImpl;
   7 cananian 1.1.2.61  import harpoon.Analysis.ReachingDefs;
   8 cananian 1.1.2.65  import harpoon.Analysis.ReachingDefsImpl;
   9 cananian 1.1.2.82  import harpoon.Analysis.SSxReachingDefsImpl;
  10 cananian 1.1.2.76  import harpoon.Analysis.Maps.AllocationInformation;
  11 cananian 1.1.2.76  import harpoon.Analysis.Maps.AllocationInformation.AllocationProperties;
  12 cananian 1.1.2.60  import harpoon.Analysis.Maps.Derivation;
  13 cananian 1.1.2.60  import harpoon.Analysis.Maps.Derivation.DList;
  14 duncan   1.1.2.1   import harpoon.Analysis.Maps.TypeMap;
  15 pnkfelix 1.1.2.86  import harpoon.Analysis.Maps.TypeMap.TypeNotKnownException;
  16 duncan   1.1.2.1   import harpoon.Backend.Generic.Frame;
  17 cananian 1.1.2.50  import harpoon.Backend.Generic.Runtime;
  18 cananian 1.1.2.44  import harpoon.Backend.Maps.NameMap;
  19 duncan   1.1.2.1   import harpoon.ClassFile.HClass;
  20 duncan   1.1.2.1   import harpoon.ClassFile.HCode;
  21 duncan   1.1.2.1   import harpoon.ClassFile.HCodeElement;
  22 duncan   1.1.2.35  import harpoon.ClassFile.HField;
  23 duncan   1.1.2.1   import harpoon.ClassFile.HMethod;
  24 duncan   1.1.2.23  import harpoon.IR.LowQuad.LowQuadFactory;
  25 duncan   1.1.2.1   import harpoon.IR.LowQuad.LowQuadNoSSA;
  26 cananian 1.1.2.81  import harpoon.IR.LowQuad.LowQuadSSA;
  27 cananian 1.1.2.73  import harpoon.IR.LowQuad.LowQuadSSI;
  28 duncan   1.1.2.1   import harpoon.IR.LowQuad.LowQuadVisitor;
  29 duncan   1.1.2.1   import harpoon.IR.LowQuad.LQop;
  30 duncan   1.1.2.1   import harpoon.IR.LowQuad.PAOFFSET;
  31 duncan   1.1.2.1   import harpoon.IR.LowQuad.PARRAY;
  32 duncan   1.1.2.1   import harpoon.IR.LowQuad.PCALL;
  33 duncan   1.1.2.1   import harpoon.IR.LowQuad.PCONST;
  34 duncan   1.1.2.1   import harpoon.IR.LowQuad.PFCONST;
  35 duncan   1.1.2.1   import harpoon.IR.LowQuad.PFIELD;
  36 duncan   1.1.2.1   import harpoon.IR.LowQuad.PFOFFSET;
  37 duncan   1.1.2.1   import harpoon.IR.LowQuad.PGET;
  38 duncan   1.1.2.1   import harpoon.IR.LowQuad.PMCONST;
  39 duncan   1.1.2.1   import harpoon.IR.LowQuad.PMETHOD;
  40 duncan   1.1.2.1   import harpoon.IR.LowQuad.PMOFFSET;
  41 duncan   1.1.2.1   import harpoon.IR.LowQuad.POPER;
  42 duncan   1.1.2.1   import harpoon.IR.LowQuad.PPTR;
  43 duncan   1.1.2.1   import harpoon.IR.LowQuad.PSET;
  44 duncan   1.1.2.1   import harpoon.IR.Quads.Edge;
  45 duncan   1.1.2.1   import harpoon.IR.Quads.Qop;
  46 duncan   1.1.2.1   import harpoon.IR.Quads.Quad;
  47 duncan   1.1.2.23  import harpoon.IR.Quads.QuadFactory;
  48 duncan   1.1.2.23  import harpoon.IR.Quads.QuadKind;
  49 duncan   1.1.2.23  import harpoon.IR.Quads.QuadVisitor;
  50 duncan   1.1.2.1   import harpoon.Temp.CloningTempMap;
  51 duncan   1.1.2.1   import harpoon.Temp.Label;
  52 cananian 1.1.2.84  import harpoon.Temp.LabelList;
  53 duncan   1.1.2.1   import harpoon.Temp.Temp;
  54 duncan   1.1.2.1   import harpoon.Temp.TempFactory;
  55 duncan   1.1.2.1   import harpoon.Temp.TempMap;
  56 cananian 1.8       import net.cscott.jutil.Default;
  57 duncan   1.1.2.34  import harpoon.Util.HClassUtil;
  58 duncan   1.1.2.1   import harpoon.Util.Util;
  59 duncan   1.1.2.1   
  60 duncan   1.1.2.23  import java.util.ArrayList;
  61 duncan   1.1.2.23  import java.util.Arrays;
  62 duncan   1.1.2.35  import java.util.Collections;
  63 duncan   1.1.2.23  import java.util.HashMap;
  64 duncan   1.1.2.23  import java.util.HashSet;
  65 duncan   1.1.2.23  import java.util.Iterator;
  66 duncan   1.1.2.23  import java.util.List;
  67 duncan   1.1.2.23  import java.util.Map;
  68 duncan   1.1.2.1   import java.util.NoSuchElementException;
  69 duncan   1.1.2.23  import java.util.Set;
  70 cananian 1.1.2.84  import java.util.SortedMap;
  71 duncan   1.1.2.1   import java.util.Stack;
  72 cananian 1.1.2.84  import java.util.TreeMap;
  73 duncan   1.1.2.1   
  74 duncan   1.1.2.9   /**
  75 cananian 1.1.2.64   * The ToTree class is used to translate low-quad code to tree code.
  76 duncan   1.1.2.9    * 
  77 duncan   1.1.2.9    * @author  Duncan Bryce <duncan@lcs.mit.edu>
  78 cananian 1.1.2.70   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
  79 cananian 1.9        * @version $Id: ToTree.java,v 1.9 2004/02/08 03:21:28 cananian Exp $
  80 duncan   1.1.2.9    */
  81 cananian 1.1.2.61  class ToTree {
  82 duncan   1.1.2.9       private Tree        m_tree;
  83 cananian 1.1.2.61      private DerivationGenerator m_dg = new DerivationGenerator();
  84 cananian 1.1.2.75      // turning this option on enables assertion checking every dispatch
  85 cananian 1.1.2.75      // to ensure the target method is not null (which happens when the
  86 cananian 1.1.2.75      // method has been proven to be uncallable by the classhierarchy)
  87 cananian 1.1.2.75      private static boolean checkDispatch =
  88 cananian 1.1.2.93          Boolean.getBoolean("harpoon.totree.check.dispatch");
  89 duncan   1.1.2.27     
  90 cananian 1.1.2.62      /** Class constructor.  Uses the default <code>EdgeOracle</code>
  91 cananian 1.1.2.62       *  and <code>ReachingDefs</code> for <code>LowQuadNoSSA</code>. */
  92 duncan   1.1.2.12      public ToTree(final TreeFactory tf, LowQuadNoSSA code) {
  93 cananian 1.1.2.67          this(tf, code,
  94 cananian 1.1.2.79               code.getAllocationInformation(),
  95 cananian 1.1.2.67               new ToTreeHelpers.DefaultEdgeOracle(),
  96 cananian 1.1.2.67               new ToTreeHelpers.DefaultFoldNanny(),
  97 cananian 1.1.2.67               new ReachingDefsImpl(code));
  98 cananian 1.1.2.62      }
  99 cananian 1.1.2.81      public ToTree(final TreeFactory tf, final LowQuadSSA code) {
 100 cananian 1.1.2.81          this(tf, code,
 101 cananian 1.1.2.81               code.getAllocationInformation(),
 102 cananian 1.1.2.81               new ToTreeHelpers.MinMaxEdgeOracle(code),
 103 cananian 1.1.2.81               new ToTreeHelpers.SSXSimpleFoldNanny(code),
 104 cananian 1.1.2.82               new SSxReachingDefsImpl(code));
 105 cananian 1.1.2.81      }
 106 cananian 1.1.2.73      public ToTree(final TreeFactory tf, final LowQuadSSI code) {
 107 cananian 1.1.2.67          this(tf, code,
 108 cananian 1.1.2.79               code.getAllocationInformation(),
 109 cananian 1.1.2.67               new ToTreeHelpers.MinMaxEdgeOracle(code),
 110 cananian 1.1.2.81               new ToTreeHelpers.SSXSimpleFoldNanny(code),
 111 cananian 1.1.2.82               new SSxReachingDefsImpl(code));
 112 cananian 1.1.2.62      }
 113 cananian 1.1.2.62      /** Class constructor. */
 114 cananian 1.1.2.62      public ToTree(final TreeFactory tf, harpoon.IR.LowQuad.Code code,
 115 cananian 1.1.2.76                    AllocationInformation ai,
 116 cananian 1.1.2.65                    EdgeOracle eo, FoldNanny fn, ReachingDefs rd) {
 117 cananian 1.3.2.1           assert ((Code.TreeFactory)tf).getParent()
 118 cananian 1.3.2.1                       .getName().equals("tree");
 119 cananian 1.1.2.79          if (ai==null)
 120 cananian 1.1.2.79              ai = harpoon.Analysis.DefaultAllocationInformation.SINGLETON;
 121 cananian 1.1.2.92          // always wrap edge oracle in a sourcesimilaredgeoracle
 122 cananian 1.1.2.92          eo = new ToTreeHelpers.SourceSimilarEdgeOracle(eo);
 123 cananian 1.1.2.76          translate(tf, code, ai, eo, fn, rd);
 124 duncan   1.1.2.9       }
 125 duncan   1.1.2.9       
 126 cananian 1.1.2.61      /** Returns a <code>TreeDerivation</code> object for the
 127 cananian 1.1.2.61       *  generated <code>Tree</code> form. */
 128 cananian 1.1.2.61      public TreeDerivation getTreeDerivation() { return m_dg; }
 129 duncan   1.1.2.9   
 130 duncan   1.1.2.9       /** Returns the root of the generated tree code */
 131 duncan   1.1.2.9       public Tree getTree() {
 132 duncan   1.1.2.9           return m_tree;
 133 duncan   1.1.2.9       }
 134 duncan   1.1.2.9   
 135 cananian 1.1.2.62      private void translate(TreeFactory tf, harpoon.IR.LowQuad.Code code,
 136 cananian 1.1.2.76                             AllocationInformation ai,
 137 cananian 1.1.2.65                             EdgeOracle eo, FoldNanny fn, ReachingDefs rd) {
 138 cananian 1.1.2.61  
 139 cananian 1.1.2.61          Quad root = (Quad)code.getRootElement();
 140 cananian 1.1.2.61          TempMap ctm = new CloningTempMap
 141 duncan   1.1.2.23              (root.getFactory().tempFactory(),tf.tempFactory());
 142 duncan   1.1.2.23  
 143 duncan   1.1.2.23          // Construct a list of harpoon.IR.Tree.Stm objects
 144 cananian 1.1.2.61          TranslationVisitor tv = new TranslationVisitor
 145 cananian 1.1.2.80              (tf, rd, code.getDerivation(), ai, eo, fn, m_dg, ctm);
 146 cananian 1.1.2.61                                                         
 147 cananian 1.1.2.61          // traverse, starting with the METHOD quad.
 148 cananian 1.1.2.99          dfsTraverse(((harpoon.IR.Quads.METHOD)root.next(1)).prevEdge(0), tv);
 149 duncan   1.1.2.27  
 150 duncan   1.1.2.27          // Assign member variables
 151 cananian 1.1.2.61          m_tree       = ((TranslationVisitor)tv).getTree();
 152 duncan   1.1.2.9       }
 153 duncan   1.1.2.9       
 154 cananian 1.1.2.61      // Translates the Quad graph in a depth-first order.
 155 cananian 1.1.2.99      private void dfsTraverse(Edge in_edge, TranslationVisitor tv) {
 156 cananian 1.1.2.99          Stack stack = new Stack(); stack.add(in_edge);
 157 cananian 1.1.2.99          HashSet visited = new HashSet();
 158 cananian 1.1.2.99          while (!stack.isEmpty())
 159 cananian 1.1.2.99              _dfsTraverse_(stack, tv, visited);
 160 cananian 1.1.2.99      }
 161 cananian 1.1.2.99      private void _dfsTraverse_(Stack stack,
 162 cananian 1.1.2.99                                 TranslationVisitor tv, Set visited) {
 163 cananian 1.1.2.99          Edge in_edge = (Edge) stack.pop();
 164 cananian 1.1.2.98          Quad q = (Quad) in_edge.to();
 165 cananian 1.1.2.98          int which_pred = in_edge.which_pred();
 166 cananian 1.1.2.99          // label sigmas
 167 cananian 1.1.2.99          if (in_edge.from() instanceof harpoon.IR.Quads.SIGMA) {
 168 cananian 1.1.2.99              harpoon.IR.Quads.SIGMA sigma =
 169 cananian 1.1.2.99                  (harpoon.IR.Quads.SIGMA) in_edge.from();
 170 cananian 1.1.2.99              // label sigma outputs, and emit proper fixup code
 171 cananian 1.1.2.99              tv.emitLabel(tv.label(in_edge),/*for line # info:*/sigma);
 172 cananian 1.1.2.99              tv.emitSigmaFixup(sigma, in_edge.which_succ());
 173 cananian 1.1.2.99          }
 174 cananian 1.1.2.61          // if this is a phi function, translate by emitting appropriate MOVEs
 175 cananian 1.1.2.61          if (q instanceof harpoon.IR.Quads.PHI)
 176 cananian 1.1.2.61              tv.emitPhiFixup((harpoon.IR.Quads.PHI)q, which_pred);
 177 cananian 1.1.2.61          // if we've already translated this quad, goto the translation.
 178 cananian 1.1.2.61          if (visited.contains(q)) {
 179 cananian 1.1.2.61              tv.emitGoto(tv.label(q), /*for line # info:*/q.prev(which_pred));
 180 cananian 1.1.2.61              return;
 181 cananian 1.1.2.61          } else visited.add(q);
 182 cananian 1.1.2.61          // label phis.
 183 cananian 1.1.2.61          if (q instanceof harpoon.IR.Quads.PHI)
 184 cananian 1.1.2.61              tv.emitLabel(tv.label(q), /* for line # info:*/q);
 185 cananian 1.1.2.61          // translate this instruction.
 186 cananian 1.1.2.61          q.accept(tv);
 187 cananian 1.1.2.61          // translate successors.
 188 cananian 1.1.2.61          int n = q.nextLength();
 189 cananian 1.1.2.61          int def = tv.edgeOracle.defaultEdge(q);
 190 cananian 1.1.2.99          // work backwards: remember first pushed is last popped.
 191 cananian 1.1.2.99          for (int i=n-1; i>=0; i--) {
 192 cananian 1.1.2.61              // permute edges such that default always comes first.
 193 cananian 1.1.2.61              //  think:  0 1[2]3 4  (if 2 is the default)
 194 cananian 1.1.2.61              //         [2]0 1 3 4
 195 cananian 1.1.2.61              Edge edge = q.nextEdge((i==0)?def:(i<=def)?i-1:i);
 196 cananian 1.1.2.61              // recurse.
 197 cananian 1.1.2.61              if (!(edge.to() instanceof harpoon.IR.Quads.FOOTER))
 198 cananian 1.1.2.99                  stack.push(edge);
 199 cananian 1.1.2.61          }
 200 cananian 1.1.2.61          // done, yay.
 201 duncan   1.1.2.9       }
 202 cananian 1.1.2.61  
 203 cananian 1.1.2.48      // don't close class: all of the following are inner classes,
 204 cananian 1.1.2.48      // even if they don't look that way.  I'm just don't feel like
 205 cananian 1.1.2.50      // reindenting all of this existing code. [CSA]
 206 duncan   1.1.2.1     
 207 duncan   1.1.2.23  // Translates the LowQuadNoSSA code into tree form. 
 208 duncan   1.1.2.9   //
 209 cananian 1.1.2.61  static class TranslationVisitor extends LowQuadVisitor {
 210 cananian 1.1.2.61      private final TempMap     m_ctm;          // Clones Temps to new tf
 211 cananian 1.1.2.61      private final NameMap     m_nm;           // Runtime-specific label naming
 212 cananian 1.1.2.61      private final List        m_stmList;      // Holds translated statements
 213 cananian 1.1.2.61      private final TreeFactory m_tf;           // The new TreeFactory
 214 cananian 1.1.2.61      private Temp              m_handler = null; 
 215 cananian 1.1.2.61      private final Runtime.TreeBuilder m_rtb;
 216 cananian 1.1.2.61  
 217 cananian 1.1.2.61      private final Derivation quadDeriv;
 218 cananian 1.1.2.61      private final DerivationGenerator treeDeriv;
 219 cananian 1.1.2.76      public final AllocationInformation allocInfo;
 220 cananian 1.1.2.61      public final EdgeOracle edgeOracle;
 221 cananian 1.1.2.65      public final FoldNanny  foldNanny;
 222 cananian 1.1.2.61      public final ReachingDefs reachingDefs;
 223 cananian 1.1.2.61  
 224 cananian 1.1.2.61      public TranslationVisitor(TreeFactory tf,
 225 cananian 1.1.2.61                                ReachingDefs reachingDefs,
 226 cananian 1.1.2.61                                Derivation quadDeriv,
 227 cananian 1.1.2.76                                AllocationInformation allocInfo,
 228 cananian 1.1.2.61                                EdgeOracle edgeOracle,
 229 cananian 1.1.2.65                                FoldNanny foldNanny,
 230 cananian 1.1.2.61                                DerivationGenerator treeDeriv,
 231 cananian 1.1.2.61                                TempMap ctm) {
 232 duncan   1.1.2.9           m_ctm          = ctm;
 233 duncan   1.1.2.29          m_tf           = tf; 
 234 cananian 1.1.2.95          m_nm           = m_tf.getFrame().getRuntime().getNameMap();
 235 duncan   1.1.2.23          m_stmList      = new ArrayList();
 236 cananian 1.1.2.95          m_rtb          = m_tf.getFrame().getRuntime().getTreeBuilder();
 237 cananian 1.1.2.61          this.quadDeriv      = quadDeriv;
 238 cananian 1.1.2.61          this.treeDeriv      = treeDeriv;
 239 cananian 1.1.2.76          this.allocInfo      = allocInfo;
 240 cananian 1.1.2.61          this.edgeOracle     = edgeOracle;
 241 cananian 1.1.2.65          this.foldNanny      = foldNanny;
 242 cananian 1.1.2.61          this.reachingDefs   = reachingDefs;
 243 duncan   1.1.2.9       }
 244 duncan   1.1.2.1   
 245 duncan   1.1.2.23      Tree getTree() { return Stm.toStm(m_stmList); } 
 246 duncan   1.1.2.9   
 247 cananian 1.1.2.61      // label maker ----------------
 248 cananian 1.1.2.61      private final Map labelMap = new HashMap() {
 249 cananian 1.1.2.61          public Object get(Object key) {
 250 cananian 1.1.2.61              if (!containsKey(key)) { put(key, new Label()); }
 251 cananian 1.1.2.61              return super.get(key);
 252 cananian 1.1.2.61          }
 253 cananian 1.1.2.61      };
 254 cananian 1.1.2.61      public Label label(Quad q) {
 255 cananian 1.3.2.1           assert q instanceof harpoon.IR.Quads.PHI;
 256 cananian 1.1.2.61          return (Label) labelMap.get(q);
 257 cananian 1.1.2.61      }
 258 cananian 1.1.2.61      public Label label(Edge e) {
 259 cananian 1.3.2.1           assert e.from() instanceof harpoon.IR.Quads.SIGMA;
 260 cananian 1.1.2.61          return (Label) labelMap.get(e);
 261 cananian 1.1.2.61      }
 262 cananian 1.1.2.61      // end label maker --------------
 263 cananian 1.1.2.61  
 264 cananian 1.1.2.61      // labels and phis and sigmas, oh my! ------------
 265 cananian 1.1.2.61      public void emitGoto(Label target, HCodeElement src) {
 266 cananian 1.1.2.61          addStmt(new JUMP(m_tf, src, target));
 267 cananian 1.1.2.61      }
 268 cananian 1.1.2.61      public void emitLabel(Label label, HCodeElement src) {
 269 cananian 1.1.2.61          addStmt(new LABEL(m_tf, src, label, false));
 270 cananian 1.1.2.61      }
 271 cananian 1.1.2.100     /* careful: phis can be conflicted (sources intersect phis != empty set) */
 272 cananian 1.1.2.61      public void emitPhiFixup(harpoon.IR.Quads.PHI q, int which_pred) {
 273 cananian 1.1.2.100         boolean hasConflicts = q.hasConflicts();
 274 cananian 1.1.2.100         Translation.Exp srcval[] = new Translation.Exp[q.numPhis()];
 275 cananian 1.1.2.100         for (int i=0; i<q.numPhis(); i++) {
 276 cananian 1.1.2.100             srcval[i] = _TEMPte(q.src(i, which_pred), q);
 277 cananian 1.1.2.100             if (hasConflicts) {
 278 cananian 1.1.2.100                 // move all sources to temps before moving to destinations.
 279 cananian 1.1.2.100                 Temp treeTemp = new Temp(m_ctm.tempMap(q.dst(i)));
 280 cananian 1.1.2.100                 HClass type = quadDeriv.typeMap(q, q.dst(i));
 281 cananian 1.1.2.100                 TEMP T1 = new TEMP(m_tf, q, TYPE(type), treeTemp);
 282 cananian 1.1.2.100                 TEMP T2 = new TEMP(m_tf, q, TYPE(type), treeTemp);
 283 cananian 1.1.2.100                 MOVE M = new MOVE(m_tf, q, T1, srcval[i].unEx(m_tf));
 284 cananian 1.1.2.100                 if (type!=null) {
 285 cananian 1.1.2.100                     treeDeriv.putTypeAndTemp(T1, type, treeTemp);
 286 cananian 1.1.2.100                     treeDeriv.putTypeAndTemp(T2, type, treeTemp);
 287 cananian 1.1.2.100                 } else {
 288 cananian 1.1.2.100                     DList dl = DList.rename(quadDeriv.derivation(q, q.dst(i)),
 289 cananian 1.1.2.100                                             m_ctm);
 290 cananian 1.1.2.100                     treeDeriv.putDerivation(T1, dl);
 291 cananian 1.1.2.100                     treeDeriv.putDerivation(T2, dl);
 292 cananian 1.1.2.100                 }
 293 cananian 1.1.2.100                 addStmt(M);
 294 cananian 1.1.2.100                 srcval[i] = new Translation.Ex(T2);
 295 cananian 1.1.2.100             }
 296 cananian 1.1.2.100         }
 297 cananian 1.1.2.66          for (int i=0; i<q.numPhis(); i++)
 298 cananian 1.1.2.100             addMove(q, q.dst(i), srcval[i]);
 299 cananian 1.1.2.61      }
 300 cananian 1.1.2.61      public void emitSigmaFixup(harpoon.IR.Quads.SIGMA q, int which_succ) {
 301 cananian 1.1.2.66          for (int i=0; i<q.numSigmas(); i++)
 302 cananian 1.1.2.66              addMove(q, q.dst(i, which_succ), _TEMPte(q.src(i), q));
 303 cananian 1.1.2.61      }
 304 cananian 1.1.2.61      // end labels and phis and sigmas, oh my! --------
 305 cananian 1.1.2.61  
 306 cananian 1.3.2.1       public void visit(Quad q) { assert false; /* not handled! */ }
 307 duncan   1.1.2.9   
 308 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.ALENGTH q) {
 309 cananian 1.1.2.61          addMove
 310 cananian 1.1.2.61              (q, q.dst(),
 311 cananian 1.1.2.50               m_rtb.arrayLength
 312 cananian 1.1.2.72               (m_tf, q, treeDeriv, _TEMPte(q.objectref(), q))
 313 cananian 1.1.2.50               );
 314 duncan   1.1.2.9       }
 315 duncan   1.1.2.9   
 316 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.ANEW q) {
 317 cananian 1.1.2.52          // create and zero fill a multi-dimensional array.
 318 cananian 1.1.2.52          int dl = q.dimsLength();
 319 cananian 1.3.2.1           assert dl>0;
 320 cananian 1.1.2.52          // temps to hold each part of the array;
 321 cananian 1.1.2.52          // arrayTemps[i] holds an (dl-i)-dimensional array.
 322 cananian 1.1.2.52          // arrayClasses[i] is the type of arrayTemps[i]
 323 cananian 1.1.2.52          Temp[] arrayTemps = new Temp[dl+1];
 324 cananian 1.1.2.52          HClass[] arrayClasses = new HClass[dl+1];
 325 cananian 1.1.2.61          arrayTemps[0] = m_ctm.tempMap(q.dst());
 326 cananian 1.1.2.52          arrayClasses[0] = q.hclass();
 327 cananian 1.1.2.52          for (int i=1; i<=dl; i++) {
 328 cananian 1.1.2.52              arrayTemps[i] = new Temp(arrayTemps[i-1]);
 329 cananian 1.1.2.52              arrayClasses[i] = arrayClasses[i-1].getComponentType();
 330 cananian 1.3.2.1               assert arrayClasses[i]!=null;
 331 cananian 1.1.2.52          }
 332 cananian 1.1.2.52          // temps standing for size of each dimension.
 333 cananian 1.1.2.52          Temp[] dimTemps = new Temp[dl];
 334 cananian 1.1.2.61          for (int i=0; i<dl; i++) {
 335 cananian 1.1.2.61              dimTemps[i] = m_ctm.tempMap(q.dims(i));
 336 cananian 1.1.2.61              // move (possibly folded) values into dimTemps, as we will
 337 cananian 1.1.2.61              // be evaluating the dimensions multiple times.
 338 cananian 1.1.2.61              addStmt(new MOVE(m_tf, q,
 339 cananian 1.1.2.61                               _TEMP(q, HClass.Int, dimTemps[i]),
 340 cananian 1.1.2.61                               _TEMP(q.dims(i), q)));
 341 cananian 1.1.2.61          }
 342 cananian 1.1.2.52          // temps used to index each dimension
 343 cananian 1.1.2.52          Temp[] indexTemps = new Temp[dl];
 344 cananian 1.1.2.52          for (int i=0; i<dl; i++)
 345 cananian 1.1.2.52              indexTemps[i] = new Temp(m_tf.tempFactory(), "idx");
 346 cananian 1.1.2.52          // labels for loop top, test, and end.
 347 cananian 1.1.2.52          Label[] testLabel = new Label[dl];
 348 cananian 1.1.2.52          Label[] loopLabel = new Label[dl];
 349 cananian 1.1.2.52          Label[] doneLabel = new Label[dl];
 350 cananian 1.1.2.52          for (int i=0; i<dl; i++) {
 351 cananian 1.1.2.52              testLabel[i] = new Label();
 352 cananian 1.1.2.52              loopLabel[i] = new Label();
 353 cananian 1.1.2.52              doneLabel[i] = new Label();
 354 cananian 1.1.2.52          }
 355 cananian 1.1.2.52          // okay.  Now do the translation:
 356 cananian 1.1.2.52          //  d1 = new array(ilen);
 357 cananian 1.1.2.52          //  for (i=0; i<ilen; i++) {
 358 cananian 1.1.2.52          //    d2 = d1[i] = new array(jlen);
 359 cananian 1.1.2.96          //    /* call to 'new array' above *must* initialize all elements,
 360 cananian 1.1.2.96          //       or else gc will get very unhappy when we alloc the subarray
 361 cananian 1.1.2.96          //       (possibly causing gc) with the uninitialized array on the
 362 cananian 1.1.2.96          //       heap */
 363 cananian 1.1.2.96          //    <next step only if there are subarrays>
 364 cananian 1.1.2.52          //    for (j=0; j<jlen; j++) {
 365 cananian 1.1.2.96          //      d3 = d2[i] = new array(jlen);
 366 cananian 1.1.2.96          //      ...
 367 cananian 1.1.2.52          //    }
 368 cananian 1.1.2.52          //  }
 369 cananian 1.1.2.96          for (int i=0; i<dl; i++) { // write the loop tops.
 370 cananian 1.1.2.96              Exp initializer = m_rtb.arrayNew
 371 cananian 1.1.2.76                      (m_tf, q, treeDeriv,
 372 cananian 1.1.2.76                       MAP(allocInfo.query(q)),
 373 cananian 1.1.2.76                       arrayClasses[i],
 374 cananian 1.1.2.52                       new Translation.Ex
 375 cananian 1.1.2.96                       (_TEMP(q, HClass.Int, dimTemps[i])), true).unEx(m_tf);
 376 cananian 1.1.2.52              // output: d1[i] = d2 = initializer.
 377 cananian 1.1.2.52              Stm s1 = new MOVE // d2 = initializer
 378 cananian 1.1.2.52                  (m_tf, q,
 379 cananian 1.1.2.61                   _TEMP(q, arrayClasses[i], arrayTemps[i]),
 380 cananian 1.1.2.52                   initializer);
 381 cananian 1.1.2.52              if (i>0) // suppress the "d1[i]" part for outermost
 382 cananian 1.1.2.52                  s1 = new MOVE
 383 cananian 1.1.2.52                      (m_tf, q,
 384 cananian 1.1.2.52                       makeMEM // d1[i] = ...
 385 cananian 1.1.2.52                       (q, arrayClasses[i],
 386 duncan   1.1.2.18                        new BINOP
 387 cananian 1.1.2.52                        (m_tf, q, Type.POINTER, Bop.ADD,
 388 cananian 1.1.2.52                         m_rtb.arrayBase
 389 cananian 1.1.2.72                         (m_tf, q, treeDeriv,
 390 cananian 1.1.2.52                          new Translation.Ex
 391 cananian 1.1.2.61                          (_TEMP(q, arrayClasses[i-1], arrayTemps[i-1])))
 392 cananian 1.1.2.52                         .unEx(m_tf),
 393 cananian 1.1.2.52                         m_rtb.arrayOffset
 394 cananian 1.1.2.72                         (m_tf, q, treeDeriv, arrayClasses[i-1],
 395 cananian 1.1.2.52                          new Translation.Ex
 396 cananian 1.1.2.61                          (_TEMP(q, HClass.Int, indexTemps[i-1])))
 397 cananian 1.1.2.52                          .unEx(m_tf)
 398 cananian 1.1.2.52                          )),
 399 cananian 1.1.2.52                       new ESEQ // ... (d2 = initializer)
 400 cananian 1.1.2.52                       (m_tf, q, s1,
 401 cananian 1.1.2.61                        _TEMP(q, arrayClasses[i], arrayTemps[i])));
 402 cananian 1.1.2.61                        
 403 cananian 1.1.2.52              addStmt(s1);
 404 cananian 1.1.2.52              // for (i=0; i<ilen; i++) ...
 405 cananian 1.1.2.96              if (i<dl-1) { // skip loop for innermost
 406 cananian 1.1.2.52                  addStmt(new MOVE // i=0.
 407 cananian 1.1.2.52                          (m_tf, q,
 408 cananian 1.1.2.61                           _TEMP(q, HClass.Int, indexTemps[i]),
 409 cananian 1.1.2.52                           new CONST(m_tf, q, 0)));
 410 cananian 1.1.2.52                  addStmt(new JUMP(m_tf, q, testLabel[i]));
 411 cananian 1.1.2.52                  addStmt(new LABEL(m_tf, q, loopLabel[i], false));
 412 duncan   1.1.2.18              }
 413 duncan   1.1.2.18          }
 414 cananian 1.1.2.52          // okay, write the loop bottoms in reverse order.
 415 cananian 1.1.2.96          for (int i=dl-2; i>=0; i--) {
 416 cananian 1.1.2.52              // increment the loop counter
 417 cananian 1.1.2.52              addStmt(new MOVE // i++
 418 cananian 1.1.2.52                      (m_tf, q,
 419 cananian 1.1.2.61                       _TEMP(q, HClass.Int, indexTemps[i]),
 420 cananian 1.1.2.52                       new BINOP(m_tf, q, Type.INT, Bop.ADD,
 421 cananian 1.1.2.61                                 _TEMP(q, HClass.Int, indexTemps[i]),
 422 cananian 1.1.2.52                                 new CONST(m_tf, q, 1))));
 423 cananian 1.1.2.52              // loop test label
 424 cananian 1.1.2.52              addStmt(new LABEL(m_tf, q, testLabel[i], false));
 425 cananian 1.1.2.52              // test and branch: if i<ilen goto LOOP else goto DONE;
 426 cananian 1.1.2.52              addStmt(new CJUMP
 427 cananian 1.1.2.52                      (m_tf, q,
 428 cananian 1.1.2.52                       new BINOP(m_tf, q, Type.INT, Bop.CMPLT,
 429 cananian 1.1.2.61                                 _TEMP(q, HClass.Int, indexTemps[i]),
 430 cananian 1.1.2.61                                 _TEMP(q, HClass.Int, dimTemps[i])),
 431 cananian 1.1.2.52                       loopLabel[i]/*iftrue*/, doneLabel[i]/*iffalse*/));
 432 cananian 1.1.2.52              addStmt(new LABEL(m_tf, q, doneLabel[i], false));
 433 cananian 1.1.2.52          }
 434 cananian 1.1.2.52          // ta-da!
 435 cananian 1.1.2.61          // add bogus move to placate folding code
 436 cananian 1.1.2.61          addMove(q, q.dst(), _TEMP(q, arrayClasses[0], arrayTemps[0]));
 437 duncan   1.1.2.9       }
 438 duncan   1.1.2.9   
 439 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.ARRAYINIT q) {
 440 cananian 1.1.2.74          HClass arrayType = HClassUtil.arrayClass(q.getFactory().getLinker(),
 441 cananian 1.1.2.74                                                   q.type(), 1);
 442 duncan   1.1.2.9           Stm s0, s1, s2;
 443 duncan   1.1.2.9   
 444 duncan   1.1.2.9           // Create a pointer which we'll use to initialize the array
 445 cananian 1.1.2.61          Temp  nextPtr = new Temp(m_tf.tempFactory(), "nxt");
 446 cananian 1.1.2.61          // make sure base pointer lives in a treetemp. (may be folded instead)
 447 cananian 1.1.2.61          Temp   objTemp = m_ctm.tempMap(q.objectref());
 448 cananian 1.1.2.61          addStmt(new MOVE(m_tf, q, 
 449 cananian 1.1.2.61                           _TEMP(q, arrayType, objTemp), 
 450 cananian 1.1.2.61                           _TEMP(q.objectref(), q)));
 451 duncan   1.1.2.9           // Create derivation information for the new TEMP
 452 cananian 1.1.2.61          DList dl = new DList(objTemp, true, null);
 453 duncan   1.1.2.9   
 454 cananian 1.5               Object[] qvalue = q.value();
 455 cananian 1.5               int offset = q.offset();
 456 cananian 1.5               // trim zero elements from from and end of this array.  the end is
 457 cananian 1.5               // actually really important, as gcc will try to optimize the
 458 cananian 1.5               // initialization table to a bss segment with the preciseC backend,
 459 cananian 1.5               // screwing with the data layout, if all the elements in a structure
 460 cananian 1.5               // are zero.
 461 cananian 1.5               int start=0, end=qvalue.length;
 462 cananian 1.5               CONST zarro = constZero(q, q.type());
 463 cananian 1.5               while (start < end &&
 464 cananian 1.5                      zarro.value().equals(_CONST(q,q.type(), qvalue[start]).value()))
 465 cananian 1.5                   start++;
 466 cananian 1.5               while (start < end &&
 467 cananian 1.5                      zarro.value().equals(_CONST(q,q.type(), qvalue[end-1]).value()))
 468 cananian 1.5                   end--;
 469 cananian 1.5               // now chop start and end bits off of qvalue.
 470 cananian 1.5               if (start!=0 || end != qvalue.length) {
 471 cananian 1.5                   Object[] old = qvalue;
 472 cananian 1.5                   qvalue = new Object[end-start];
 473 cananian 1.5                   System.arraycopy(old, start, qvalue, 0, qvalue.length);
 474 cananian 1.5                   offset += start;
 475 cananian 1.5               }
 476 cananian 1.5       
 477 cananian 1.5               // set nextPtr to point to arrayBase + offset * size.
 478 duncan   1.1.2.9           s0 = new MOVE
 479 duncan   1.1.2.9               (m_tf, q, 
 480 cananian 1.1.2.61               _TEMP(q, dl, nextPtr),
 481 duncan   1.1.2.9                new BINOP
 482 duncan   1.1.2.9                (m_tf, q, Type.POINTER, Bop.ADD,
 483 cananian 1.1.2.50                m_rtb.arrayBase
 484 cananian 1.1.2.72                (m_tf, q, treeDeriv,
 485 cananian 1.1.2.72                 new Translation.Ex(_TEMP(q, arrayType, objTemp)))
 486 cananian 1.1.2.61                .unEx(m_tf),
 487 cananian 1.1.2.50                m_rtb.arrayOffset
 488 cananian 1.1.2.72                (m_tf, q, treeDeriv, arrayType,
 489 cananian 1.5                      new Translation.Ex(new CONST(m_tf, q, offset))).unEx(m_tf)
 490 cananian 1.1.2.50                ));
 491 duncan   1.1.2.9   
 492 duncan   1.1.2.23          addStmt(s0);
 493 duncan   1.1.2.1       
 494 cananian 1.5               // okay, now pick the proper initialization strategy.
 495 cananian 1.1.2.85          if (qvalue.length <= 5 /* magic number */ || !q.type().isPrimitive()) {
 496 cananian 1.1.2.85              // explicit element-by-element initialization
 497 cananian 1.1.2.85              for (int i=0; i<qvalue.length; i++) {
 498 cananian 1.1.2.85                  Exp c = mapconst(q, qvalue[i], q.type()).unEx(m_tf);
 499 cananian 1.1.2.85                  MEM m = makeMEM(q, q.type(), _TEMP(q, dl, nextPtr));
 500 cananian 1.1.2.85                  s0 = new MOVE(m_tf, q, m, c);
 501 cananian 1.1.2.85                  s1 = new MOVE
 502 cananian 1.1.2.85                      (m_tf, q, 
 503 cananian 1.1.2.85                       _TEMP(q, dl, nextPtr), 
 504 cananian 1.1.2.85                       new BINOP
 505 cananian 1.1.2.85                       (m_tf, q, Type.POINTER, Bop.ADD, 
 506 cananian 1.1.2.85                        _TEMP(q, dl, nextPtr), 
 507 cananian 1.1.2.85                        m_rtb.arrayOffset
 508 cananian 1.1.2.85                        (m_tf, q, treeDeriv, arrayType,
 509 cananian 1.1.2.85                         new Translation.Ex(new CONST(m_tf, q, 1))).unEx(m_tf)
 510 cananian 1.1.2.85                        ));
 511 cananian 1.1.2.85                  
 512 cananian 1.1.2.85                  addStmt(new SEQ(m_tf, q, s0, s1));
 513 cananian 1.1.2.85              }
 514 cananian 1.1.2.85          } else {
 515 cananian 1.1.2.85              // initialize array from a constant table.
 516 duncan   1.1.2.9   
 517 cananian 1.1.2.85              // create labels for our constant table
 518 cananian 1.1.2.85              Label constTblStart = new Label(), constTblEnd = new Label();
 519 cananian 1.1.2.85              // and labels for loop
 520 cananian 1.1.2.85              Label looptop=new Label(),looptst=new Label(),loopend=new Label();
 521 cananian 1.1.2.85              // create a pointer into our constant table...
 522 cananian 1.1.2.85              Temp constPtr = new Temp(m_tf.tempFactory(), "cnst");
 523 cananian 1.6                   // for (constPtr=constTblStart; constPtr <=constTblEnd; constPtr++)
 524 cananian 1.1.2.85              // loop header:
 525 cananian 1.1.2.85              addStmt(new MOVE
 526 cananian 1.1.2.85                      (m_tf, q,
 527 cananian 1.1.2.85                       _TEMP(q, HClass.Void, constPtr),
 528 cananian 1.1.2.85                       new NAME(m_tf, q, constTblStart)));
 529 cananian 1.1.2.85              addStmt(new JUMP(m_tf, q, looptst));
 530 cananian 1.1.2.85              addStmt(new LABEL(m_tf, q, looptop, false));
 531 cananian 1.1.2.85              // loop body: { *nextptr = *constPtr; }
 532 cananian 1.1.2.85              addStmt(new MOVE
 533 cananian 1.1.2.85                      (m_tf, q,
 534 cananian 1.1.2.85                       makeMEM(q, q.type(), _TEMP(q, dl, nextPtr)),
 535 cananian 1.1.2.85                       makeMEM(q, q.type(), _TEMP(q, HClass.Void, constPtr))));
 536 cananian 1.1.2.85              // loop increment:
 537 cananian 1.1.2.85              addStmt(new MOVE
 538 cananian 1.1.2.85                      (m_tf, q,
 539 cananian 1.1.2.85                       _TEMP(q, dl, nextPtr),
 540 cananian 1.1.2.85                       new BINOP
 541 cananian 1.1.2.85                       (m_tf, q, Type.POINTER, Bop.ADD,
 542 cananian 1.1.2.85                        _TEMP(q, dl, nextPtr),
 543 cananian 1.1.2.85                        m_rtb.arrayOffset
 544 cananian 1.1.2.85                        (m_tf, q, treeDeriv, arrayType,
 545 cananian 1.1.2.85                         new Translation.Ex(new CONST(m_tf, q, 1))).unEx(m_tf)
 546 cananian 1.1.2.85                        )));
 547 cananian 1.1.2.85              addStmt(new MOVE
 548 cananian 1.1.2.85                      (m_tf, q,
 549 cananian 1.1.2.85                       _TEMP(q, HClass.Void, constPtr),
 550 cananian 1.1.2.85                       new BINOP
 551 cananian 1.1.2.85                       (m_tf, q, Type.POINTER, Bop.ADD,
 552 cananian 1.1.2.85                        _TEMP(q, HClass.Void, constPtr),
 553 cananian 1.1.2.85                        new CONST(m_tf, q, sizeof(q.type())))));
 554 cananian 1.1.2.85              // loop test:
 555 cananian 1.1.2.85              addStmt(new LABEL(m_tf, q, looptst, false));
 556 cananian 1.1.2.85              addStmt(new CJUMP
 557 cananian 1.1.2.85                      (m_tf, q,
 558 cananian 1.1.2.85                       new BINOP
 559 cananian 1.1.2.85                       (m_tf, q, Type.POINTER, Bop.CMPLE,
 560 cananian 1.1.2.85                        _TEMP(q, HClass.Void, constPtr),
 561 cananian 1.1.2.85                        new NAME(m_tf, q, constTblEnd)),
 562 cananian 1.1.2.85                       looptop/*iftrue*/, loopend/*iffalse*/));
 563 cananian 1.1.2.85              // okay, now output constant data table.
 564 cananian 1.1.2.85              addStmt(new ALIGN(m_tf, q, sizeof(q.type())));
 565 cananian 1.1.2.85              addStmt(new LABEL(m_tf, q, constTblStart, false));
 566 cananian 1.3.2.1               assert qvalue.length>0;
 567 cananian 1.1.2.85              for (int i=0; i<qvalue.length; i++) {
 568 cananian 1.7                       if (i==qvalue.length-1) {
 569 cananian 1.7                           // explicit alignment here as a hint to preciseC backend,
 570 cananian 1.7                           // so that the __aligned__ tag on the struct is correct.
 571 cananian 1.7                           addStmt(new ALIGN(m_tf, q, sizeof(q.type())));
 572 cananian 1.1.2.85                      addStmt(new LABEL(m_tf, q, constTblEnd, false));
 573 cananian 1.7                       }
 574 cananian 1.1.2.85                  addStmt(new DATUM(m_tf, q, _CONST(q, q.type(), qvalue[i])));
 575 cananian 1.5                       if (i==qvalue.length-1)
 576 cananian 1.5                           assert ! _CONST(q, q.type(), qvalue[i]).value()
 577 cananian 1.5                               .equals(constZero(q, q.type()).value()) :
 578 cananian 1.5                               "PreciseC backend may relocate this trailing part of "+
 579 cananian 1.5                               "the table to the .bss segment, separating it from "+
 580 cananian 1.5                               "the rest of the table.  Old versions of gcc didn't "+
 581 cananian 1.5                               "used to do this; new versions are too darn smart."
 582 cananian 1.6                               /* require -fno-zero-initialized-in-bss to gcc */;
 583 cananian 1.1.2.85              }
 584 cananian 1.6                   /* workaround AIX gcc brokenness by realigning @ end of table */
 585 cananian 1.6                   addStmt(new ALIGN(m_tf, q, 8/* big alignment */));
 586 cananian 1.6                   addStmt(new LABEL(m_tf, q, new Label(), false));
 587 cananian 1.6                   addStmt(new DATUM(m_tf, q, new CONST(m_tf, q, 1976L)));
 588 cananian 1.6                   /* end workaround */
 589 cananian 1.6                   
 590 cananian 1.1.2.85              // and jump back here when loop's done.
 591 cananian 1.1.2.85              addStmt(new ALIGN(m_tf, q, 8/* safe value for alignment */));
 592 cananian 1.1.2.85              addStmt(new LABEL(m_tf, q, loopend, false));
 593 duncan   1.1.2.9           }
 594 cananian 1.1.2.85          // done.
 595 duncan   1.1.2.9       }
 596 duncan   1.1.2.9   
 597 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.CJMP q) { 
 598 cananian 1.1.2.66          addStmt(_TEMPte(q.test(), q).unCx
 599 cananian 1.1.2.66                  (m_tf, label(q.nextEdge(1)), label(q.nextEdge(0))));
 600 duncan   1.1.2.9       }
 601 duncan   1.1.2.1     
 602 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.COMPONENTOF q) {
 603 cananian 1.1.2.61          addMove(q, q.dst(),
 604 cananian 1.1.2.72                  m_rtb.componentOf(m_tf, q, treeDeriv,
 605 cananian 1.1.2.61                                    _TEMPte(q.arrayref(), q),
 606 cananian 1.1.2.61                                    _TEMPte(q.objectref(), q)));
 607 duncan   1.1.2.9       }
 608 duncan   1.1.2.9   
 609 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.CONST q) {
 610 cananian 1.1.2.61          addMove(q, q.dst(), mapconst(q, q.value(), q.type()));
 611 duncan   1.1.2.9       }
 612 duncan   1.1.2.1     
 613 cananian 1.1.2.101     public void visit(harpoon.IR.Quads.DEBUG q) {
 614 cananian 1.1.2.101         emitDebug(m_tf, q, q.str());
 615 cananian 1.1.2.101     }
 616 cananian 1.1.2.101 
 617 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.INSTANCEOF q) {
 618 cananian 1.1.2.61          addMove
 619 cananian 1.1.2.61              (q, q.dst(),
 620 cananian 1.1.2.72               m_rtb.instanceOf(m_tf, q, treeDeriv,
 621 cananian 1.1.2.61                                _TEMPte(q.src(), q), q.hclass()));
 622 duncan   1.1.2.9       }
 623 duncan   1.1.2.1   
 624 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.METHOD q) {
 625 duncan   1.1.2.28          METHOD method; SEGMENT segment;
 626 cananian 1.1.2.68          Temp   paramsQ[]  = q.params(); // quad temps
 627 cananian 1.1.2.68          Temp   paramsT[] = new Temp[paramsQ.length]; // tree temps
 628 cananian 1.1.2.68          TEMP   mParams[] = new TEMP[paramsQ.length+1];
 629 duncan   1.1.2.24          
 630 cananian 1.1.2.68          // compute types of TEMPs
 631 cananian 1.1.2.68          HMethod hm = q.getFactory().getMethod();
 632 cananian 1.1.2.68          List types = new ArrayList(Arrays.asList(hm.getParameterTypes()));
 633 cananian 1.1.2.68          if (!q.isStatic()) types.add(0, hm.getDeclaringClass());
 634 cananian 1.1.2.68          HClass paramType[] = (HClass[])types.toArray(new HClass[types.size()]);
 635 cananian 1.1.2.68          // make tree temps for quad temps
 636 cananian 1.1.2.68          for (int i=0; i<paramsQ.length; i++)
 637 cananian 1.1.2.68              paramsT[i] = m_ctm.tempMap(paramsQ[i]);
 638 cananian 1.1.2.68  
 639 duncan   1.1.2.28          segment = new SEGMENT(m_tf, q, SEGMENT.CODE);
 640 cananian 1.1.2.68          for (int i=0; i<paramsT.length; i++) { 
 641 cananian 1.1.2.68              mParams[i+1] = _TEMP(q, paramType[i], paramsT[i]);
 642 duncan   1.1.2.27          }
 643 cananian 1.3.2.1           assert m_handler==null;
 644 cananian 1.1.2.61          m_handler = new Temp(m_tf.tempFactory(), "handler");
 645 cananian 1.1.2.61          mParams[0] = _TEMP(q, HClass.Void, m_handler);
 646 cananian 1.1.2.83          int rettype = (hm.getReturnType()==HClass.Void) ? -1 :
 647 cananian 1.1.2.83              TYPE(hm.getReturnType());
 648 cananian 1.1.2.83          method    = new METHOD(m_tf, q, m_nm.label(hm), rettype, mParams);
 649 duncan   1.1.2.28          addStmt(segment);
 650 duncan   1.1.2.24          addStmt(method);
 651 cananian 1.1.2.68          // deal with possible folding
 652 cananian 1.1.2.68          for (int i=0; i<paramsQ.length; i++)
 653 cananian 1.1.2.68              addMove(q, paramsQ[i], _TEMP(q, paramType[i], paramsT[i]));
 654 duncan   1.1.2.9       }
 655 duncan   1.1.2.9   
 656 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.MONITORENTER q) {
 657 cananian 1.1.2.72          addStmt(m_rtb.monitorEnter(m_tf, q, treeDeriv, _TEMPte(q.lock(), q))
 658 cananian 1.1.2.50                       .unNx(m_tf));
 659 duncan   1.1.2.9       }
 660 duncan   1.1.2.9   
 661 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.MONITOREXIT q) {
 662 cananian 1.1.2.72          addStmt(m_rtb.monitorExit(m_tf, q, treeDeriv, _TEMPte(q.lock(), q))
 663 cananian 1.1.2.50                       .unNx(m_tf));
 664 duncan   1.1.2.9       }
 665 duncan   1.1.2.9   
 666 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.MOVE q) {
 667 cananian 1.1.2.61          addMove(q, q.dst(), _TEMPte(q.src(), q));
 668 duncan   1.1.2.9       }
 669 duncan   1.1.2.9   
 670 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.NEW q) { 
 671 cananian 1.1.2.61          addMove(q, q.dst(),
 672 cananian 1.1.2.76                  m_rtb.objectNew(m_tf, q, treeDeriv, MAP(allocInfo.query(q)),
 673 cananian 1.1.2.76                                  q.hclass(), true));
 674 duncan   1.1.2.9       }
 675 duncan   1.1.2.9           
 676 cananian 1.1.2.63      public void visit(harpoon.IR.Quads.PHI q) {
 677 cananian 1.1.2.63          // do nothing!
 678 cananian 1.1.2.63      }
 679 cananian 1.1.2.63  
 680 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.RETURN q) {
 681 duncan   1.1.2.9           Exp retval;
 682 duncan   1.1.2.4       
 683 duncan   1.1.2.9           if (q.retval()==null) {
 684 duncan   1.1.2.9               retval = new CONST(m_tf, q, 0);
 685 duncan   1.1.2.9           }
 686 duncan   1.1.2.9           else {
 687 duncan   1.1.2.27              retval = _TEMP(q.retval(), q);
 688 duncan   1.1.2.9           }
 689 duncan   1.1.2.9   
 690 duncan   1.1.2.9           Stm s0 = new RETURN(m_tf, q, retval);    
 691 duncan   1.1.2.23          addStmt(s0);
 692 duncan   1.1.2.9       }
 693 duncan   1.1.2.9   
 694 cananian 1.1.2.84      public void visit(final harpoon.IR.Quads.SWITCH q) { 
 695 cananian 1.1.2.61          // move (possibly folded) discriminant into Temp, since we'll be
 696 cananian 1.1.2.61          // evaluating it multiple times.
 697 cananian 1.1.2.84          final Temp index = m_ctm.tempMap(q.index());
 698 cananian 1.1.2.61          addStmt(new MOVE(m_tf, q,
 699 cananian 1.1.2.61                           _TEMP(q, HClass.Int, index),
 700 cananian 1.1.2.61                           _TEMP(q.index(), q)));
 701 cananian 1.1.2.84          // sort keys by inserting into TreeMap (n ln n time)
 702 cananian 1.1.2.84          final SortedMap cases = new TreeMap();
 703 duncan   1.1.2.9           for (int i=0; i<q.keysLength(); i++) {
 704 cananian 1.1.2.84              Object chk=cases.put(new Integer(q.keys(i)), label(q.nextEdge(i)));
 705 cananian 1.3.2.1               assert chk==null : "duplicate key in switch statement!";
 706 cananian 1.1.2.84          }
 707 cananian 1.1.2.84          final Label deflabel = label(q.nextEdge(q.keysLength()));
 708 cananian 1.1.2.84          // bail out of zero-key case.
 709 cananian 1.1.2.84          if (cases.size()==0) {
 710 cananian 1.1.2.84              addStmt(new JUMP(m_tf, q, deflabel));
 711 cananian 1.1.2.84              return;
 712 cananian 1.1.2.84          }
 713 cananian 1.1.2.84          // select translation depending on size and sparsity of the keys array.
 714 cananian 1.1.2.84          // (note that we now know that keysLength() is greater than 0)
 715 cananian 1.1.2.84          int min_key = ((Integer)cases.firstKey()).intValue();
 716 cananian 1.1.2.84          int max_key = ((Integer)cases.lastKey()).intValue();
 717 cananian 1.1.2.84          double sparsity = ((double)max_key - min_key) / q.keysLength();
 718 cananian 1.1.2.84  
 719 cananian 1.1.2.84          // SWITCH TRANSLATIONS:
 720 cananian 1.1.2.84  
 721 cananian 1.1.2.84          // for small numbers of keys, it's most efficient to test each.
 722 cananian 1.1.2.84          if ( (q.keysLength() > 5/* this is a magic number*/) &&
 723 cananian 1.1.2.84               (sparsity < 3/* oh, look! another magic number! */)) {
 724 cananian 1.1.2.84              // DIRECT JUMP TABLE
 725 cananian 1.1.2.84              // first check if < min or > max (this means default!)
 726 cananian 1.1.2.84              Label l1 = new Label(), l2 = new Label(), l3 = new Label();
 727 cananian 1.1.2.84              addStmt(new CJUMP
 728 cananian 1.1.2.84                      (m_tf, q, new BINOP(m_tf, q, Type.INT, Bop.CMPLT,
 729 cananian 1.1.2.84                                          _TEMP(q, HClass.Int, index),
 730 cananian 1.1.2.84                                          new CONST(m_tf, q, min_key)),
 731 cananian 1.1.2.84                       deflabel, l1));
 732 cananian 1.1.2.84              addStmt(new LABEL(m_tf, q, l1, false));
 733 cananian 1.1.2.84              addStmt(new CJUMP
 734 cananian 1.1.2.84                      (m_tf, q, new BINOP(m_tf, q, Type.INT, Bop.CMPGT,
 735 cananian 1.1.2.84                                          _TEMP(q, HClass.Int, index),
 736 cananian 1.1.2.84                                          new CONST(m_tf, q, max_key)),
 737 cananian 1.1.2.84                       deflabel, l2));
 738 cananian 1.1.2.84              addStmt(new LABEL(m_tf, q, l2, false));
 739 cananian 1.1.2.84              // construct LabelList of possible targets
 740 cananian 1.1.2.84              LabelList targets = new LabelList(deflabel, null);
 741 cananian 1.1.2.84              for (Iterator it=cases.values().iterator(); it.hasNext(); )
 742 cananian 1.1.2.84                  targets = new LabelList((Label)it.next(), targets);
 743 cananian 1.1.2.84              // okay, do the jump!
 744 cananian 1.1.2.84              boolean pointersAreLong = Type.isDoubleWord(m_tf, Type.POINTER);
 745 cananian 1.1.2.84              addStmt(new JUMP
 746 cananian 1.1.2.84                      (m_tf, q,
 747 cananian 1.1.2.84                       makeMEM
 748 cananian 1.1.2.84                       (q, HClass.Void,
 749 cananian 1.1.2.84                        new BINOP(m_tf, q, Type.POINTER, Bop.ADD,
 750 cananian 1.1.2.84                                  new NAME(m_tf, q, l3),
 751 cananian 1.1.2.84                                  new BINOP
 752 cananian 1.1.2.84                                  (m_tf, q, Type.INT, Bop.SHL,
 753 cananian 1.1.2.84                                   new BINOP(m_tf, q, Type.INT, Bop.ADD,
 754 cananian 1.1.2.84                                             _TEMP(q, HClass.Int, index),
 755 cananian 1.1.2.84                                             new CONST(m_tf, q, -min_key)),
 756 cananian 1.1.2.84                                   new CONST(m_tf, q, pointersAreLong?3:2)))),
 757 cananian 1.1.2.84                       targets));
 758 cananian 1.1.2.84              // and lastly, emit the jump table.
 759 cananian 1.1.2.85              addStmt(new ALIGN(m_tf, q, 8/* safe alignment*/));
 760 cananian 1.1.2.84              addStmt(new LABEL(m_tf, q, l3, false));
 761 cananian 1.1.2.84              int expected=min_key;
 762 cananian 1.9                   for (Object thiscaseO : cases.entrySet()) {
 763 cananian 1.9                       Map.Entry thiscase = (Map.Entry) thiscaseO;
 764 cananian 1.1.2.84                  int thiskey = ((Integer)thiscase.getKey()).intValue();
 765 cananian 1.1.2.84                  Label thislabel = (Label)thiscase.getValue();
 766 cananian 1.1.2.84                  while (expected++ < thiskey)
 767 cananian 1.1.2.84                      addStmt(new DATUM(m_tf, q, new NAME(m_tf, q, deflabel)));
 768 cananian 1.1.2.84                  addStmt(new DATUM(m_tf, q, new NAME(m_tf, q, thislabel)));
 769 cananian 1.1.2.84              }
 770 cananian 1.6                   /* workaround AIX gcc brokenness by realigning @ end of table */
 771 cananian 1.6                   addStmt(new ALIGN(m_tf, q, 8/* big alignment */));
 772 cananian 1.6                   addStmt(new LABEL(m_tf, q, new Label(), false));
 773 cananian 1.6                   addStmt(new DATUM(m_tf, q, new CONST(m_tf, q, 1976L)));
 774 cananian 1.6                   /* end workaround */
 775 cananian 1.6       
 776 cananian 1.1.2.85              // align for code again.
 777 cananian 1.1.2.85              addStmt(new ALIGN(m_tf, q, 8/* safe alignment*/));
 778 cananian 1.1.2.84              // done
 779 cananian 1.1.2.84          } else {
 780 cananian 1.1.2.84              // BINARY-SEARCH THROUGH JUMP TABLE
 781 cananian 1.1.2.84              // this is used for sparse or small switch statements.
 782 cananian 1.1.2.84              class SwitchState { // class to help out our recursion.
 783 cananian 1.1.2.84                  private final Map.Entry[] keya = (Map.Entry[])
 784 cananian 1.1.2.84                      cases.entrySet().toArray(new Map.Entry[cases.size()]);
 785 cananian 1.1.2.84                  int key(int i) {return ((Integer)keya[i].getKey()).intValue();}
 786 cananian 1.1.2.84                  Label label(int i) { return (Label)keya[i].getValue(); }
 787 cananian 1.1.2.84  
 788 cananian 1.1.2.84                  private void emit(int low, int high) {
 789 cananian 1.1.2.84                      if (high-low < 2/*what did we say about magic numbers?*/) {
 790 cananian 1.1.2.84                          // emit simple equality checks for "small" ranges.
 791 cananian 1.1.2.84                          for (int i=low; i<=high; i++) {
 792 cananian 1.1.2.84                              Label lNext = (i!=high) ? new Label() : deflabel;
 793 cananian 1.1.2.84                              addStmt(new CJUMP
 794 cananian 1.1.2.84                                      (m_tf, q,
 795 cananian 1.1.2.84                                       new BINOP
 796 cananian 1.1.2.84                                       (m_tf, q, Type.INT, Bop.CMPEQ,
 797 cananian 1.1.2.84                                        _TEMP(q, HClass.Int, index),
 798 cananian 1.1.2.84                                        new CONST(m_tf, q, key(i))),
 799 cananian 1.1.2.84                                       label(i), lNext));
 800 cananian 1.1.2.84                              if (i!=high)
 801 cananian 1.1.2.84                                  addStmt(new LABEL(m_tf, q, lNext, false));
 802 cananian 1.1.2.84                          }
 803 cananian 1.1.2.84                      } else {
 804 cananian 1.1.2.84                          // divide and conquer for "larger" ranges.
 805 cananian 1.1.2.84                          int mid = (high+low)/2;
 806 cananian 1.1.2.84                          // emit equality test against keys(mid)
 807 cananian 1.1.2.84                          Label lNext = new Label();
 808 cananian 1.1.2.84                          addStmt(new CJUMP
 809 cananian 1.1.2.84                                  (m_tf, q,
 810 cananian 1.1.2.84                                   new BINOP
 811 cananian 1.1.2.84                                   (m_tf, q, Type.INT, Bop.CMPEQ,
 812 cananian 1.1.2.84                                    _TEMP(q, HClass.Int, index),
 813 cananian 1.1.2.84                                    new CONST(m_tf, q, key(mid))),
 814 cananian 1.1.2.84                                   label(mid), lNext));
 815 cananian 1.1.2.84                          addStmt(new LABEL(m_tf, q, lNext, false));
 816 cananian 1.1.2.84                          // apply pigeonhole principle:
 817 cananian 1.1.2.84                          boolean gtP = pigeonhole(mid+1, high);
 818 cananian 1.1.2.84                          Label gtL = gtP ? label(high) : new Label();
 819 cananian 1.1.2.84                          boolean ltP = pigeonhole(low, mid-1);
 820 cananian 1.1.2.84                          Label ltL = ltP ? label(low) : new Label();
 821 cananian 1.1.2.84                          // test lower than key
 822 cananian 1.1.2.84                          addStmt(new CJUMP
 823 cananian 1.1.2.84                                  (m_tf, q,
 824 cananian 1.1.2.84                                   new BINOP
 825 cananian 1.1.2.84                                   (m_tf, q, Type.INT, Bop.CMPLT,
 826 cananian 1.1.2.84                                    _TEMP(q, HClass.Int, index),
 827 cananian 1.1.2.84                                    new CONST(m_tf, q, key(mid))),
 828 cananian 1.1.2.84                                   /*< and > labels*/ltL, gtL));
 829 cananian 1.1.2.84                          // greater-than case
 830 cananian 1.1.2.84                          if (!gtP) { //(sometimes we can skip this)
 831 cananian 1.1.2.84                              addStmt(new LABEL(m_tf, q, gtL, false));
 832 cananian 1.1.2.84                              emit(mid+1, high); // i love recursion.
 833 cananian 1.1.2.84                          }
 834 cananian 1.1.2.84                          // less-than case
 835 cananian 1.1.2.84                          if (!ltP) { //(sometimes we can skip this)
 836 cananian 1.1.2.84                              addStmt(new LABEL(m_tf, q, ltL, false));
 837 cananian 1.1.2.84                              emit(low, mid-1); // really, i do!
 838 cananian 1.1.2.84                          }
 839 cananian 1.1.2.84                          // done!
 840 cananian 1.1.2.84                      }
 841 cananian 1.1.2.84                  }
 842 cananian 1.1.2.84                  boolean pigeonhole(int low, int high) {
 843 cananian 1.1.2.84                      // sometimes we can skip a test due to pigeonholing.
 844 cananian 1.1.2.84                      return (low==high) && (low>0) && (high < keya.length-1) &&
 845 cananian 1.1.2.84                          /*pigeonhole:*/((key(high+1) - key(low-1)) == 2);
 846 cananian 1.1.2.84                  }
 847 cananian 1.1.2.84              }
 848 cananian 1.1.2.84              // use helper to recurse, emitting the test-and-branch chains.
 849 cananian 1.1.2.84              new SwitchState().emit(0, cases.size()-1);
 850 duncan   1.1.2.9           }
 851 duncan   1.1.2.1       }
 852 duncan   1.1.2.1     
 853 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.THROW q) { 
 854 cananian 1.3.2.1           assert m_handler!=null;
 855 cananian 1.1.2.61          addStmt(new THROW(m_tf, q,
 856 cananian 1.1.2.61                            _TEMP(q.throwable(), q),
 857 cananian 1.1.2.61                            _TEMP(q, HClass.Void, m_handler)));
 858 duncan   1.1.2.9       }
 859 duncan   1.1.2.9   
 860 duncan   1.1.2.9       public void visit(harpoon.IR.Quads.TYPECAST q) {
 861 duncan   1.1.2.9           throw new Error("Use INSTANCEOF instead of TYPECAST");
 862 cananian 1.1.2.88      }
 863 cananian 1.1.2.88  
 864 cananian 1.1.2.88      public void visit(harpoon.IR.Quads.TYPESWITCH q) {
 865 cananian 1.1.2.88          throw new Error("Direct translation of TYPESWITCH is unimplemented."+
 866 cananian 1.1.2.88                          " Use TypeSwitchRemover class.");
 867 duncan   1.1.2.9       }
 868 duncan   1.1.2.9   
 869 duncan   1.1.2.9       /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
 870 duncan   1.1.2.9        *                                                          *
 871 duncan   1.1.2.9        *                   LowQuad Translator                     *
 872 duncan   1.1.2.9        *                                                          *
 873 duncan   1.1.2.9        *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 874 duncan   1.1.2.1                     
 875 duncan   1.1.2.27      public void visit(PAOFFSET q) {
 876 cananian 1.1.2.61          addMove
 877 cananian 1.1.2.61              (q, q.dst(),
 878 cananian 1.1.2.72               m_rtb.arrayOffset(m_tf, q, treeDeriv, q.arrayType(),
 879 cananian 1.1.2.61                                 _TEMPte(q.index(), q)));
 880 duncan   1.1.2.9       }
 881 duncan   1.1.2.9   
 882 duncan   1.1.2.9       public void visit(PARRAY q) {
 883 cananian 1.1.2.61          addMove
 884 cananian 1.1.2.61              (q, q.dst(),
 885 cananian 1.1.2.72               m_rtb.arrayBase(m_tf, q, treeDeriv,
 886 cananian 1.1.2.61                               _TEMPte(q.objectref(), q)));
 887 duncan   1.1.2.9       }
 888 duncan   1.1.2.9   
 889 duncan   1.1.2.23  
 890 cananian 1.1.2.50      // runtime-independent
 891 duncan   1.1.2.23      public void visit(PCALL q) { 
 892 cananian 1.1.2.61          ExpList params; Temp[] qParams;
 893 cananian 1.1.2.61          Temp retval, retex; // tree temps for destination variables
 894 cananian 1.1.2.61          TEMP retvalT, retexT; // TEMP expressions for the above.
 895 cananian 1.1.2.61          Exp func, ptr;
 896 duncan   1.1.2.9   
 897 cananian 1.3.2.1           assert q.retex()!=null && q.ptr()!=null;
 898 duncan   1.1.2.9   
 899 cananian 1.1.2.51          // If q.retval() is null, the 'retval' in Tree.CALL is also null.
 900 duncan   1.1.2.9           if (q.retval()==null) {
 901 cananian 1.1.2.51              retval = null;
 902 cananian 1.1.2.61              retvalT = null;
 903 duncan   1.1.2.9           }
 904 duncan   1.1.2.9           else {
 905 cananian 1.1.2.61              retval = m_ctm.tempMap(q.retval()); // a tree temp.
 906 cananian 1.1.2.61              // (return value should never have a derived type)
 907 cananian 1.3.2.1               assert quadDeriv.typeMap(q, q.retval())!=null;
 908 cananian 1.1.2.61              retvalT = _TEMP(q, quadDeriv.typeMap(q, q.retval()), retval);
 909 duncan   1.1.2.9           }
 910 duncan   1.1.2.4         
 911 cananian 1.1.2.61          // clone & type retex.
 912 cananian 1.1.2.61          retex = m_ctm.tempMap(q.retex());
 913 cananian 1.1.2.61          // (exception value should never have a derived type)
 914 cananian 1.3.2.1           assert quadDeriv.typeMap(q, q.retex())!=null;
 915 cananian 1.1.2.61          retexT= _TEMP(q, quadDeriv.typeMap(q, q.retex()), retex);
 916 cananian 1.1.2.61  
 917 cananian 1.1.2.61          // deal with function pointer.
 918 duncan   1.1.2.27          func  = _TEMP(q.ptr(), q);
 919 cananian 1.1.2.51          ptr = q.isVirtual() ? // extra dereference for virtual functions.
 920 cananian 1.1.2.64              (Exp) makeMEM(q, HClass.Void, func) : (Exp) func;
 921 duncan   1.1.2.23              
 922 duncan   1.1.2.9           qParams = q.params(); params = null; 
 923 duncan   1.1.2.9           for (int i=qParams.length-1; i >= 0; i--) {
 924 duncan   1.1.2.27              params = new ExpList(_TEMP(qParams[i], q), params);      
 925 duncan   1.1.2.9           }
 926 duncan   1.1.2.56  
 927 cananian 1.1.2.75          // if debugging option enabled, check that this dispatch pointer is
 928 cananian 1.1.2.75          // non-null, and call a special reporting function if it is.
 929 cananian 1.1.2.75          if (checkDispatch) {
 930 cananian 1.1.2.75              Temp pT = new Temp(m_tf.tempFactory(), "ptr");
 931 cananian 1.1.2.75              addStmt(new MOVE(m_tf, q, _TEMP(q, HClass.Void, pT), ptr));
 932 cananian 1.1.2.75              emitAssert(m_tf, q,
 933 cananian 1.1.2.75                         new BINOP(m_tf, q, Type.POINTER, Bop.CMPEQ,
 934 cananian 1.1.2.75                                   _TEMP(q, HClass.Void, pT),new CONST(m_tf, q)),
 935 cananian 1.1.2.75                         false, "method pointer != null");
 936 cananian 1.1.2.75              ptr = _TEMP(q, HClass.Void, pT);
 937 cananian 1.1.2.75          }
 938 cananian 1.1.2.61          addStmt(new CALL
 939 duncan   1.1.2.23              (m_tf, q, 
 940 cananian 1.1.2.61               retvalT, retexT,
 941 cananian 1.1.2.51               ptr, params,
 942 cananian 1.1.2.61               new NAME(m_tf, q, label(q.nextEdge(1/*exception edge*/))),
 943 cananian 1.1.2.61               q.isTailCall()));
 944 cananian 1.1.2.61          if (edgeOracle.defaultEdge(q)!=0)
 945 cananian 1.1.2.61              addStmt(new JUMP(m_tf, q, label(q.nextEdge(0))));
 946 cananian 1.1.2.61  
 947 cananian 1.1.2.61          // RESULTS OF CALLS SHOULD NEVER BE FOLDED! (assert this here?)
 948 duncan   1.1.2.9       }
 949 duncan   1.1.2.9   
 950 cananian 1.1.2.50      // just refer to the runtime's NameMap
 951 duncan   1.1.2.9       public void visit(PFCONST q) {
 952 cananian 1.1.2.61          addMove
 953 cananian 1.1.2.61              (q, q.dst(),
 954 cananian 1.1.2.44               new NAME(m_tf, q, m_nm.label(q.field())));
 955 duncan   1.1.2.9       }
 956 duncan   1.1.2.9   
 957 duncan   1.1.2.9       public void visit(PFIELD q) { 
 958 cananian 1.1.2.61          addMove
 959 cananian 1.1.2.61              (q, q.dst(),
 960 cananian 1.1.2.72               m_rtb.fieldBase(m_tf, q, treeDeriv,
 961 cananian 1.1.2.61                               _TEMPte(q.objectref(), q)));
 962 duncan   1.1.2.9       }
 963 duncan   1.1.2.1     
 964 duncan   1.1.2.9       public void visit(PFOFFSET q) {
 965 cananian 1.1.2.61          addMove
 966 cananian 1.1.2.61              (q, q.dst(),
 967 cananian 1.1.2.72               m_rtb.fieldOffset(m_tf, q, treeDeriv, q.field()));
 968 duncan   1.1.2.9       }
 969 duncan   1.1.2.9   
 970 cananian 1.1.2.50      // runtime-independent
 971 duncan   1.1.2.9       public void visit(PGET q) {
 972 cananian 1.1.2.61          MEM m = makeMEM(q, q.type(), _TEMP(q.ptr(), q));
 973 cananian 1.1.2.61          addMove(q, q.dst(), m);
 974 duncan   1.1.2.9       }
 975 duncan   1.1.2.1     
 976 cananian 1.1.2.50      // just refer to the runtime's NameMap
 977 duncan   1.1.2.9       public void visit(PMCONST q) { 
 978 cananian 1.1.2.61          addMove(q, q.dst(),
 979 cananian 1.1.2.61                  new NAME(m_tf, q, m_nm.label(q.method())));
 980 duncan   1.1.2.9       }
 981 duncan   1.1.2.9   
 982 duncan   1.1.2.9       public void visit(PMETHOD q) {
 983 cananian 1.1.2.61          addMove
 984 cananian 1.1.2.61              (q, q.dst(),
 985 cananian 1.1.2.72               m_rtb.methodBase(m_tf, q, treeDeriv,
 986 cananian 1.1.2.61                                _TEMPte(q.objectref(), q)));
 987 duncan   1.1.2.9       }
 988 duncan   1.1.2.9   
 989 duncan   1.1.2.9       public void visit(PMOFFSET q) {
 990 cananian 1.1.2.61          addMove(q, q.dst(),
 991 cananian 1.1.2.72                  m_rtb.methodOffset(m_tf, q, treeDeriv, q.method()));
 992 duncan   1.1.2.9       }
 993 duncan   1.1.2.9   
 994 duncan   1.1.2.9       public void visit(POPER q) {
 995 duncan   1.1.2.15          Exp oper = null; int optype; 
 996 duncan   1.1.2.9           Stm s0;
 997 duncan   1.1.2.9           Temp[] operands = q.operands();
 998 cananian 1.1.2.61          TEMP dst;
 999 duncan   1.1.2.1     
1000 duncan   1.1.2.9           // Convert optype to a Bop or a Uop
1001 duncan   1.1.2.9           switch(q.opcode()) {
1002 duncan   1.1.2.9           case Qop.ACMPEQ:
1003 cananian 1.1.2.94              // reference equality (unlike pointer equality) is runtime
1004 cananian 1.1.2.94              // specific (there may be pointer twiddling involved)
1005 cananian 1.1.2.94              addMove(q, q.dst(),
1006 cananian 1.1.2.94                      m_rtb.referenceEqual(m_tf, q, treeDeriv,
1007 cananian 1.1.2.94                                           _TEMPte(operands[0], q),
1008 cananian 1.1.2.94                                           _TEMPte(operands[1], q)));
1009 cananian 1.1.2.94              return;
1010 duncan   1.1.2.9           case Qop.DCMPEQ:
1011 duncan   1.1.2.9           case Qop.FCMPEQ:
1012 duncan   1.1.2.9           case Qop.ICMPEQ:
1013 duncan   1.1.2.9           case Qop.LCMPEQ:
1014 duncan   1.1.2.9           case LQop.PCMPEQ: optype = Bop.CMPEQ; break;
1015 duncan   1.1.2.9           case Qop.D2F:
1016 duncan   1.1.2.9           case Qop.I2F:
1017 duncan   1.1.2.9           case Qop.L2F: optype = Uop._2F; break;
1018 duncan   1.1.2.9           case Qop.D2I:
1019 duncan   1.1.2.9           case Qop.F2I:
1020 duncan   1.1.2.9           case Qop.L2I: optype = Uop._2I; break;
1021 duncan   1.1.2.9           case Qop.D2L:
1022 duncan   1.1.2.9           case Qop.F2L:
1023 duncan   1.1.2.9           case Qop.I2L: optype = Uop._2L; break; 
1024 cananian 1.1.2.39          case Qop.I2D:
1025 cananian 1.1.2.39          case Qop.F2D:
1026 cananian 1.1.2.39          case Qop.L2D: optype = Uop._2D; break;
1027 duncan   1.1.2.9           case Qop.DADD: 
1028 duncan   1.1.2.9           case Qop.FADD:
1029 duncan   1.1.2.9           case Qop.IADD:
1030 duncan   1.1.2.9           case Qop.LADD: 
1031 duncan   1.1.2.9           case LQop.PADD: optype = Bop.ADD; break;
1032 duncan   1.1.2.9           case Qop.DCMPGE:
1033 duncan   1.1.2.9           case Qop.FCMPGE: optype = Bop.CMPGE; break;
1034 duncan   1.1.2.9           case Qop.DCMPGT:
1035 duncan   1.1.2.9           case Qop.FCMPGT:
1036 duncan   1.1.2.9           case Qop.ICMPGT:
1037 duncan   1.1.2.9           case Qop.LCMPGT: 
1038 duncan   1.1.2.9           case LQop.PCMPGT: optype = Bop.CMPGT; break;
1039 duncan   1.1.2.9           case Qop.DDIV:
1040 duncan   1.1.2.9           case Qop.FDIV:
1041 duncan   1.1.2.9           case Qop.IDIV:
1042 duncan   1.1.2.9           case Qop.LDIV: optype = Bop.DIV; break;
1043 duncan   1.1.2.9           case Qop.DMUL:
1044 duncan   1.1.2.9           case Qop.FMUL:
1045 duncan   1.1.2.9           case Qop.IMUL:
1046 duncan   1.1.2.9           case Qop.LMUL: optype = Bop.MUL; break;
1047 duncan   1.1.2.9           case Qop.DNEG:   
1048 duncan   1.1.2.9           case Qop.FNEG: 
1049 duncan   1.1.2.9           case Qop.INEG:
1050 duncan   1.1.2.9           case Qop.LNEG:
1051 duncan   1.1.2.9           case LQop.PNEG: optype = Uop.NEG; break;
1052 duncan   1.1.2.9           case Qop.DREM:
1053 duncan   1.1.2.9           case Qop.FREM:
1054 duncan   1.1.2.9           case Qop.IREM:
1055 duncan   1.1.2.9           case Qop.LREM: optype = Bop.REM; break;
1056 cananian 1.1.2.87          case Qop.I2B: optype = Uop.I2B; break;
1057 cananian 1.1.2.87          case Qop.I2C: optype = Uop.I2C; break;
1058 cananian 1.1.2.87          case Qop.I2S: optype = Uop.I2S; break;
1059 duncan   1.1.2.9           case Qop.IAND:
1060 duncan   1.1.2.9           case Qop.LAND: optype = Bop.AND; break;
1061 duncan   1.1.2.9           case Qop.IOR:
1062 duncan   1.1.2.9           case Qop.LOR: optype = Bop.OR; break;
1063 duncan   1.1.2.9           case Qop.IXOR:
1064 duncan   1.1.2.9           case Qop.LXOR: optype = Bop.XOR; break;
1065 duncan   1.1.2.9           case Qop.ISHL:
1066 duncan   1.1.2.16          case Qop.LSHL: 
1067 duncan   1.1.2.9           case Qop.ISHR:
1068 duncan   1.1.2.16          case Qop.LSHR: 
1069 duncan   1.1.2.9           case Qop.IUSHR:
1070 duncan   1.1.2.16          case Qop.LUSHR: 
1071 duncan   1.1.2.16              visitShiftOper(q); return;  // Special case
1072 duncan   1.1.2.16          default: 
1073 cananian 1.1.2.39              throw new Error("Unknown optype in ToTree: "+q.opcode());
1074 duncan   1.1.2.9           }
1075 duncan   1.1.2.1       
1076 duncan   1.1.2.9           if (operands.length==1) {
1077 cananian 1.1.2.61              Exp op0 = _TEMP(operands[0], q);
1078 cananian 1.1.2.61              oper = new UNOP(m_tf, q, op0.type(), optype, op0);
1079 duncan   1.1.2.9           }
1080 duncan   1.1.2.9           else if (operands.length==2) {
1081 cananian 1.1.2.61              Exp op0 = _TEMP(operands[0], q), op1 = _TEMP(operands[1], q);
1082 duncan   1.1.2.9               oper = new BINOP
1083 duncan   1.1.2.15                  (m_tf, q, 
1084 cananian 1.1.2.61                   MERGE_TYPE(op0.type(), op1.type()),
1085 duncan   1.1.2.15                   optype,
1086 duncan   1.1.2.27                   op0, 
1087 duncan   1.1.2.27                   op1);
1088 duncan   1.1.2.9           }
1089 duncan   1.1.2.9           else 
1090 duncan   1.1.2.9               throw new Error("Unexpected # of operands: " + q);
1091 duncan   1.1.2.1       
1092 cananian 1.1.2.61          addMove(q, q.dst(), oper);
1093 duncan   1.1.2.16      }
1094 duncan   1.1.2.16  
1095 duncan   1.1.2.16      private void visitShiftOper(POPER q) { 
1096 cananian 1.1.2.61          int optype; OPER oper;
1097 duncan   1.1.2.17          Temp[] operands = q.operands();
1098 duncan   1.1.2.16  
1099 duncan   1.1.2.16          switch (q.opcode()) { 
1100 duncan   1.1.2.16          case Qop.ISHL:
1101 duncan   1.1.2.16          case Qop.LSHL: 
1102 duncan   1.1.2.16              optype = Bop.SHL; break;
1103 duncan   1.1.2.16          case Qop.LUSHR: 
1104 duncan   1.1.2.16          case Qop.IUSHR:
1105 duncan   1.1.2.16              optype = Bop.USHR; break;
1106 duncan   1.1.2.16          case Qop.ISHR:
1107 duncan   1.1.2.16          case Qop.LSHR: 
1108 duncan   1.1.2.16              optype = Bop.SHR; break;
1109 duncan   1.1.2.16          default: 
1110 duncan   1.1.2.16              throw new Error("Not a shift optype: " + q.opcode());
1111 duncan   1.1.2.16          }
1112 duncan   1.1.2.27  
1113 cananian 1.1.2.61          Exp op0 = _TEMP(operands[0], q), op1 = _TEMP(operands[1], q);
1114 cananian 1.1.2.61          oper = new BINOP(m_tf, q, op0.type(), optype, op0, op1);
1115 cananian 1.1.2.61          addMove(q, q.dst(), oper);
1116 duncan   1.1.2.9       }
1117 duncan   1.1.2.1     
1118 duncan   1.1.2.9       public void visit(PSET q) {
1119 cananian 1.1.2.61          Exp src = _TEMP(q.src(), q), ptr = _TEMP(q.ptr(), q);
1120 cananian 1.1.2.42          MEM m = makeMEM(q, q.type(), ptr);
1121 cananian 1.1.2.42          Stm s0 = new MOVE(m_tf, q, m, src);
1122 duncan   1.1.2.23          addStmt(s0);
1123 duncan   1.1.2.9       }
1124 duncan   1.1.2.9   
1125 duncan   1.1.2.9       /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
1126 duncan   1.1.2.9        *                                                          *
1127 duncan   1.1.2.9        *                   Utility Functions                      *
1128 duncan   1.1.2.9        *                                                          *
1129 duncan   1.1.2.9        *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1130 duncan   1.1.2.9   
1131 cananian 1.1.2.75      private void emitAssert(TreeFactory m_tf, HCodeElement src,
1132 cananian 1.1.2.75                              Exp cond, boolean condShouldBeTrue,
1133 cananian 1.1.2.75                              String assertion) {
1134 cananian 1.1.2.75          Label Lsafe = new Label(), Lunsafe = new Label();
1135 cananian 1.1.2.75          Label Lassert = new Label(), Lfile = new Label();
1136 cananian 1.1.2.75          addStmt(new CJUMP(m_tf, src, cond, 
1137 cananian 1.1.2.75                            condShouldBeTrue ? Lsafe : Lunsafe,
1138 cananian 1.1.2.75                            condShouldBeTrue ? Lunsafe : Lsafe));
1139 cananian 1.1.2.75          addStmt(new LABEL(m_tf, src, Lunsafe, false));
1140 cananian 1.1.2.75          // unsafe jump!  call reporting function.
1141 cananian 1.1.2.75          Label Lreporter = new Label(m_nm.c_function_name("__assert_fail"));
1142 cananian 1.1.2.75          addStmt(new NATIVECALL(m_tf, src, null, new NAME(m_tf, src, Lreporter),
1143 cananian 1.1.2.75                                 new ExpList
1144 cananian 1.1.2.75                                 (new NAME(m_tf, src, Lassert), new ExpList
1145 cananian 1.1.2.75                                  (new NAME(m_tf, src, Lfile), new ExpList
1146 cananian 1.1.2.75                                   (new CONST(m_tf, src, src.getLineNumber()),
1147 cananian 1.1.2.75                                    new ExpList(new CONST(m_tf, src), null))))
1148 cananian 1.1.2.75                                 ));
1149 cananian 1.1.2.75              addStmt(new LABEL(m_tf, src, Lassert, false));
1150 cananian 1.1.2.75              emitString(m_tf, src, assertion);
1151 cananian 1.1.2.75              addStmt(new LABEL(m_tf, src, Lfile, false));
1152 cananian 1.1.2.75              emitString(m_tf, src, src.getSourceFile());
1153 cananian 1.1.2.75              addStmt(new LABEL(m_tf, src, Lsafe, false));
1154 cananian 1.1.2.101     }
1155 cananian 1.1.2.101     private void emitDebug(TreeFactory m_tf, HCodeElement src, String message){
1156 cananian 1.1.2.101         Label Lmessage = new Label(), Lcontinuation = new Label();
1157 cananian 1.1.2.101         Label Lprinter = new Label(m_nm.c_function_name("puts"));
1158 cananian 1.1.2.101         addStmt(new NATIVECALL(m_tf, src, null, new NAME(m_tf, src, Lprinter),
1159 cananian 1.1.2.101                                new ExpList
1160 cananian 1.1.2.101                                    (new NAME(m_tf, src, Lmessage), null)));
1161 cananian 1.1.2.101         addStmt(new JUMP(m_tf, src, Lcontinuation));
1162 cananian 1.1.2.101         addStmt(new LABEL(m_tf, src, Lmessage, false));
1163 cananian 1.1.2.101         // puts includes a trailing newline, so we don't have to add it
1164 cananian 1.1.2.101         // to message.
1165 cananian 1.1.2.101         emitString(m_tf, src, message);
1166 cananian 1.1.2.101         addStmt(new LABEL(m_tf, src, Lcontinuation, false));
1167 cananian 1.1.2.75      }
1168 cananian 1.1.2.75      private void emitString(TreeFactory m_tf, HCodeElement src, String s) {
1169 cananian 1.1.2.75          for (int i=0; i<s.length(); i++)
1170 cananian 1.1.2.75              addStmt(new DATUM(m_tf, src, new CONST(m_tf, src, 8, false,
1171 cananian 1.1.2.75                                                     (int) s.charAt(i))));
1172 cananian 1.1.2.75          // null-terminate:
1173 cananian 1.1.2.75          addStmt(new DATUM(m_tf, src, new CONST(m_tf, src, 8, false, 0)));
1174 cananian 1.1.2.75          // align to proper word boundary.  (be safe, align 8)
1175 cananian 1.1.2.75          addStmt(new ALIGN(m_tf, src, 8));
1176 cananian 1.1.2.76      }
1177 cananian 1.1.2.76      // do appropriate temp mapping on allocationproperties object
1178 cananian 1.1.2.76      private AllocationProperties MAP(final AllocationProperties ap) {
1179 cananian 1.1.2.76          if (ap.allocationHeap()==null) return ap;
1180 cananian 1.1.2.77          else return new AllocationPropertiesImpl(ap, m_ctm);
1181 cananian 1.1.2.75      }
1182 cananian 1.1.2.75                             
1183 duncan   1.1.2.23      private void addStmt(Stm stm) { 
1184 duncan   1.1.2.23          m_stmList.add(stm);
1185 duncan   1.1.2.9       }
1186 duncan   1.1.2.9   
1187 cananian 1.1.2.61      // foldable _TEMP
1188 cananian 1.1.2.61      private Translation.Exp _TEMPte(Temp quadTemp, Quad useSite) {
1189 cananian 1.1.2.61          // this constructor takes quad temps.
1190 cananian 1.3.2.1           assert quadTemp.tempFactory()!=m_tf.tempFactory() : "Temp should be from LowQuad factory, not Tree factory.";
1191 cananian 1.1.2.61          // use reachingDefs to find definition sites.
1192 cananian 1.1.2.61          Set defSites = reachingDefs.reachingDefs(useSite, quadTemp);
1193 cananian 1.1.2.66          if (defSites.size()==1) {
1194 cananian 1.1.2.66              HCodeElement hce = (HCodeElement) defSites.iterator().next();
1195 cananian 1.1.2.68              if (foldNanny.canFold(hce, quadTemp)) {
1196 cananian 1.1.2.66                  // fold this use!
1197 cananian 1.3.2.1                   assert foldMap.containsKey(Default.pair(hce,quadTemp));
1198 cananian 1.1.2.66                  return (Translation.Exp)
1199 cananian 1.1.2.66                      foldMap.remove(Default.pair(hce,quadTemp));
1200 cananian 1.1.2.68              }
1201 cananian 1.1.2.66          }
1202 cananian 1.1.2.61          TypeBundle tb = mergeTypes(quadTemp, defSites);
1203 cananian 1.1.2.61          Temp treeTemp = m_ctm.tempMap(quadTemp);
1204 cananian 1.1.2.61          TEMP result = new TEMP(m_tf, useSite, tb.simpleType, treeTemp);
1205 cananian 1.1.2.61          if (tb.classType!=null)
1206 cananian 1.1.2.61              treeDeriv.putTypeAndTemp(result, tb.classType, treeTemp);
1207 cananian 1.1.2.61          else
1208 cananian 1.1.2.61              treeDeriv.putDerivation(result, tb.derivation);
1209 cananian 1.1.2.66          return new Translation.Ex(result);
1210 cananian 1.1.2.66      }
1211 cananian 1.1.2.66      // creates a properly typed TEMP -- may fold this use!
1212 cananian 1.1.2.66      private Exp _TEMP(Temp quadTemp, Quad useSite) {
1213 cananian 1.1.2.66          return _TEMPte(quadTemp, useSite).unEx(m_tf);
1214 duncan   1.1.2.4       }
1215 cananian 1.1.2.61      private TEMP _TEMP(HCodeElement src, HClass type, Temp treeTemp) {
1216 cananian 1.1.2.61          // this constructor takes TreeTemps.
1217 cananian 1.3.2.1           assert treeTemp.tempFactory()==m_tf.tempFactory() : "Temp should be from Tree factory.";
1218 cananian 1.1.2.61          TEMP result = new TEMP(m_tf, src, TYPE(type), treeTemp);
1219 cananian 1.1.2.61          treeDeriv.putTypeAndTemp(result, type, treeTemp);
1220 cananian 1.1.2.61          return result;
1221 cananian 1.1.2.61      }
1222 cananian 1.1.2.61      private TEMP _TEMP(HCodeElement src, DList deriv, Temp treeTemp) {
1223 cananian 1.1.2.61          // this constructor takes TreeTemps.
1224 cananian 1.3.2.1           assert treeTemp.tempFactory()==m_tf.tempFactory() : "Temp should be from Tree factory.";
1225 cananian 1.1.2.61          TEMP result = new TEMP(m_tf, src, Type.POINTER, treeTemp);
1226 cananian 1.1.2.61          treeDeriv.putDerivation(result, deriv);
1227 cananian 1.1.2.61          return result;
1228 cananian 1.1.2.61      }
1229 cananian 1.1.2.66      // make a move.  unless, of course, the expression should be folded.
1230 cananian 1.1.2.61      private void addMove(Quad defSite, Temp quadTemp, Translation.Exp value) {
1231 cananian 1.1.2.61          // this constructor takes quad temps.
1232 cananian 1.3.2.1           assert quadTemp.tempFactory()!=m_tf.tempFactory() : "Temp should be from LowQuad factory, not Tree factory.";
1233 cananian 1.1.2.66          if (foldNanny.canFold(defSite, quadTemp)) {
1234 cananian 1.3.2.1               assert !foldMap.containsKey(Default.pair(defSite, quadTemp));
1235 cananian 1.1.2.66              foldMap.put(Default.pair(defSite, quadTemp), value);
1236 cananian 1.1.2.66              return;
1237 cananian 1.1.2.66          }
1238 cananian 1.1.2.66          // otherwise... make Tree.MOVE
1239 cananian 1.1.2.61          HClass type = quadDeriv.typeMap(defSite, quadTemp);
1240 cananian 1.1.2.61          Temp treeTemp = m_ctm.tempMap(quadTemp);
1241 cananian 1.1.2.61          TEMP dst = new TEMP(m_tf, defSite, TYPE(type), treeTemp);
1242 cananian 1.1.2.66          MOVE m = new MOVE(m_tf, defSite, dst, value.unEx(m_tf));
1243 cananian 1.1.2.61          if (type!=null)
1244 cananian 1.1.2.61              treeDeriv.putTypeAndTemp(dst, type, treeTemp);
1245 cananian 1.1.2.61          else
1246 cananian 1.1.2.61              treeDeriv.putDerivation(dst, 
1247 cananian 1.1.2.97                                      DList.rename(quadDeriv.derivation(defSite, quadTemp),m_ctm));
1248 cananian 1.1.2.61          addStmt(m);
1249 cananian 1.1.2.66          return;
1250 cananian 1.1.2.66      }
1251 cananian 1.1.2.66      private void addMove(Quad defSite, Temp quadTemp, Exp value) {
1252 cananian 1.1.2.66          addMove(defSite, quadTemp, new Translation.Ex(value));
1253 duncan   1.1.2.9       }
1254 cananian 1.1.2.66      // storage for folded definitions.
1255 cananian 1.1.2.66      private final Map foldMap = new HashMap();
1256 duncan   1.1.2.9   
1257 cananian 1.1.2.61      private TypeBundle mergeTypes(Temp t, Set defSites) {
1258 cananian 1.7               assert defSites.size() > 0: "undefined temp "+t+" : "+defSites;
1259 cananian 1.1.2.61          
1260 cananian 1.1.2.61          TypeBundle tb = null;
1261 cananian 1.9               for (Object defO : defSites) {
1262 cananian 1.9                   Quad def = (Quad) defO;
1263 cananian 1.1.2.61              TypeBundle tb2 = (quadDeriv.typeMap(def, t)!=null) ?
1264 cananian 1.1.2.61                  new TypeBundle(quadDeriv.typeMap(def, t)) :
1265 cananian 1.1.2.97                  new TypeBundle(DList.rename(quadDeriv.derivation(def, t),m_ctm));
1266 cananian 1.1.2.61              tb = (tb==null) ? tb2 : tb.merge(tb2);
1267 cananian 1.1.2.61          }
1268 cananian 1.1.2.61          return tb;
1269 duncan   1.1.2.9       }
1270 duncan   1.1.2.9   
1271 cananian 1.1.2.42      // make a properly-sized MEM
1272 cananian 1.1.2.42      private MEM makeMEM(HCodeElement source, HClass type, Exp ptr) {
1273 cananian 1.1.2.64          MEM result;
1274 cananian 1.1.2.42          if (type.equals(HClass.Boolean) || type.equals(HClass.Byte))
1275 cananian 1.1.2.64              result = new MEM(m_tf, source, 8, true, ptr);
1276 cananian 1.1.2.64          else if (type.equals(HClass.Char))
1277 cananian 1.1.2.64              result = new MEM(m_tf, source, 16, false, ptr);
1278 cananian 1.1.2.64          else if (type.equals(HClass.Short))
1279 cananian 1.1.2.64              result = new MEM(m_tf, source, 16, true, ptr);
1280 cananian 1.1.2.64          else
1281 cananian 1.1.2.64              result = new MEM(m_tf, source, maptype(type), ptr);
1282 cananian 1.1.2.64          treeDeriv.putType(result, type);// update type information!
1283 cananian 1.1.2.64          return result;
1284 cananian 1.1.2.42      }
1285 cananian 1.1.2.42  
1286 duncan   1.1.2.15      // Implmentation of binary numeric promotion found in the Java
1287 duncan   1.1.2.15      // language spec. 
1288 duncan   1.1.2.15      private int MERGE_TYPE(int type1, int type2) { 
1289 duncan   1.1.2.29          boolean longptrs = m_tf.getFrame().pointersAreLong();
1290 duncan   1.1.2.15          if (type1==type2) return type1;
1291 duncan   1.1.2.15          else { 
1292 duncan   1.1.2.15              if (type1==Type.DOUBLE || type2==Type.DOUBLE) { 
1293 cananian 1.3.2.1                   assert type1!=Type.POINTER && type2!=Type.POINTER;
1294 duncan   1.1.2.15                  return Type.DOUBLE;
1295 duncan   1.1.2.15              }
1296 duncan   1.1.2.15              else if (type1==Type.FLOAT || type2==Type.FLOAT) { 
1297 cananian 1.3.2.1                   assert type1!=Type.POINTER && type2!=Type.POINTER;
1298 duncan   1.1.2.15                  return Type.FLOAT;
1299 duncan   1.1.2.15              }
1300 duncan   1.1.2.15              else if (type1==Type.LONG || type2==Type.LONG) { 
1301 duncan   1.1.2.15                  if (type1==Type.POINTER || type2==Type.POINTER) { 
1302 cananian 1.3.2.1                       assert longptrs; return Type.POINTER;
1303 duncan   1.1.2.15                  }
1304 duncan   1.1.2.15                  return Type.LONG;
1305 duncan   1.1.2.15              }
1306 duncan   1.1.2.15              else if (type1==Type.POINTER || type2==Type.POINTER) { 
1307 duncan   1.1.2.15                  return Type.POINTER;
1308 duncan   1.1.2.15              }
1309 duncan   1.1.2.15              else {
1310 duncan   1.1.2.15                  return Type.INT;  // Should not get this far
1311 duncan   1.1.2.15              }
1312 duncan   1.1.2.15          }
1313 duncan   1.1.2.15      }
1314 duncan   1.1.2.15  
1315 cananian 1.1.2.85      /** Return the sizeof a given type. */
1316 cananian 1.1.2.85      private int sizeof(HClass type) {
1317 cananian 1.1.2.85          if (type==HClass.Boolean || type==HClass.Byte) return 1;
1318 cananian 1.1.2.85          if (type==HClass.Char || type==HClass.Short) return 2;
1319 cananian 1.1.2.85          if (type==HClass.Int || type==HClass.Float) return 4;
1320 cananian 1.1.2.85          if (type==HClass.Long|| type==HClass.Double) return 8;
1321 cananian 1.1.2.85          return Type.isDoubleWord(m_tf, Type.POINTER) ? 8 : 4;
1322 cananian 1.1.2.85      }
1323 cananian 1.1.2.85      /** map constant value into precisely-typed CONST expression */
1324 cananian 1.1.2.85      // (string initializers are not allowed)
1325 cananian 1.1.2.85      private CONST _CONST(HCodeElement src, HClass type, Object value) {
1326 cananian 1.1.2.85          if (type==HClass.Void) return new CONST(m_tf, src); // null constant
1327 cananian 1.1.2.85          // sub-int types seen in ARRAYINIT
1328 cananian 1.1.2.85          if (type==HClass.Boolean)
1329 cananian 1.1.2.85              return new CONST(m_tf, src, 8/*booleans are bytes*/, false,
1330 cananian 1.1.2.85                               ((Boolean)value).booleanValue()?1:0);
1331 cananian 1.1.2.85          if (type==HClass.Byte)
1332 cananian 1.1.2.85              return new CONST(m_tf, src, 8, true, ((Byte)value).intValue());
1333 cananian 1.1.2.85          if (type==HClass.Char)
1334 cananian 1.1.2.85              return new CONST(m_tf, src, 16, false, (int)
1335 cananian 1.1.2.85                               ((Character)value).charValue());
1336 cananian 1.1.2.85          if (type==HClass.Short)
1337 cananian 1.1.2.85              return new CONST(m_tf, src, 16, true, ((Short)value).intValue());
1338 cananian 1.1.2.85          if (type==HClass.Int)
1339 cananian 1.1.2.85              return new CONST(m_tf, src, ((Integer)value).intValue());
1340 cananian 1.1.2.85          if (type==HClass.Long)
1341 cananian 1.1.2.85              return new CONST(m_tf, src, ((Long)value).longValue());
1342 cananian 1.1.2.85          if (type==HClass.Float)
1343 cananian 1.1.2.85              return new CONST(m_tf, src, ((Float)value).floatValue());
1344 cananian 1.1.2.85          if (type==HClass.Double)
1345 cananian 1.1.2.85              return new CONST(m_tf, src, ((Double)value).doubleValue());
1346 cananian 1.1.2.85          throw new Error("Bad type for CONST: " + type);
1347 cananian 1.1.2.85      }
1348 cananian 1.1.2.85      /** map constant value into (non-precisely-typed) CONST expression */
1349 cananian 1.1.2.69      private Translation.Exp mapconst(HCodeElement src,
1350 cananian 1.1.2.69                                       Object value, HClass type) {
1351 duncan   1.1.2.9           Exp constant;
1352 duncan   1.1.2.9   
1353 duncan   1.1.2.15          if (type==HClass.Void) // HClass.Void reserved for null constants
1354 duncan   1.1.2.32              constant = new CONST(m_tf, src);
1355 cananian 1.1.2.40          /* CSA: Sub-int types only seen in ARRAYINIT */
1356 duncan   1.1.2.15          else if (type==HClass.Boolean)
1357 cananian 1.1.2.69              return new ExCONST
1358 duncan   1.1.2.9                   (m_tf, src, ((Boolean)value).booleanValue()?1:0);
1359 duncan   1.1.2.9           else if (type==HClass.Byte)
1360 cananian 1.1.2.69              return new ExCONST(m_tf, src, ((Byte)value).intValue()); 
1361 duncan   1.1.2.9           else if (type==HClass.Char)
1362 cananian 1.1.2.69              return new ExCONST 
1363 duncan   1.1.2.9                   (m_tf, src, 
1364 duncan   1.1.2.13                   (int)(((Character)value).charValue())); 
1365 duncan   1.1.2.9           else if (type==HClass.Short)
1366 cananian 1.1.2.69              return new ExCONST(m_tf, src, ((Short)value).intValue()); 
1367 duncan   1.1.2.9           else if(type==HClass.Int) 
1368 cananian 1.1.2.69              return new ExCONST(m_tf, src, ((Integer)value).intValue()); 
1369 duncan   1.1.2.9           else if (type==HClass.Long)
1370 duncan   1.1.2.9               constant = new CONST(m_tf, src, ((Long)value).longValue());
1371 duncan   1.1.2.9           else if (type==HClass.Float)
1372 duncan   1.1.2.9               constant = new CONST(m_tf, src, ((Float)value).floatValue()); 
1373 duncan   1.1.2.9           else if (type==HClass.Double)
1374 duncan   1.1.2.9               constant = new CONST(m_tf, src, ((Double)value).doubleValue());
1375 cananian 1.1.2.74          else if (type.getName().equals("java.lang.String"))
1376 cananian 1.1.2.72              return m_rtb.stringConst(m_tf, src, treeDeriv, (String)value);
1377 cananian 1.1.2.89          else if (type.getName().equals("java.lang.Class"))
1378 cananian 1.1.2.89              return m_rtb.classConst(m_tf, src, treeDeriv, (HClass)value);
1379 cananian 1.1.2.89          else if (type.getName().equals("java.lang.reflect.Field"))
1380 cananian 1.1.2.89              return m_rtb.fieldConst(m_tf, src, treeDeriv, (HField)value);
1381 cananian 1.1.2.89          else if (type.getName().equals("java.lang.reflect.Method"))
1382 cananian 1.1.2.89              return m_rtb.methodConst(m_tf, src, treeDeriv, (HMethod)value);
1383 duncan   1.1.2.9           else 
1384 cananian 1.1.2.40              throw new Error("Bad type for CONST: " + type); 
1385 cananian 1.1.2.69          return new Translation.Ex(constant);
1386 cananian 1.1.2.69      }
1387 cananian 1.1.2.69      private static class ExCONST extends Translation.Ex {
1388 cananian 1.1.2.69          final int val;
1389 cananian 1.1.2.69          public ExCONST(TreeFactory tf, HCodeElement src, int val) {
1390 cananian 1.1.2.69              super(new CONST(tf, src, val));
1391 cananian 1.1.2.69              this.val = val;
1392 cananian 1.1.2.69          }
1393 cananian 1.1.2.69          protected Stm unCxImpl(TreeFactory tf, Label iftrue, Label iffalse) {
1394 cananian 1.1.2.69              if (val==0) return new JUMP(tf, exp, iffalse);
1395 cananian 1.1.2.69              else return new JUMP(tf, exp, iftrue);
1396 cananian 1.1.2.69          }
1397 cananian 1.1.2.52      }
1398 cananian 1.1.2.52      private CONST constZero(HCodeElement src, HClass type) {
1399 cananian 1.1.2.52          if (type==HClass.Boolean || type==HClass.Byte ||
1400 cananian 1.1.2.52              type==HClass.Char || type==HClass.Short ||
1401 cananian 1.1.2.52              type==HClass.Int) 
1402 cananian 1.1.2.52              return new CONST(m_tf, src, (int)0);
1403 cananian 1.1.2.52          else if (type==HClass.Long)
1404 cananian 1.1.2.52              return new CONST(m_tf, src, (long)0);
1405 cananian 1.1.2.52          else if (type==HClass.Float)
1406 cananian 1.1.2.52              return new CONST(m_tf, src, (float)0);
1407 cananian 1.1.2.52          else if (type==HClass.Double)
1408 cananian 1.1.2.52              return new CONST(m_tf, src, (double)0);
1409 cananian 1.1.2.52          else
1410 cananian 1.1.2.52              return new CONST(m_tf, src); // null.
1411 duncan   1.1.2.9       }
1412 duncan   1.1.2.9   }
1413 duncan   1.1.2.9   
1414 duncan   1.1.2.23  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1415 duncan   1.1.2.23  //                                                            //
1416 cananian 1.1.2.61  //                    Utility classes                         //
1417 duncan   1.1.2.23  //                                                            //
1418 duncan   1.1.2.27  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
1419 duncan   1.1.2.23  
1420 cananian 1.1.2.65      /** An edge oracle tells you which edge out of an
1421 cananian 1.1.2.65       *  <code>HCodeElement</code> wants to be the default
1422 cananian 1.1.2.65       *  (ie, non-branching) edge. */
1423 cananian 1.1.2.65      static interface EdgeOracle {
1424 cananian 1.1.2.61          public int defaultEdge(HCodeElement hce);
1425 duncan   1.1.2.27      }
1426 cananian 1.1.2.65      /** A fold nanny tells you whether or not you can fold a
1427 cananian 1.1.2.65       *  particular definition of a <code>Temp</code>. */
1428 cananian 1.1.2.65      static interface FoldNanny {
1429 cananian 1.1.2.65          public boolean canFold(HCodeElement defSite, Temp t);
1430 cananian 1.1.2.65      }
1431 duncan   1.1.2.27          
1432 cananian 1.1.2.65      /** A <code>TypeBundle</code> rolls together the <code>HClass</code>
1433 cananian 1.1.2.65       *  type or <code>DList</code> derivation of a value, along with
1434 cananian 1.1.2.65       *  the integer <code>Tree.Type</code>. */
1435 cananian 1.1.2.61      private static class TypeBundle {
1436 cananian 1.1.2.61          final int simpleType;
1437 cananian 1.1.2.61          final HClass classType;
1438 cananian 1.1.2.61          final DList derivation;
1439 cananian 1.1.2.61          TypeBundle(HClass hc) {
1440 cananian 1.1.2.61              this.simpleType = TYPE(hc);
1441 cananian 1.1.2.61              this.classType = hc;
1442 cananian 1.1.2.61              this.derivation = null;
1443 cananian 1.1.2.61          }
1444 cananian 1.1.2.61          TypeBundle(DList deriv) {
1445 cananian 1.1.2.61              this.simpleType = Type.POINTER;
1446 cananian 1.1.2.61              this.classType = null;
1447 cananian 1.1.2.61              this.derivation = deriv;
1448 cananian 1.1.2.61          }
1449 cananian 1.1.2.61          TypeBundle merge(TypeBundle tb) {
1450 cananian 1.1.2.61              if (this.derivation!=null) {
1451 cananian 1.3.2.1                   assert this.equals(tb);
1452 cananian 1.1.2.61                  return this;
1453 cananian 1.1.2.61              }
1454 cananian 1.3.2.1               assert false;return null;
1455 duncan   1.1.2.27          }
1456 cananian 1.1.2.61          public boolean equals(Object o) {
1457 cananian 1.1.2.61              if (!(o instanceof TypeBundle)) return false;
1458 cananian 1.1.2.61              TypeBundle tb = (TypeBundle) o;
1459 cananian 1.1.2.61              if (this.simpleType != tb.simpleType) return false;
1460 cananian 1.1.2.61              if (this.classType != null)
1461 cananian 1.1.2.61                  return (this.classType == tb.classType);
1462 cananian 1.3.2.1               assert this.derivation != null;
1463 cananian 1.1.2.61              if (tb.derivation == null) return false;
1464 cananian 1.1.2.61              return this.derivation.equals(tb.derivation);
1465 duncan   1.1.2.27          }
1466 duncan   1.1.2.27      }
1467 duncan   1.1.2.5   
1468 cananian 1.1.2.61      // UTILITY METHODS........
1469 duncan   1.1.2.23  
1470 cananian 1.1.2.61      private static int TYPE(HClass hc) { 
1471 cananian 1.1.2.61          if (hc==null || hc==HClass.Void) return Type.POINTER;
1472 cananian 1.1.2.61          return maptype(hc);
1473 duncan   1.1.2.9       }
1474 duncan   1.1.2.23  
1475 cananian 1.1.2.61      private static int maptype(HClass hc) {
1476 cananian 1.1.2.61          if (hc==HClass.Boolean ||
1477 cananian 1.1.2.61              hc==HClass.Byte    ||
1478 cananian 1.1.2.61              hc==HClass.Char    ||
1479 cananian 1.1.2.61              hc==HClass.Short   ||
1480 cananian 1.1.2.61              hc==HClass.Int)          return Type.INT;
1481 cananian 1.1.2.61          else if (hc==HClass.Long)    return Type.LONG;
1482 cananian 1.1.2.61          else if (hc==HClass.Float)   return Type.FLOAT;
1483 cananian 1.1.2.61          else if (hc==HClass.Double)  return Type.DOUBLE;
1484 cananian 1.1.2.61          else                         return Type.POINTER;
1485 duncan   1.1.2.27      }
1486 cananian 1.1.2.48  
1487 cananian 1.2       } // end of public class ToTree