1 cananian 1.1.2.1  // BINOP.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.25 import harpoon.Temp.TempMap;
  8 cananian 1.1.2.3  import harpoon.Util.Util;
  9 cananian 1.1.2.3  
 10 cananian 1.1.2.1  /**
 11 cananian 1.1.2.1   * <code>BINOP</code> objects are expressions which stand for result of
 12 cananian 1.1.2.1   * applying some binary operator <i>o</i> to a pair of subexpressions.
 13 cananian 1.1.2.1   * 
 14 cananian 1.1.2.1   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>, based on
 15 cananian 1.1.2.1   *          <i>Modern Compiler Implementation in Java</i> by Andrew Appel.
 16 cananian 1.5       * @version $Id: BINOP.java,v 1.5 2003/10/20 04:26:37 cananian Exp $
 17 cananian 1.1.2.3   * @see Bop
 18 cananian 1.1.2.1   */
 19 cananian 1.1.2.1  public class BINOP extends OPER {
 20 cananian 1.1.2.12     /** Constructor.
 21 cananian 1.1.2.12      * @param binop Enumerated operation type, from <code>Bop</code>.
 22 cananian 1.1.2.12      */
 23 cananian 1.1.2.4      public BINOP(TreeFactory tf, HCodeElement source,
 24 cananian 1.1.2.5                   int optype, int binop, Exp left, Exp right) {
 25 cananian 1.1.2.24         super(tf, source, optype, binop, 2);
 26 cananian 1.3.2.1          assert left != null && right != null;
 27 duncan   1.1.2.20         this.setLeft(left); this.setRight(right); 
 28 cananian 1.3.2.1          assert Bop.isValid(binop);
 29 cananian 1.3.2.1          assert tf==right.tf : "Left and Right must have same tree factory";
 30 cananian 1.3.2.1          assert tf==left.tf : "This and Left must have same tree factory";
 31 pnkfelix 1.1.2.22 
 32 pnkfelix 1.1.2.23         // FSK: debugging hack
 33 pnkfelix 1.1.2.23         // this.accept(TreeVerifyingVisitor.norepeats());
 34 cananian 1.1.2.1      }
 35 duncan   1.1.2.20 
 36 cananian 1.1.2.3      // binops defined in harpoon.IR.Tree.Bop.
 37 cananian 1.1.2.5      public int type() {
 38 cananian 1.1.2.3          switch(op) {
 39 cananian 1.1.2.27         case Bop.CMPLT: case Bop.CMPLE:
 40 cananian 1.1.2.27         case Bop.CMPEQ: case Bop.CMPNE:
 41 cananian 1.1.2.3          case Bop.CMPGE: case Bop.CMPGT:
 42 duncan   1.1.2.10             return Type.INT; // boolean comparison result
 43 cananian 1.1.2.3          default:
 44 cananian 1.1.2.5              return optype;
 45 cananian 1.1.2.3          }
 46 cananian 1.1.2.3      }
 47 duncan   1.1.2.20     
 48 cananian 1.1.2.24     /** Returns the subexpression of the left-hand side of the operator. */
 49 cananian 1.1.2.24     public Exp getLeft() { return (Exp) getChild(0); } 
 50 cananian 1.1.2.24     /** Returns the subexpression of the right-hand side of the operator. */
 51 cananian 1.1.2.24     public Exp getRight() { return (Exp) getChild(1); } 
 52 cananian 1.1.2.24 
 53 cananian 1.1.2.24     /** Sets the subexpression of the left-hand side of the operator. */
 54 cananian 1.1.2.24     public void setLeft(Exp left) {  setChild(0, left); }
 55 cananian 1.1.2.24     /** Sets the subexpression of the right-hand side of the operator. */
 56 cananian 1.1.2.24     public void setRight(Exp right) { setChild(1, right); }
 57 duncan   1.1.2.11     
 58 duncan   1.1.2.11     public int kind() { return TreeKind.BINOP; }
 59 duncan   1.1.2.11     
 60 duncan   1.1.2.16     public Exp build(TreeFactory tf, ExpList kids) {
 61 cananian 1.3.2.1          assert kids!=null && kids.tail!=null && kids.tail.tail==null;
 62 cananian 1.3.2.1          assert tf == kids.head.tf && tf == kids.tail.head.tf;
 63 cananian 1.1.2.5          return new BINOP(tf, this, optype, op, kids.head, kids.tail.head);
 64 cananian 1.1.2.1      }
 65 duncan   1.1.2.2      /** Accept a visitor */
 66 cananian 1.1.2.19     public void accept(TreeVisitor v) { v.visit(this); }
 67 duncan   1.1.2.6    
 68 cananian 1.1.2.25     public Tree rename(TreeFactory tf, TempMap tm, CloneCallback cb) {
 69 cananian 1.1.2.25         return cb.callback(this, new BINOP(tf, this, optype, op, 
 70 cananian 1.1.2.25                                            (Exp)getLeft().rename(tf, tm, cb), 
 71 cananian 1.1.2.26                                            (Exp)getRight().rename(tf, tm, cb)),
 72 cananian 1.1.2.26                            tm);
 73 andyb    1.1.2.7      }
 74 duncan   1.1.2.8  
 75 duncan   1.1.2.8      /** Evaluates a constant value for the result of a <code>BINOP</code>, 
 76 duncan   1.1.2.8       *  given constant values for the operands. */
 77 duncan   1.1.2.8      public static Object evalValue(TreeFactory tf, 
 78 duncan   1.1.2.8                                     int op, int optype, 
 79 duncan   1.1.2.8                                     Object left, Object right) {
 80 duncan   1.1.2.8          switch(op) {
 81 duncan   1.1.2.8          case Bop.CMPLT: 
 82 duncan   1.1.2.8              switch(optype) {
 83 duncan   1.1.2.8              case Type.INT:      return _i((_i(left)<_i(right))?1:0);
 84 duncan   1.1.2.8              case Type.LONG:     return _i((_l(left)<_l(right))?1:0);
 85 duncan   1.1.2.8              case Type.FLOAT:    return _i((_f(left)<_f(right))?1:0);
 86 duncan   1.1.2.8              case Type.DOUBLE:   return _i((_d(left)<_d(right))?1:0);
 87 duncan   1.1.2.8              case Type.POINTER:  
 88 duncan   1.1.2.9                  return Type.isDoubleWord(tf, optype) ?
 89 duncan   1.1.2.9                      _i(_l(left)<_l(right)?1:0) :
 90 duncan   1.1.2.9                          _i(_i(left)<_i(right)?1:0);
 91 duncan   1.1.2.8              }
 92 duncan   1.1.2.8          case Bop.CMPLE: 
 93 duncan   1.1.2.8              switch(optype) {
 94 duncan   1.1.2.8              case Type.INT:      return _i((_i(left)<=_i(right))?1:0);
 95 duncan   1.1.2.8              case Type.LONG:     return _i((_l(left)<=_l(right))?1:0);
 96 duncan   1.1.2.8              case Type.FLOAT:    return _i((_f(left)<=_f(right))?1:0);
 97 duncan   1.1.2.8              case Type.DOUBLE:   return _i((_d(left)<=_d(right))?1:0);
 98 duncan   1.1.2.8              case Type.POINTER:  
 99 duncan   1.1.2.9                  return Type.isDoubleWord(tf, optype) ?
100 duncan   1.1.2.9                      _i(_l(left)<=_l(right)?1:0) :
101 duncan   1.1.2.9                          _i(_i(left)<=_i(right)?1:0);
102 duncan   1.1.2.8              }
103 duncan   1.1.2.8          case Bop.CMPEQ: 
104 duncan   1.1.2.8              switch (optype) {
105 duncan   1.1.2.8              case Type.INT:      return _i((_i(left)==_i(right))?1:0);
106 duncan   1.1.2.8              case Type.LONG:     return _i((_l(left)==_l(right))?1:0);
107 duncan   1.1.2.8              case Type.FLOAT:    return _i((_f(left)==_f(right))?1:0);
108 duncan   1.1.2.8              case Type.DOUBLE:   return _i((_d(left)==_d(right))?1:0);
109 duncan   1.1.2.8              case Type.POINTER:  
110 duncan   1.1.2.8                  return Type.isDoubleWord(tf, optype) ?
111 duncan   1.1.2.8                      _i(_l(left)==_l(right)?1:0) :
112 duncan   1.1.2.8                          _i(_i(left)==_i(right)?1:0);
113 cananian 1.1.2.27             }
114 cananian 1.1.2.27         case Bop.CMPNE: 
115 cananian 1.1.2.27             switch (optype) {
116 cananian 1.1.2.27             case Type.INT:      return _i((_i(left)!=_i(right))?1:0);
117 cananian 1.1.2.27             case Type.LONG:     return _i((_l(left)!=_l(right))?1:0);
118 cananian 1.1.2.27             case Type.FLOAT:    return _i((_f(left)!=_f(right))?1:0);
119 cananian 1.1.2.27             case Type.DOUBLE:   return _i((_d(left)!=_d(right))?1:0);
120 cananian 1.1.2.27             case Type.POINTER:  
121 cananian 1.1.2.27                 return Type.isDoubleWord(tf, optype) ?
122 cananian 1.1.2.27                     _i(_l(left)!=_l(right)?1:0) :
123 cananian 1.1.2.27                         _i(_i(left)!=_i(right)?1:0);
124 duncan   1.1.2.8              }
125 duncan   1.1.2.8          case Bop.CMPGE:
126 duncan   1.1.2.8              switch (optype) {
127 duncan   1.1.2.8              case Type.INT:      return _i((_i(left)>=_i(right))?1:0);
128 duncan   1.1.2.8              case Type.LONG:     return _i((_l(left)>=_l(right))?1:0);
129 duncan   1.1.2.9              case Type.FLOAT:    return _i((_f(left)>=_f(right))?1:0);
130 duncan   1.1.2.9              case Type.DOUBLE:   return _i((_d(left)>=_d(right))?1:0);
131 duncan   1.1.2.8              case Type.POINTER:  
132 duncan   1.1.2.9                  return Type.isDoubleWord(tf, optype) ?
133 duncan   1.1.2.9                      _i(_l(left)>=_l(right)?1:0) :
134 duncan   1.1.2.9                          _i(_i(left)>=_i(right)?1:0);
135 duncan   1.1.2.9              }
136 duncan   1.1.2.8          case Bop.CMPGT: 
137 duncan   1.1.2.8              switch (optype) {
138 duncan   1.1.2.8              case Type.INT:      return _i((_i(left)>_i(right))?1:0);
139 duncan   1.1.2.8              case Type.LONG:     return _i((_l(left)>_l(right))?1:0);
140 duncan   1.1.2.8              case Type.FLOAT:    return _i((_f(left)>_f(right))?1:0);
141 duncan   1.1.2.8              case Type.DOUBLE:   return _i((_d(left)>_d(right))?1:0);
142 duncan   1.1.2.8              case Type.POINTER:  
143 duncan   1.1.2.9                  return Type.isDoubleWord(tf, optype) ?
144 duncan   1.1.2.9                      _i(_l(left)>_l(right)?1:0) :
145 duncan   1.1.2.9                          _i(_i(left)>_i(right)?1:0);
146 duncan   1.1.2.8              }
147 duncan   1.1.2.8          case Bop.ADD:   
148 duncan   1.1.2.8              switch (optype) {
149 duncan   1.1.2.8              case Type.INT:      return _i(_i(left)+_i(right));
150 duncan   1.1.2.8              case Type.LONG:     return _l(_l(left)+_l(right));
151 duncan   1.1.2.8              case Type.FLOAT:    return _f(_f(left)+_f(right));
152 duncan   1.1.2.8              case Type.DOUBLE:   return _d(_d(left)+_d(right));
153 duncan   1.1.2.8              case Type.POINTER:  
154 cananian 1.5                    // note that we allow silent coercion of ints to longs
155 cananian 1.5                    // on 64-bit platforms.  If you try to make the offsets
156 cananian 1.5                    // match the pointer size, then you have to deal with
157 cananian 1.5                    // the array indexing issue: java only allows 32-bit
158 cananian 1.5                    // array indexes.  At the moment, we're going to do
159 cananian 1.5                    // only integer multiplication on offsets, so we're
160 cananian 1.5                    // going to end up with integers are pointer offsets.
161 duncan   1.1.2.9                return Type.isDoubleWord(tf, optype) ?
162 cananian 1.5                          (Object)_l(_lp(left)+_lp(right)) :
163 duncan   1.1.2.9                          (Object)_i(_i(left)+_i(right));
164 duncan   1.1.2.8              }
165 duncan   1.1.2.8          case Bop.MUL:   
166 duncan   1.1.2.8              switch (optype) {
167 duncan   1.1.2.8              case Type.INT:      return _i(_i(left)*_i(right));
168 duncan   1.1.2.8              case Type.LONG:     return _l(_l(left)*_l(right));
169 duncan   1.1.2.8              case Type.FLOAT:    return _f(_f(left)*_f(right));
170 duncan   1.1.2.8              case Type.DOUBLE:   return _d(_d(left)*_d(right));
171 duncan   1.1.2.8              case Type.POINTER:  
172 duncan   1.1.2.9                return Type.isDoubleWord(tf, optype) ?
173 duncan   1.1.2.9                      (Object)_l(_l(left)*_l(right)) :
174 duncan   1.1.2.9                          (Object)_i(_i(left)*_i(right));
175 duncan   1.1.2.8              }
176 duncan   1.1.2.8          case Bop.DIV:
177 duncan   1.1.2.8              switch (optype) {
178 duncan   1.1.2.8              case Type.INT:      return _i(_i(left)/_i(right));
179 duncan   1.1.2.8              case Type.LONG:     return _l(_l(left)/_l(right));
180 duncan   1.1.2.8              case Type.FLOAT:    return _f(_f(left)/_f(right));
181 duncan   1.1.2.8              case Type.DOUBLE:   return _d(_d(left)/_d(right));
182 duncan   1.1.2.8              case Type.POINTER:  
183 duncan   1.1.2.8                  throw new Error("Operation not supported");
184 duncan   1.1.2.8              }
185 duncan   1.1.2.8          case Bop.REM: 
186 duncan   1.1.2.8              switch (optype) {
187 duncan   1.1.2.8              case Type.INT:      return _i(_i(left)%_i(right));
188 duncan   1.1.2.8              case Type.LONG:     return _l(_l(left)%_l(right));
189 duncan   1.1.2.8              case Type.FLOAT:    return _f(_f(left)%_f(right));
190 duncan   1.1.2.8              case Type.DOUBLE:   return _d(_d(left)%_d(right));
191 duncan   1.1.2.8              case Type.POINTER:  
192 duncan   1.1.2.8                  throw new Error("Operation not supported");
193 duncan   1.1.2.8              }
194 duncan   1.1.2.8          case Bop.SHL:
195 duncan   1.1.2.8              switch (optype) {
196 duncan   1.1.2.14             case Type.INT:      return _i(_i(left)<<_i(right));
197 duncan   1.1.2.14             case Type.LONG:     return _l(_l(left)<<_i(right));
198 duncan   1.1.2.8              case Type.FLOAT:
199 duncan   1.1.2.8              case Type.DOUBLE:
200 duncan   1.1.2.8              case Type.POINTER:
201 duncan   1.1.2.8                  throw new Error("Operation not supported");
202 duncan   1.1.2.8              }
203 duncan   1.1.2.8          case Bop.SHR:
204 duncan   1.1.2.8              switch (optype) {
205 duncan   1.1.2.14             case Type.INT:      return _i(_i(left)>>_i(right));
206 duncan   1.1.2.14             case Type.LONG:     return _l(_l(left)>>_i(right));
207 duncan   1.1.2.8              case Type.FLOAT:
208 duncan   1.1.2.8              case Type.DOUBLE:
209 duncan   1.1.2.8              case Type.POINTER:
210 duncan   1.1.2.8                  throw new Error("Operation not supported");
211 duncan   1.1.2.8              }
212 duncan   1.1.2.8          case Bop.USHR:
213 duncan   1.1.2.8              switch (optype) {
214 duncan   1.1.2.14             case Type.INT:      return _i(_i(left)>>>_i(right));
215 duncan   1.1.2.14             case Type.LONG:     return _l(_l(left)>>>_i(right));
216 duncan   1.1.2.8              case Type.FLOAT:
217 duncan   1.1.2.8              case Type.DOUBLE:
218 duncan   1.1.2.8              case Type.POINTER:
219 duncan   1.1.2.8                  throw new Error("Operation not supported");
220 duncan   1.1.2.8              }
221 duncan   1.1.2.8          case Bop.AND:
222 duncan   1.1.2.8              switch (optype) {
223 duncan   1.1.2.8              case Type.INT:      return _i(_i(left)&_i(right));
224 duncan   1.1.2.8              case Type.LONG:     return _l(_l(left)&_l(right));
225 duncan   1.1.2.8              case Type.FLOAT:
226 duncan   1.1.2.8              case Type.DOUBLE:
227 duncan   1.1.2.8              case Type.POINTER:
228 duncan   1.1.2.8                  throw new Error("Operation not supported");
229 duncan   1.1.2.8              }
230 duncan   1.1.2.8          case Bop.OR:
231 duncan   1.1.2.8              switch (optype) {
232 duncan   1.1.2.8              case Type.INT:      return _i(_i(left)|_i(right));
233 duncan   1.1.2.8              case Type.LONG:     return _l(_l(left)|_l(right));
234 duncan   1.1.2.8              case Type.FLOAT:
235 duncan   1.1.2.8              case Type.DOUBLE:
236 duncan   1.1.2.8              case Type.POINTER:
237 duncan   1.1.2.8                  throw new Error("Operation not supported");
238 duncan   1.1.2.8              }
239 duncan   1.1.2.8          case Bop.XOR:
240 duncan   1.1.2.8              switch (optype) {
241 duncan   1.1.2.8              case Type.INT:      return _i(_i(left)^_i(right));
242 duncan   1.1.2.8              case Type.LONG:     return _l(_l(left)^_l(right));
243 duncan   1.1.2.8              case Type.FLOAT:
244 duncan   1.1.2.8              case Type.DOUBLE:
245 duncan   1.1.2.8              case Type.POINTER:
246 duncan   1.1.2.8                  throw new Error("Operation not supported");
247 duncan   1.1.2.8              }
248 duncan   1.1.2.8          default:        
249 duncan   1.1.2.8              throw new RuntimeException("Unknown Bop type: "+op);
250 duncan   1.1.2.8          }
251 duncan   1.1.2.8      }
252 duncan   1.1.2.8  
253 duncan   1.1.2.8      // wrapper functions.
254 duncan   1.1.2.8      private static Integer _i(int i)     { return new Integer(i); }
255 duncan   1.1.2.8      private static Long    _l(long l)    { return new Long(l);    }
256 duncan   1.1.2.8      private static Float   _f(float f)   { return new Float(f);   }
257 duncan   1.1.2.8      private static Double  _d(double d)  { return new Double(d);  }
258 duncan   1.1.2.8      private static Boolean _b(boolean b) { return new Boolean(b); }
259 duncan   1.1.2.8      // unwrapper functions.
260 duncan   1.1.2.8      private static int    _i(Object o) { return ((Integer)o).intValue(); }
261 duncan   1.1.2.8      private static long   _l(Object o) { return ((Long)o)   .longValue(); }
262 cananian 1.5          private static long   _lp(Object o){ return ((Number)o) .longValue(); }
263 duncan   1.1.2.8      private static float  _f(Object o) { return ((Float)o)  .floatValue(); }
264 duncan   1.1.2.8      private static double _d(Object o) { return ((Double)o) .doubleValue(); }
265 andyb    1.1.2.7  
266 andyb    1.1.2.7      public String toString() {
267 andyb    1.1.2.7          return "BINOP<"+Type.toString(optype)+">("+Bop.toString(op)+
268 cananian 1.1.2.24                ", #" + getLeft().getID() + ", #" + getRight().getID() + ")";
269 duncan   1.1.2.6      }
270 cananian 1.1.2.1  }
271 cananian 1.2