1 cananian 1.1.2.1  // PCALL.java, created Wed Jan 20 21:47:52 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.1  import harpoon.ClassFile.HCodeElement;
  7 cananian 1.1.2.1  import harpoon.Temp.Temp;
  8 cananian 1.1.2.1  import harpoon.Temp.TempMap;
  9 cananian 1.1.2.1  import harpoon.Util.Util;
 10 cananian 1.1.2.1  
 11 cananian 1.1.2.1  /**
 12 cananian 1.1.2.1   * <code>PCALL</code> objects represent a method pointer dereference and
 13 cananian 1.1.2.7   * invocation.  Interpretation is similar to that of
 14 cananian 1.1.2.9   * <code>harpoon.IR.Quads.CALL</code>.<p>
 15 cananian 1.1.2.7   * If an exception is thrown by the called method, the <code>Temp</code>
 16 cananian 1.1.2.7   * specified by <code>retex</code> will be assigned the non-null 
 17 cananian 1.1.2.11  * reference to the thrown exception, and the <code>Temp</code>
 18 cananian 1.1.2.11  * specified by the <code>retval</code> field will be undefined
 19 cananian 1.1.2.11  * (that is, it may have any value at all).
 20 cananian 1.1.2.7   * Execution will proceed along the second outgoing edge,
 21 cananian 1.1.2.7   * <code>nextEdge(1)</code>.  If no exception is thrown, the 
 22 cananian 1.1.2.7   * return value will be assigned to the <code>Temp</code> specified
 23 cananian 1.1.2.7   * by <code>retval</code> (if any), and <code>retex</code> will
 24 cananian 1.1.2.11  * be undefined.  Execution will proceed along the first outgoing
 25 cananian 1.1.2.7   * edge, <code>nextEdge(0)</code>.
 26 cananian 1.1.2.7   * <p>
 27 cananian 1.1.2.7   * See also <code>IR.Quads.CALL</code> and <code>IR.Tree.CALL</code>.
 28 cananian 1.1.2.1   * 
 29 cananian 1.1.2.1   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 30 cananian 1.4       * @version $Id: PCALL.java,v 1.4 2002/04/10 03:04:57 cananian Exp $
 31 cananian 1.1.2.1   */
 32 cananian 1.1.2.3  public class PCALL extends harpoon.IR.Quads.SIGMA {
 33 cananian 1.1.2.1      /** The method pointer to dereference. */
 34 cananian 1.1.2.1      protected final Temp ptr;
 35 cananian 1.1.2.1      /** Parameters to pass to the method. */
 36 cananian 1.1.2.1      protected Temp[] params;
 37 cananian 1.1.2.1      /** Destination for the method's return value;
 38 cananian 1.1.2.1       *  <code>null</code> for <code>void</code> methods. */
 39 cananian 1.1.2.1      protected Temp retval;
 40 cananian 1.1.2.1      /** Destination for any exception thrown by the method.
 41 cananian 1.1.2.1       *  May not be <code>null</code>. */
 42 cananian 1.1.2.1      protected Temp retex;
 43 cananian 1.1.2.4      /** Whether this is a virtual or non-virtual method invocation. */
 44 cananian 1.1.2.4      protected boolean isVirtual;
 45 cananian 1.1.2.4      /** Whether this should be treated as a tail call. */
 46 cananian 1.1.2.4      protected boolean isTailCall;
 47 cananian 1.1.2.1  
 48 cananian 1.1.2.1      /** Creates a <code>PCALL</code> representing a method pointer dereference
 49 cananian 1.1.2.1       *  and method invocation. Interpretation is similar to that of
 50 cananian 1.1.2.11      *  <code>harpoon.IR.Quads.CALL</code>.<p>
 51 cananian 1.1.2.1       *  If an exception is thrown by the called method, the <code>Temp</code>
 52 cananian 1.1.2.1       *  specified by <code>retex</code> will be assigned the non-null 
 53 cananian 1.1.2.11      *  reference to the thrown exception, and the <code>Temp</code>
 54 cananian 1.1.2.11      *  specified by the <code>retval</code> field will be undefined
 55 cananian 1.1.2.11      *  (that is, it may have any value at all).
 56 cananian 1.1.2.3       *  Execution will proceed along the second outgoing edge,
 57 cananian 1.1.2.3       *  <code>nextEdge(1)</code>.  If no exception is thrown, the 
 58 cananian 1.1.2.3       *  return value will be assigned to the <code>Temp</code> specified
 59 cananian 1.1.2.3       *  by <code>retval</code> (if any), and <code>retex</code> will
 60 cananian 1.1.2.11      *  be undefined.  Execution will proceed along the first outgoing
 61 cananian 1.1.2.3       *  edge, <code>nextEdge(0)</code>.
 62 cananian 1.1.2.1       * @param ptr
 63 cananian 1.1.2.1       *        the method pointer to dereference and invoke.
 64 cananian 1.1.2.1       * @param params
 65 cananian 1.1.2.1       *        an array of <code>Temp</code>s containing the parameters
 66 cananian 1.1.2.1       *        to pass to the method.  The object on which to invoke the 
 67 cananian 1.1.2.1       *        method is the first element in the parameter list of a
 68 cananian 1.1.2.1       *        virtual method; non-virtual methods do not need to specify a
 69 cananian 1.1.2.1       *        receiver.  For non-virtual methods, <code>params</code>
 70 cananian 1.1.2.1       *        should match exactly the number and types of parameters in 
 71 cananian 1.1.2.1       *        the method descriptor.  For virtual methods, the receiver
 72 cananian 1.1.2.1       *        object (which is not included in the descriptor) is element
 73 cananian 1.1.2.1       *        zero of the <code>params</code> array.
 74 cananian 1.1.2.1       * @param retval
 75 cananian 1.1.2.1       *        the destination <code>Temp</code> for the method's return
 76 cananian 1.1.2.1       *        value, or <code>null</code> if the method returns no
 77 cananian 1.1.2.1       *        value (return type is <code>void</code>.
 78 cananian 1.1.2.1       * @param retex
 79 cananian 1.1.2.1       *        the destination <code>Temp</code> for any exception thrown
 80 cananian 1.1.2.1       *        by the called method.  May not be <code>null</code>.
 81 cananian 1.1.2.3       * @param dst
 82 cananian 1.1.2.3       *        the elements of the pairs on the left-hand side of
 83 cananian 1.1.2.3       *        the sigma function assignment block associated with
 84 cananian 1.1.2.3       *        this <code>PCALL</code>.
 85 cananian 1.1.2.3       * @param src
 86 cananian 1.1.2.3       *        the arguments to the sigma functions associated with
 87 cananian 1.1.2.3       *        this <code>PCALL</code>.
 88 cananian 1.1.2.4       * @param isVirtual
 89 cananian 1.1.2.4       *        <code>true</code> if this is a virtual method invocation,
 90 cananian 1.1.2.4       *        in which case <code>ptr</code> <i>points to</i> the address of
 91 cananian 1.1.2.4       *        the method to invoke, or <code>false</code> if this is a
 92 cananian 1.1.2.4       *        non-virtual invocation, in which case <code>ptr</code> is
 93 cananian 1.1.2.4       *        the <i>actual address</i> of the method to invoke.
 94 cananian 1.1.2.4       * @param isTailCall
 95 cananian 1.1.2.4       *        <code>true</code> if this method should return the same
 96 cananian 1.1.2.4       *        value the callee returns or throw whatever exception the
 97 cananian 1.1.2.4       *        callee throws (in which case we can get rid of our
 98 cananian 1.1.2.4       *        stack and let the callee return directly to our caller).
 99 cananian 1.1.2.4       *        Usually <code>false</code>.
100 cananian 1.1.2.1       */
101 cananian 1.1.2.1      public PCALL(LowQuadFactory qf, HCodeElement source,
102 cananian 1.1.2.3                   Temp ptr, Temp[] params, Temp retval, Temp retex,
103 cananian 1.1.2.6                   Temp[][] dst, Temp[] src,
104 cananian 1.1.2.4                   boolean isVirtual, boolean isTailCall) {
105 cananian 1.1.2.3          super(qf, source, dst, src, 2/* always arity two */);
106 cananian 1.1.2.1          this.ptr = ptr;
107 cananian 1.1.2.1          this.params = params;
108 cananian 1.1.2.1          this.retval = retval;
109 cananian 1.1.2.1          this.retex = retex;
110 cananian 1.1.2.4          this.isVirtual = isVirtual;
111 cananian 1.1.2.4          this.isTailCall = isTailCall;
112 cananian 1.3.2.1          assert ptr!=null && params!=null && retex !=null;
113 cananian 1.1.2.1          // hm.  can't check much else without knowing the method identity.
114 cananian 1.1.2.1      }
115 cananian 1.1.2.3      // convenience constructor.
116 cananian 1.1.2.3      /** Creates a <code>PCALL</code> with an empty <code>dst</code> array
117 cananian 1.1.2.3       *  of the proper size and arity.  Other arguments as above. */
118 cananian 1.1.2.3      public PCALL(LowQuadFactory qf, HCodeElement source,
119 cananian 1.1.2.4                   Temp ptr, Temp[] params, Temp retval, Temp retex,
120 cananian 1.1.2.6                   Temp[] src, boolean isVirtual, boolean isTailCall){
121 cananian 1.1.2.3          this(qf, source, ptr, params, retval, retex,
122 cananian 1.1.2.6               new Temp[src.length][2], src, isVirtual, isTailCall);
123 cananian 1.1.2.3      }
124 cananian 1.1.2.3  
125 cananian 1.1.2.1      // ACCESSOR METHODS:
126 cananian 1.1.2.1      /** Returns the <code>POINTER</code> which is to be dereferenced by this
127 cananian 1.1.2.1       *  <code>PCALL</code>. */
128 cananian 1.1.2.1      public Temp ptr() { return ptr; }
129 cananian 1.1.2.1      /** Returns the parameters of this method invocation. */
130 cananian 1.1.2.1      public Temp[] params()
131 cananian 1.1.2.1      { return (Temp[]) Util.safeCopy(Temp.arrayFactory, params); }
132 cananian 1.1.2.1      /** Returns a specified parameter in the <code>params</code> array. */
133 cananian 1.1.2.1      public Temp params(int i) { return params[i]; }
134 cananian 1.1.2.1      /** Returns the number of parameters in the <code>params</code> array. */
135 cananian 1.1.2.1      public int paramsLength() { return params.length; }
136 cananian 1.1.2.1      /** Returns the <code>Temp</code> which will hold the return value of
137 cananian 1.1.2.1       *  the method, or the value <code>null</code> if the method returns
138 cananian 1.1.2.1       *  no value. */
139 cananian 1.1.2.1      public Temp retval() { return retval; }
140 cananian 1.1.2.1      /** Returns the <code>Temp</code> which will get any exception thrown
141 cananian 1.1.2.1       *  by the called method, or <code>null</code> if exceptions are
142 cananian 1.1.2.1       *  not caught. */
143 cananian 1.1.2.1      public Temp retex() { return retex; }
144 cananian 1.1.2.4      /** Returns <code>true</code> if <code>ptr</code> <i>points to</i>
145 cananian 1.1.2.4       *  the address of the method to invoke; or <code>false</code> if
146 cananian 1.1.2.4       *  <code>ptr</code> contains the direct address of the method to
147 cananian 1.1.2.4       *  invoke. */
148 cananian 1.1.2.4      public boolean isVirtual() { return isVirtual; }
149 cananian 1.1.2.4      /** Return <code>true</code> if this method should return the same
150 cananian 1.1.2.4       *  value the callee returns or throw whatever exception the
151 cananian 1.1.2.4       *  callee throws (in which case we can get rid of our
152 cananian 1.1.2.4       *  stack and let the callee return directly to our caller).
153 cananian 1.1.2.4       *  Usually <code>false</code>. */
154 cananian 1.1.2.4      public boolean isTailCall() { return isTailCall; }
155 cananian 1.1.2.1  
156 cananian 1.1.2.1      public int kind() { return LowQuadKind.PCALL; }
157 cananian 1.1.2.1  
158 cananian 1.1.2.1      public Temp[] use() {
159 cananian 1.1.2.3          Temp[] u = super.use();
160 cananian 1.1.2.3          Temp[] r = new Temp[u.length+params.length+1];
161 cananian 1.1.2.3          System.arraycopy(u,      0, r, 0,        u.length);
162 cananian 1.1.2.3          System.arraycopy(params, 0, r, u.length, params.length);
163 cananian 1.1.2.3          r[u.length+params.length] = ptr;
164 cananian 1.1.2.3          return r;
165 cananian 1.1.2.1      }
166 cananian 1.1.2.1      public Temp[] def() {
167 cananian 1.1.2.3          Temp[] d = super.def();
168 cananian 1.1.2.3          Temp[] r = new Temp[d.length+(retval==null?1:2)];
169 cananian 1.1.2.3          System.arraycopy(d, 0, r, 0, d.length);
170 cananian 1.1.2.3          if (retval!=null) r[r.length-2] = retval;
171 cananian 1.1.2.3          r[r.length-1] = retex;
172 cananian 1.1.2.3          return r;
173 cananian 1.1.2.1      }
174 cananian 1.1.2.1  
175 cananian 1.1.2.1      public harpoon.IR.Quads.Quad rename(harpoon.IR.Quads.QuadFactory qf,
176 cananian 1.1.2.1                                          TempMap defMap, TempMap useMap) {
177 cananian 1.1.2.1          return new PCALL((LowQuadFactory)qf, this,
178 cananian 1.1.2.1                           map(useMap, ptr), map(useMap, params),
179 cananian 1.1.2.3                           map(defMap, retval), map(defMap, retex),
180 cananian 1.1.2.4                           map(defMap, dst), map(useMap, src),
181 cananian 1.1.2.6                           isVirtual, isTailCall);
182 cananian 1.1.2.1      }
183 cananian 1.1.2.1  
184 cananian 1.1.2.3      public void accept(harpoon.IR.Quads.QuadVisitor v) {
185 cananian 1.1.2.3          ((LowQuadVisitor)v).visit(this);
186 cananian 1.1.2.3      }
187 cananian 1.1.2.1  
188 cananian 1.1.2.1      public String toString() {
189 cananian 1.1.2.1          StringBuffer sb = new StringBuffer();
190 cananian 1.1.2.1          if (retval != null)
191 cananian 1.1.2.1              sb.append(retval.toString() + " = ");
192 cananian 1.1.2.4          sb.append("PCALL ");
193 cananian 1.1.2.4          if (isVirtual) sb.append("*");
194 cananian 1.1.2.4          sb.append(ptr.toString());
195 cananian 1.1.2.1  
196 cananian 1.1.2.1          sb.append('(');
197 cananian 1.1.2.1          for (int i=0; i<params.length; i++) {
198 cananian 1.1.2.1              sb.append(params[i].toString());
199 cananian 1.1.2.1              if (i<params.length-1)
200 cananian 1.1.2.1                  sb.append(", ");
201 cananian 1.1.2.1          }
202 cananian 1.1.2.1          sb.append(')');
203 cananian 1.1.2.1  
204 cananian 1.1.2.4          if (isTailCall) sb.append(" [tail call]");
205 cananian 1.1.2.1          sb.append(" exceptions in "+retex.toString());
206 cananian 1.1.2.3          sb.append(" / "); sb.append(super.toString());
207 cananian 1.1.2.1          return sb.toString();
208 cananian 1.1.2.1      }
209 cananian 1.2      }