1 cananian 1.1.2.1  // CALL.java, created Wed Jan 13 21:14:57 1999 by cananian
  2 cananian 1.1.2.17 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.17 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1  package harpoon.IR.Tree;
  5 cananian 1.1.2.1  
  6 cananian 1.1.2.4  import harpoon.ClassFile.HCodeElement;
  7 cananian 1.1.2.32 import harpoon.Temp.TempMap;
  8 cananian 1.1.2.4  import harpoon.Util.Util;
  9 cananian 1.1.2.4  
 10 duncan   1.1.2.14 import java.util.HashSet;
 11 duncan   1.1.2.14 import java.util.Set;
 12 duncan   1.1.2.14 
 13 cananian 1.1.2.1  /**
 14 duncan   1.1.2.7   * <code>CALL</code> objects are statements which stand for 
 15 cananian 1.1.2.16  * java method invocations, using our runtime's calling convention.
 16 cananian 1.1.2.16  * <p>
 17 cananian 1.1.2.21  * The <code>handler</code> expression is a
 18 cananian 1.1.2.16  * <code>Tree.NAME</code> specifying the label to which we should return
 19 cananian 1.1.2.21  * from this call if an exception occurs.  If the called method throws
 20 cananian 1.1.2.21  * an exception, the throwable object is placed in the <code>Temp</code>
 21 cananian 1.1.2.21  * specified by <code>retex</code> and a control tranfer to the
 22 cananian 1.1.2.21  * <code>Label</code> specified by <code>handler</code> occurs.
 23 cananian 1.1.2.39  * Note the value in <code>retval</code> is undefined (that is, it
 24 cananian 1.1.2.39  * may have any value at all) when an "exceptional" return occurs.
 25 cananian 1.1.2.16  * <p>
 26 cananian 1.1.2.21  * If there is no exception thrown by the callee, then the return
 27 cananian 1.1.2.21  * value is placed in the <code>Temp</code> specified by
 28 cananian 1.1.2.37  * <code>retval</code> and execution continues normally.  The value
 29 cananian 1.1.2.39  * in <code>retex</code> is undefined (may be given any value) in this case.
 30 cananian 1.1.2.39  * Note that
 31 cananian 1.1.2.21  * <code>retval</code> may be null if the called method has void return
 32 cananian 1.1.2.21  * type.
 33 cananian 1.1.2.36  * <p>
 34 cananian 1.1.2.36  * See also <code>IR.LowQuad.PCALL</code> and <code>IR.Quads.CALL</code>,
 35 cananian 1.1.2.37  * which have similar execution semantics.
 36 cananian 1.1.2.1   * 
 37 cananian 1.1.2.1   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>, based on
 38 cananian 1.1.2.1   *          <i>Modern Compiler Implementation in Java</i> by Andrew Appel.
 39 cananian 1.4       * @version $Id: CALL.java,v 1.4 2002/04/10 03:05:38 cananian Exp $
 40 pnkfelix 1.1.2.10  * @see harpoon.IR.Quads.CALL
 41 cananian 1.1.2.11  * @see INVOCATION
 42 pnkfelix 1.1.2.10  * @see NATIVECALL
 43 cananian 1.1.2.1   */
 44 duncan   1.1.2.8  public class CALL extends INVOCATION {
 45 cananian 1.1.2.20     /** Whether this invocation should be performed as a tail call. */
 46 cananian 1.1.2.31     public final boolean isTailCall;
 47 duncan   1.1.2.26 
 48 cananian 1.1.2.31     /** Create a <code>CALL</code> object.
 49 cananian 1.1.2.31      * @param retex Destination for any exception which the callee
 50 cananian 1.1.2.31      *  might throw.  Must be non-null.
 51 cananian 1.1.2.31      * @param handler Expression indicating the destination to which
 52 cananian 1.1.2.31      *  we should return if our caller throws an exception.
 53 cananian 1.1.2.31      */
 54 cananian 1.1.2.4      public CALL(TreeFactory tf, HCodeElement source,
 55 cananian 1.1.2.20                 TEMP retval, TEMP retex, Exp func, ExpList args,
 56 cananian 1.1.2.20                 NAME handler, boolean isTailCall) {
 57 cananian 1.1.2.31         super(tf, source, retval, func, args, 2); 
 58 cananian 1.3.2.1          assert retex != null && handler != null;
 59 cananian 1.3.2.1          assert retex.tf == tf;
 60 duncan   1.1.2.23         this.setRetex(retex); this.setHandler(handler);
 61 cananian 1.1.2.20         this.isTailCall = isTailCall;
 62 pnkfelix 1.1.2.27         
 63 pnkfelix 1.1.2.30         // FSK: debugging hack
 64 pnkfelix 1.1.2.30         // this.accept(TreeVerifyingVisitor.norepeats());
 65 cananian 1.1.2.4      }
 66 duncan   1.1.2.23 
 67 cananian 1.1.2.31     /** Returns the destination expression for any exception which
 68 cananian 1.1.2.31      *  the callee might throw.  Guaranteed to be non-null. */
 69 cananian 1.1.2.31     public TEMP getRetex() { return (TEMP) getChild(0); }
 70 cananian 1.1.2.31     /** Returns an expression indicating the destination to which
 71 cananian 1.1.2.31      *  we should return if our caller throws an exception. */
 72 cananian 1.1.2.31     public NAME getHandler() { return (NAME) getChild(1); } 
 73 duncan   1.1.2.7    
 74 cananian 1.1.2.31     /** Sets the destination temp for any exception which the callee
 75 cananian 1.1.2.31      *  might throw.  Must be non-null. */
 76 cananian 1.1.2.31     public void setRetex(TEMP retex) {
 77 cananian 1.3.2.1          assert retex!=null;
 78 cananian 1.1.2.31         setChild(0, retex);
 79 duncan   1.1.2.7      }
 80 cananian 1.1.2.31     /** Sets the destination to which we should return
 81 cananian 1.1.2.31      *  if our caller throws an exception. */
 82 cananian 1.1.2.31     public void setHandler(NAME handler) { setChild(1, handler); }
 83 duncan   1.1.2.12 
 84 duncan   1.1.2.23     public boolean isNative() { return false; }
 85 duncan   1.1.2.23 
 86 duncan   1.1.2.12     public int kind() { return TreeKind.CALL; }
 87 duncan   1.1.2.7  
 88 duncan   1.1.2.13     public Stm build(TreeFactory tf, ExpList kids) {
 89 cananian 1.1.2.20         for (ExpList e = kids; e!=null; e=e.tail)
 90 cananian 1.3.2.1              assert e.head == null || tf == e.head.tf;
 91 cananian 1.3.2.1          assert tf==this.tf : "cloning retval/retex/handler not yet impl.";
 92 duncan   1.1.2.26 
 93 cananian 1.1.2.31         return new CALL(tf, this, getRetval(), getRetex(),
 94 cananian 1.1.2.31                         kids.head,            // func
 95 cananian 1.1.2.31                         kids.tail,            // args
 96 cananian 1.1.2.31                         getHandler(),         // handler
 97 cananian 1.1.2.31                         isTailCall);
 98 cananian 1.1.2.1      }
 99 duncan   1.1.2.7  
100 duncan   1.1.2.3      /** Accept a visitor */
101 cananian 1.1.2.19     public void accept(TreeVisitor v) { v.visit(this); }
102 duncan   1.1.2.5  
103 cananian 1.1.2.32     public Tree rename(TreeFactory tf, TempMap tm, CloneCallback cb) {
104 cananian 1.1.2.32         return cb.callback(this,
105 cananian 1.1.2.34                            new CALL(tf, this, getRetval()==null ? null :
106 cananian 1.1.2.32                                     (TEMP)getRetval().rename(tf, tm, cb),
107 cananian 1.1.2.32                                     (TEMP)getRetex().rename(tf, tm, cb), 
108 cananian 1.1.2.32                                     (Exp)getFunc().rename(tf, tm, cb),
109 cananian 1.1.2.32                                     ExpList.rename(getArgs(), tf, tm, cb),
110 cananian 1.1.2.32                                     (NAME)getHandler().rename(tf, tm, cb),
111 cananian 1.1.2.33                                     isTailCall),
112 cananian 1.1.2.33                            tm);
113 duncan   1.1.2.14     }
114 cananian 1.1.2.1  
115 andyb    1.1.2.9      public String toString() {
116 andyb    1.1.2.9          ExpList list;
117 andyb    1.1.2.9          StringBuffer s = new StringBuffer();
118 cananian 1.1.2.20         s.append("CALL(");
119 duncan   1.1.2.23         if (this.getRetval()==null) { s.append("null"); } 
120 duncan   1.1.2.23         else { s.append("#"+this.getRetval().getID()); } 
121 cananian 1.1.2.31         s.append(", #"+this.getRetex().getID()+
122 duncan   1.1.2.23                  ", #" + this.getFunc().getID() + ", {");
123 duncan   1.1.2.23         list = this.getArgs();
124 andyb    1.1.2.9          while (list != null) {
125 andyb    1.1.2.9              s.append(" #"+list.head.getID());
126 andyb    1.1.2.9              if (list.tail != null) {
127 andyb    1.1.2.9                  s.append(",");
128 andyb    1.1.2.9              }
129 andyb    1.1.2.9              list = list.tail;
130 andyb    1.1.2.9          }
131 cananian 1.1.2.20         s.append(" }");
132 cananian 1.1.2.31         s.append(", #"+this.getHandler().getID());
133 cananian 1.1.2.20         s.append(")");
134 cananian 1.1.2.20         if (isTailCall) s.append(" [tail call]");
135 andyb    1.1.2.9          return new String(s);
136 andyb    1.1.2.9      }
137 cananian 1.2      }