1 cananian 1.1.2.1  // Translate.java, created Fri Jan 22 17:07:31 1999 by cananian
  2 cananian 1.1.2.1  // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.1  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1  package harpoon.IR.LowQuad;
  5 cananian 1.1.2.1  
  6 cananian 1.1.2.22 import harpoon.Analysis.AllocationInformationMap;
  7 cananian 1.1.2.22 import harpoon.Analysis.Maps.AllocationInformation;
  8 cananian 1.1.2.19 import harpoon.Analysis.Maps.Derivation.DList;
  9 cananian 1.1.2.2  import harpoon.Analysis.Maps.TypeMap;
 10 cananian 1.1.2.2  import harpoon.Backend.Maps.FinalMap;
 11 cananian 1.1.2.2  import harpoon.ClassFile.HClass;
 12 duncan   1.1.2.9  import harpoon.ClassFile.HCodeElement;
 13 cananian 1.1.2.22 import harpoon.IR.Quads.ANEW;
 14 cananian 1.1.2.2  import harpoon.IR.Quads.Edge;
 15 cananian 1.1.2.22 import harpoon.IR.Quads.NEW;
 16 cananian 1.1.2.1  import harpoon.IR.Quads.Quad;
 17 cananian 1.1.2.2  import harpoon.IR.Quads.QuadVisitor;
 18 cananian 1.1.2.4  import harpoon.Temp.CloningTempMap;
 19 cananian 1.1.2.2  import harpoon.Temp.Temp;
 20 cananian 1.1.2.2  import harpoon.Temp.TempMap;
 21 duncan   1.1.2.5  import harpoon.Util.Util;
 22 cananian 1.1.2.1  
 23 duncan   1.1.2.8  import java.util.HashMap;
 24 duncan   1.1.2.8  import java.util.Iterator; 
 25 duncan   1.1.2.8  import java.util.Map;
 26 duncan   1.1.2.8  
 27 cananian 1.1.2.1  /**
 28 cananian 1.1.2.1   * <code>Translate</code> is a utility class which implements the 
 29 cananian 1.1.2.10  * <code>QuadSSI</code>/<code>QuadNoSSA</code> to 
 30 cananian 1.1.2.21  * <code>LowQuadSSI</code>/<code>LowQuadNoSSA</code> translation.
 31 cananian 1.1.2.1   * 
 32 cananian 1.1.2.1   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 33 cananian 1.3       * @version $Id: Translate.java,v 1.3 2002/09/10 15:06:55 cananian Exp $
 34 cananian 1.1.2.1   */
 35 duncan   1.1.2.5  final class Translate { // not public
 36 cananian 1.1.2.1      public static final Quad translate(final LowQuadFactory qf,
 37 cananian 1.1.2.3                                         final harpoon.IR.Quads.Code code,
 38 cananian 1.1.2.2                                         TypeMap tym, FinalMap fm,
 39 duncan   1.1.2.8                                         Map derivationTable,
 40 cananian 1.1.2.22                                        Map typeTable,
 41 cananian 1.1.2.22                                        AllocationInformationMap allocInfo) {
 42 cananian 1.1.2.2          final Quad old_header = (Quad) code.getRootElement();
 43 cananian 1.1.2.2          final CloningTempMap ctm =
 44 cananian 1.1.2.2              new CloningTempMap(old_header.getFactory().tempFactory(),
 45 cananian 1.1.2.2                                 qf.tempFactory());
 46 cananian 1.1.2.2          final LowQuadMap lqm = new LowQuadMap();
 47 cananian 1.1.2.2          final Visitor v = new Visitor(qf, lqm, ctm, code, tym, fm,
 48 cananian 1.1.2.22                                       derivationTable, typeTable, allocInfo);
 49 cananian 1.1.2.2  
 50 cananian 1.1.2.2          // visit all.
 51 duncan   1.1.2.8          for (Iterator i = code.getElementsI(); i.hasNext(); ) 
 52 cananian 1.1.2.11             ((Quad)i.next()).accept(v);
 53 cananian 1.1.2.2          // now qm contains mappings from old to new, we just have to link them
 54 duncan   1.1.2.8          for (Iterator i = code.getElementsI(); i.hasNext(); ) {
 55 duncan   1.1.2.8              Quad old = (Quad)i.next();
 56 cananian 1.1.2.2              // link next
 57 cananian 1.1.2.2              Edge[] el = old.nextEdge();
 58 duncan   1.1.2.8              for (int n=0; n<el.length; n++)
 59 duncan   1.1.2.8                  Quad.addEdge(lqm.getFoot((Quad)el[n].from()),
 60 duncan   1.1.2.8                               el[n].which_succ(),
 61 duncan   1.1.2.8                               lqm.getHead((Quad)el[n].to()),
 62 duncan   1.1.2.8                               el[n].which_pred());
 63 cananian 1.1.2.2          }
 64 cananian 1.1.2.2          // return new header.
 65 cananian 1.1.2.2          return lqm.getHead(old_header);
 66 cananian 1.1.2.2      }
 67 cananian 1.1.2.2  
 68 cananian 1.1.2.2      private static class LowQuadMap {
 69 duncan   1.1.2.8          final private Map h  = new HashMap();
 70 duncan   1.1.2.5          void put(Quad old, Quad new_header, Quad new_footer) {
 71 cananian 1.1.2.2              h.put(old, new Quad[] { new_header, new_footer });
 72 cananian 1.1.2.2          }
 73 cananian 1.1.2.2          Quad getHead(Quad old) {
 74 cananian 1.1.2.2              Quad[] ql = (Quad[])h.get(old); return (ql==null)?null:ql[0];
 75 cananian 1.1.2.2          }
 76 cananian 1.1.2.2          Quad getFoot(Quad old) {
 77 cananian 1.1.2.2              Quad[] ql = (Quad[])h.get(old); return (ql==null)?null:ql[1];
 78 cananian 1.1.2.2          }
 79 duncan   1.1.2.5          
 80 cananian 1.1.2.2          boolean contains(Quad old) { return h.containsKey(old); }
 81 cananian 1.1.2.2      }
 82 cananian 1.1.2.2  
 83 cananian 1.1.2.2      private static final class Visitor extends QuadVisitor {
 84 cananian 1.1.2.2          final LowQuadFactory qf;
 85 cananian 1.1.2.2          final LowQuadMap lqm;
 86 cananian 1.1.2.2          final CloningTempMap ctm;
 87 cananian 1.1.2.3          final harpoon.IR.Quads.Code code;
 88 cananian 1.1.2.2          final TypeMap tym;
 89 cananian 1.1.2.2          final FinalMap fm;
 90 duncan   1.1.2.8          final Map dT, tT;
 91 cananian 1.1.2.22         final AllocationInformation oldai;
 92 cananian 1.1.2.22         final AllocationInformationMap aim;
 93 cananian 1.1.2.2  
 94 cananian 1.1.2.2          Visitor(LowQuadFactory qf, LowQuadMap lqm, CloningTempMap ctm,
 95 cananian 1.1.2.3                  harpoon.IR.Quads.Code code, TypeMap tym, FinalMap fm,
 96 cananian 1.1.2.22                 Map dT, Map tT, AllocationInformationMap aim) {
 97 cananian 1.1.2.2              this.qf = qf; this.lqm = lqm; this.ctm = ctm;
 98 cananian 1.1.2.2              this.code = code; this.tym = tym; this.fm = fm; this.dT = dT;
 99 duncan   1.1.2.5              this.tT = tT;
100 cananian 1.1.2.22             this.oldai = code.getAllocationInformation(); this.aim = aim;
101 cananian 1.1.2.2          }
102 duncan   1.1.2.5  
103 duncan   1.1.2.5          private void updateTypeInfo(Quad q) {
104 cananian 1.1.2.18             Temp[] defs = q.def();
105 cananian 1.1.2.18             for (int i=0; i<defs.length; i++)
106 cananian 1.1.2.18                 tT.put(map(defs[i]), tym.typeMap(q, defs[i]));
107 duncan   1.1.2.5          }
108 duncan   1.1.2.5  
109 cananian 1.1.2.2          /** By default, just clone and set all destinations to top. */
110 cananian 1.1.2.2          public void visit(Quad q) {
111 cananian 1.1.2.2              Quad nq = (Quad) q.clone(qf, ctm);
112 cananian 1.1.2.2              lqm.put(q, nq, nq);
113 duncan   1.1.2.5              updateTypeInfo(q);
114 cananian 1.1.2.22             if (oldai!=null && (q instanceof ANEW || q instanceof NEW))
115 cananian 1.1.2.22                 aim.transfer(nq, q, ctm, oldai);
116 cananian 1.1.2.2          }
117 duncan   1.1.2.5  
118 cananian 1.1.2.2          // take apart array references.
119 cananian 1.1.2.2          public final void visit(harpoon.IR.Quads.AGET q) {
120 cananian 1.1.2.2              Quad q0 = new PARRAY(qf, q, extra(q.objectref()),
121 cananian 1.1.2.2                                   map(q.objectref()));
122 duncan   1.1.2.9              Quad q1 = new PAOFFSET(qf,q,extra(q.index()),type(q,q.objectref()),
123 cananian 1.1.2.2                                     map(q.index()));
124 cananian 1.1.2.2              Quad q2 = new POPER(qf, q, LQop.PADD, extra(q.objectref()),
125 cananian 1.1.2.2                                  new Temp[] { q0.def()[0], q1.def()[0] });
126 cananian 1.1.2.12             Quad q3 = new PGET(qf, q, map(q.dst()), q2.def()[0],
127 cananian 1.1.2.12                                type(q,q.objectref()).getComponentType());
128 cananian 1.1.2.2              Quad.addEdges(new Quad[] { q0, q1, q2, q3 });
129 cananian 1.1.2.2              lqm.put(q, q0, q3);
130 cananian 1.1.2.2              // update derivation table.
131 cananian 1.1.2.2              DList dl = new DList(map(q.objectref()), true, null);
132 cananian 1.1.2.2              dT.put(q0.def()[0], dl);
133 cananian 1.1.2.2              dT.put(q2.def()[0], dl);
134 duncan   1.1.2.5              // update type info
135 cananian 1.1.2.18             updateTypeInfo(q);
136 cananian 1.1.2.18             tT.put(q1.def()[0], HClass.Int);// maybe should be HClass.Void?
137 cananian 1.1.2.2          }
138 duncan   1.1.2.5  
139 cananian 1.1.2.2          public final void visit(harpoon.IR.Quads.ASET q) {
140 cananian 1.1.2.2              Quad q0 = new PARRAY(qf, q, extra(q.objectref()),
141 cananian 1.1.2.2                                   map(q.objectref()));
142 duncan   1.1.2.9              Quad q1 = new PAOFFSET(qf,q,extra(q.index()),type(q,q.objectref()),
143 cananian 1.1.2.2                                     map(q.index()));
144 cananian 1.1.2.2              Quad q2 = new POPER(qf, q, LQop.PADD, extra(q.objectref()),
145 cananian 1.1.2.2                                  new Temp[] { q0.def()[0], q1.def()[0] });
146 cananian 1.1.2.12             Quad q3 = new PSET(qf, q, q2.def()[0], map(q.src()),
147 cananian 1.1.2.12                                type(q,q.objectref()).getComponentType());
148 cananian 1.1.2.2              Quad.addEdges(new Quad[] { q0, q1, q2, q3 });
149 cananian 1.1.2.2              lqm.put(q, q0, q3);
150 cananian 1.1.2.2              // update derivation table.
151 cananian 1.1.2.2              DList dl = new DList(map(q.objectref()), true, null);
152 cananian 1.1.2.2              dT.put(q0.def()[0], dl);
153 cananian 1.1.2.2              dT.put(q2.def()[0], dl);
154 duncan   1.1.2.5              // Update type information
155 duncan   1.1.2.5              updateTypeInfo(q);
156 cananian 1.1.2.18             tT.put(q1.def()[0], HClass.Int);// maybe should be HClass.Void?
157 cananian 1.1.2.2          }
158 duncan   1.1.2.5  
159 cananian 1.1.2.2          public final void visit(harpoon.IR.Quads.CALL q) {
160 cananian 1.1.2.14             boolean isVirtual;
161 cananian 1.1.2.2              Quad q0, qN;
162 cananian 1.3                  if (!q.isVirtual() /*|| fm.isFinal(q.method())*/) {
163 cananian 1.1.2.2                  // non-virtual or final.  Method address is constant.
164 cananian 1.1.2.14                 isVirtual = false;
165 cananian 1.1.2.2                  q0 = qN = new PMCONST(qf, q, extra(), q.method());
166 duncan   1.1.2.7                  // Map q0.def()[0] to a generic pointer type.
167 cananian 1.1.2.18                 tT.put(q0.def()[0], HClass.Void); // opaque pointer
168 cananian 1.1.2.2              } else { // virtual; perform table lookup.
169 cananian 1.1.2.14                 isVirtual = true;
170 cananian 1.1.2.2                  q0 = new PMETHOD(qf, q, extra(q.params(0)), map(q.params(0)));
171 cananian 1.1.2.2                  Quad q1 = new PMOFFSET(qf, q, extra(q.params(0)), q.method());
172 cananian 1.1.2.2                  Quad q2 = new POPER(qf, q, LQop.PADD, extra(q.params(0)),
173 cananian 1.1.2.2                                      new Temp[] { q0.def()[0], q1.def()[0] });
174 cananian 1.1.2.2                  qN = q2;
175 cananian 1.1.2.2                  Quad.addEdges(new Quad[] { q0, q1, q2 });
176 cananian 1.1.2.2                  // update derivation table.
177 cananian 1.1.2.18                 // pointers into claz structure are opaque.
178 cananian 1.1.2.18                 tT.put(q0.def()[0], HClass.Void);
179 cananian 1.1.2.20                 tT.put(q1.def()[0], HClass.Int);
180 cananian 1.1.2.18                 tT.put(q2.def()[0], HClass.Void);
181 cananian 1.1.2.2              }
182 duncan   1.1.2.5              updateTypeInfo(q);
183 cananian 1.1.2.13             // for some reason SIGMA doesn't have a whole-array accessor.
184 cananian 1.1.2.13             Temp[]   nsrc = new Temp[q.numSigmas()];
185 cananian 1.1.2.13             Temp[][] ndst = new Temp[q.numSigmas()][];
186 cananian 1.1.2.13             for (int i=0; i<nsrc.length; i++) { // copy copy copy
187 cananian 1.1.2.13                 nsrc[i] = q.src(i); ndst[i] = q.dst(i);
188 cananian 1.1.2.13             }
189 cananian 1.1.2.13             // CALL->PCALL.
190 cananian 1.1.2.2              Quad q3 = new PCALL(qf, q, qN.def()[0], map(q.params()),
191 cananian 1.1.2.13                                 map(q.retval()), map(q.retex()),
192 cananian 1.1.2.17                                 map(ndst), map(nsrc),
193 cananian 1.1.2.14                                 isVirtual, q.isTailCall());
194 cananian 1.1.2.2              Quad.addEdge(qN, 0, q3, 0);
195 cananian 1.1.2.2              lqm.put(q, q0, q3);
196 cananian 1.1.2.2          }
197 duncan   1.1.2.5  
198 cananian 1.1.2.2          public final void visit(harpoon.IR.Quads.GET q) {
199 cananian 1.1.2.2              Quad q0, qN;
200 cananian 1.1.2.2              if (q.isStatic()) {
201 cananian 1.1.2.2                  q0 = qN = new PFCONST(qf, q, extra(), q.field());
202 duncan   1.1.2.7                  // Map q0.def()[0] to a generic pointer type.
203 cananian 1.1.2.18                 tT.put(q0.def()[0], HClass.Void);
204 cananian 1.1.2.2              } else { // virtual
205 cananian 1.1.2.2                  q0 = new PFIELD(qf, q,
206 cananian 1.1.2.2                                  extra(q.objectref()), map(q.objectref()));
207 cananian 1.1.2.2                  Quad q1 = new PFOFFSET(qf, q, extra(q.objectref()), q.field());
208 cananian 1.1.2.2                  Quad q2 = new POPER(qf, q, LQop.PADD, extra(q.objectref()),
209 cananian 1.1.2.2                                      new Temp[] { q0.def()[0], q1.def()[0] });
210 cananian 1.1.2.2                  qN = q2;
211 cananian 1.1.2.2                  Quad.addEdges(new Quad[] { q0, q1, q2 });
212 cananian 1.1.2.2                  // update derivation table.
213 cananian 1.1.2.2                  DList dl = new DList(map(q.objectref()), true, null);
214 cananian 1.1.2.2                  dT.put(q0.def()[0], dl);
215 cananian 1.1.2.2                  dT.put(q2.def()[0], dl);
216 duncan   1.1.2.5                  tT.put(q1.def()[0], HClass.Int);
217 cananian 1.1.2.2              }
218 duncan   1.1.2.5              updateTypeInfo(q);
219 cananian 1.1.2.12             Quad q3 = new PGET(qf, q, map(q.dst()), qN.def()[0],
220 cananian 1.1.2.12                                q.field().getType());
221 cananian 1.1.2.2              Quad.addEdge(qN, 0, q3, 0);
222 cananian 1.1.2.2              lqm.put(q, q0, q3);
223 cananian 1.1.2.2          }
224 duncan   1.1.2.5  
225 cananian 1.1.2.2          public final void visit(harpoon.IR.Quads.OPER q) {
226 cananian 1.1.2.2              // mutate into POPER
227 cananian 1.1.2.2              Quad nq = new POPER(qf, q, q.opcode(),
228 cananian 1.1.2.2                                 map(q.dst()), map(q.operands()));
229 cananian 1.1.2.2              lqm.put(q, nq, nq);
230 duncan   1.1.2.5              updateTypeInfo(q);
231 cananian 1.1.2.2          }
232 duncan   1.1.2.5  
233 cananian 1.1.2.2          public final void visit(harpoon.IR.Quads.SET q) {
234 cananian 1.1.2.2              Quad q0, qN;
235 cananian 1.1.2.2              if (q.isStatic()) {
236 duncan   1.1.2.7                  q0 = qN = new PFCONST(qf, q, extra(), q.field());       
237 duncan   1.1.2.7                  // Map q0.def()[0] to a generic pointer type.
238 cananian 1.1.2.18                 tT.put(q0.def()[0], HClass.Void);
239 cananian 1.1.2.2              } else { // virtual
240 cananian 1.1.2.2                  q0 = new PFIELD(qf, q,
241 cananian 1.1.2.2                                  extra(q.objectref()), map(q.objectref()));
242 cananian 1.1.2.2                  Quad q1 = new PFOFFSET(qf, q, extra(q.objectref()), q.field());
243 cananian 1.1.2.2                  Quad q2 = new POPER(qf, q, LQop.PADD, extra(q.objectref()),
244 cananian 1.1.2.2                                      new Temp[] { q0.def()[0], q1.def()[0] });
245 cananian 1.1.2.2                  qN = q2;
246 cananian 1.1.2.2                  Quad.addEdges(new Quad[] { q0, q1, q2 });
247 cananian 1.1.2.2                  // update derivation table.
248 cananian 1.1.2.2                  DList dl = new DList(map(q.objectref()), true, null);
249 cananian 1.1.2.2                  dT.put(q0.def()[0], dl);
250 cananian 1.1.2.2                  dT.put(q2.def()[0], dl);
251 duncan   1.1.2.5                  tT.put(q1.def()[0], HClass.Int);
252 cananian 1.1.2.2              }
253 duncan   1.1.2.5              updateTypeInfo(q);
254 cananian 1.1.2.12             Quad q3 = new PSET(qf, q, qN.def()[0], map(q.src()),
255 cananian 1.1.2.12                                q.field().getType());
256 cananian 1.1.2.2              Quad.addEdge(qN, 0, q3, 0);
257 cananian 1.1.2.2              lqm.put(q, q0, q3);
258 cananian 1.1.2.2          }
259 duncan   1.1.2.6        
260 cananian 1.1.2.2          //---------------------------------------------------------
261 duncan   1.1.2.5          // UTILITY FUNCTIONS:
262 cananian 1.1.2.2          private Temp extra() { return new Temp(qf.tempFactory(), "lq_"); }
263 cananian 1.1.2.2          private Temp extra(Temp t) { return t.clone(qf.tempFactory()); }
264 duncan   1.1.2.9          private HClass type(HCodeElement hce, Temp t) { 
265 duncan   1.1.2.9              return tym.typeMap(hce, t); 
266 duncan   1.1.2.9          }
267 cananian 1.1.2.2          private Temp map(Temp t) {
268 cananian 1.1.2.2              return (t==null)?null:ctm.tempMap(t);
269 cananian 1.1.2.2          }
270 cananian 1.1.2.2          private Temp[] map(Temp[] ta) {
271 cananian 1.1.2.2              Temp[] r = new Temp[ta.length];
272 cananian 1.1.2.2              for (int i=0; i<r.length; i++)
273 cananian 1.1.2.2                  r[i] = map(ta[i]);
274 cananian 1.1.2.2              return r;
275 cananian 1.1.2.2          }
276 cananian 1.1.2.2          private Temp[][] map(Temp[][] taa) {
277 cananian 1.1.2.2              Temp[][] r = new Temp[taa.length][];
278 cananian 1.1.2.2              for (int i=0; i<r.length; i++)
279 cananian 1.1.2.2                  r[i] = map(taa[i]);
280 cananian 1.1.2.2              return r;
281 cananian 1.1.2.2          }
282 cananian 1.1.2.1      }
283 cananian 1.2      }