1 /* 2 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.tools.tree; 27 28 import sun.tools.java.*; 29 import sun.tools.asm.Label; 30 import sun.tools.asm.Assembler; 31 import java.io.PrintStream; 32 import java.util.Hashtable; 33 34 /** 35 * WARNING: The contents of this source file are not part of any 36 * supported API. Code that depends on them does so at its own risk: 37 * they are subject to change or removal without notice. 38 */ 39 public 40 class BinaryExpression extends UnaryExpression { 41 Expression left; 42 43 /** 44 * Constructor 45 */ BinaryExpression(int op, long where, Type type, Expression left, Expression right)46 BinaryExpression(int op, long where, Type type, Expression left, Expression right) { 47 super(op, where, type, right); 48 this.left = left; 49 } 50 51 /** 52 * Order the expression based on precedence 53 */ order()54 public Expression order() { 55 if (precedence() > left.precedence()) { 56 UnaryExpression e = (UnaryExpression)left; 57 left = e.right; 58 e.right = order(); 59 return e; 60 } 61 return this; 62 } 63 64 /** 65 * Check a binary expression 66 */ checkValue(Environment env, Context ctx, Vset vset, Hashtable<Object, Object> exp)67 public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable<Object, Object> exp) { 68 vset = left.checkValue(env, ctx, vset, exp); 69 vset = right.checkValue(env, ctx, vset, exp); 70 71 int tm = left.type.getTypeMask() | right.type.getTypeMask(); 72 if ((tm & TM_ERROR) != 0) { 73 return vset; 74 } 75 selectType(env, ctx, tm); 76 77 if (type.isType(TC_ERROR)) { 78 env.error(where, "invalid.args", opNames[op]); 79 } 80 return vset; 81 } 82 83 /** 84 * Check if constant 85 */ isConstant()86 public boolean isConstant() { 87 switch (op) { 88 case MUL: 89 case DIV: 90 case REM: 91 case ADD: 92 case SUB: 93 case LSHIFT: 94 case RSHIFT: 95 case URSHIFT: 96 case LT: 97 case LE: 98 case GT: 99 case GE: 100 case EQ: 101 case NE: 102 case BITAND: 103 case BITXOR: 104 case BITOR: 105 case AND: 106 case OR: 107 return left.isConstant() && right.isConstant(); 108 } 109 return false; 110 } 111 /** 112 * Evaluate 113 */ eval(int a, int b)114 Expression eval(int a, int b) { 115 return this; 116 } eval(long a, long b)117 Expression eval(long a, long b) { 118 return this; 119 } eval(float a, float b)120 Expression eval(float a, float b) { 121 return this; 122 } eval(double a, double b)123 Expression eval(double a, double b) { 124 return this; 125 } eval(boolean a, boolean b)126 Expression eval(boolean a, boolean b) { 127 return this; 128 } eval(String a, String b)129 Expression eval(String a, String b) { 130 return this; 131 } eval()132 Expression eval() { 133 // See also the eval() code in BinaryShiftExpression.java. 134 if (left.op == right.op) { 135 switch (left.op) { 136 case BYTEVAL: 137 case CHARVAL: 138 case SHORTVAL: 139 case INTVAL: 140 return eval(((IntegerExpression)left).value, ((IntegerExpression)right).value); 141 case LONGVAL: 142 return eval(((LongExpression)left).value, ((LongExpression)right).value); 143 case FLOATVAL: 144 return eval(((FloatExpression)left).value, ((FloatExpression)right).value); 145 case DOUBLEVAL: 146 return eval(((DoubleExpression)left).value, ((DoubleExpression)right).value); 147 case BOOLEANVAL: 148 return eval(((BooleanExpression)left).value, ((BooleanExpression)right).value); 149 case STRINGVAL: 150 return eval(((StringExpression)left).value, ((StringExpression)right).value); 151 } 152 } 153 return this; 154 } 155 156 /** 157 * Inline 158 */ inline(Environment env, Context ctx)159 public Expression inline(Environment env, Context ctx) { 160 left = left.inline(env, ctx); 161 right = right.inline(env, ctx); 162 return (left == null) ? right : new CommaExpression(where, left, right); 163 } inlineValue(Environment env, Context ctx)164 public Expression inlineValue(Environment env, Context ctx) { 165 left = left.inlineValue(env, ctx); 166 right = right.inlineValue(env, ctx); 167 try { 168 return eval().simplify(); 169 } catch (ArithmeticException e) { 170 // Got rid of this error message. It isn't illegal to 171 // have a program which does a constant division by 172 // zero. We return `this' to make the compiler to 173 // generate code here. 174 // (bugs 4019304, 4089107). 175 // 176 // env.error(where, "arithmetic.exception"); 177 return this; 178 } 179 } 180 181 /** 182 * Create a copy of the expression for method inlining 183 */ copyInline(Context ctx)184 public Expression copyInline(Context ctx) { 185 BinaryExpression e = (BinaryExpression)clone(); 186 if (left != null) { 187 e.left = left.copyInline(ctx); 188 } 189 if (right != null) { 190 e.right = right.copyInline(ctx); 191 } 192 return e; 193 } 194 195 /** 196 * The cost of inlining this expression 197 */ costInline(int thresh, Environment env, Context ctx)198 public int costInline(int thresh, Environment env, Context ctx) { 199 return 1 + ((left != null) ? left.costInline(thresh, env, ctx) : 0) + 200 ((right != null) ? right.costInline(thresh, env, ctx) : 0); 201 } 202 203 /** 204 * Code 205 */ codeOperation(Environment env, Context ctx, Assembler asm)206 void codeOperation(Environment env, Context ctx, Assembler asm) { 207 throw new CompilerError("codeOperation: " + opNames[op]); 208 } codeValue(Environment env, Context ctx, Assembler asm)209 public void codeValue(Environment env, Context ctx, Assembler asm) { 210 if (type.isType(TC_BOOLEAN)) { 211 Label l1 = new Label(); 212 Label l2 = new Label(); 213 214 codeBranch(env, ctx, asm, l1, true); 215 asm.add(true, where, opc_ldc, 0); 216 asm.add(true, where, opc_goto, l2); 217 asm.add(l1); 218 asm.add(true, where, opc_ldc, 1); 219 asm.add(l2); 220 } else { 221 left.codeValue(env, ctx, asm); 222 right.codeValue(env, ctx, asm); 223 codeOperation(env, ctx, asm); 224 } 225 } 226 227 /** 228 * Print 229 */ print(PrintStream out)230 public void print(PrintStream out) { 231 out.print("(" + opNames[op] + " "); 232 if (left != null) { 233 left.print(out); 234 } else { 235 out.print("<null>"); 236 } 237 out.print(" "); 238 if (right != null) { 239 right.print(out); 240 } else { 241 out.print("<null>"); 242 } 243 out.print(")"); 244 } 245 } 246