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