blob: 15de8d9c2b89d063b6cf3378e8a213f7cc2cb53a [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1994-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.tools.tree;
27
28import sun.tools.java.*;
29import sun.tools.asm.Label;
30import sun.tools.asm.Assembler;
31import java.io.PrintStream;
32import 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 */
39public
40class Expression extends Node {
41 Type type;
42
43 /**
44 * Constructor
45 */
46 Expression(int op, long where, Type type) {
47 super(op, where);
48 this.type = type;
49 }
50
51 /**
52 * Type checking may assign a more complex implementation
53 * to an innocuous-looking expression (like an identifier).
54 * Return that implementation, or the original expression itself
55 * if there is no special implementation.
56 * <p>
57 * This appears at present to be dead code, and is not called
58 * from within javac. Access to the implementation generally
59 * occurs within the same class, and thus uses the underlying
60 * field directly.
61 */
62 public Expression getImplementation() {
63 return this;
64 }
65
66 public Type getType() {
67 return type;
68 }
69
70 /**
71 * Return the precedence of the operator
72 */
73 int precedence() {
74 return (op < opPrecedence.length) ? opPrecedence[op] : 100;
75 }
76
77 /**
78 * Order the expression based on precedence
79 */
80 public Expression order() {
81 return this;
82 }
83
84 /**
85 * Return true if constant, according to JLS 15.27.
86 * A constant expression must inline away to a literal constant.
87 */
88 public boolean isConstant() {
89 return false;
90 }
91
92 /**
93 * Return the constant value.
94 */
95 public Object getValue() {
96 return null;
97 }
98
99 /**
100 * Check if the expression is known to be equal to a given value.
101 * Returns false for any expression other than a literal constant,
102 * thus should be called only after simplification (inlining) has
103 * been performed.
104 */
105 public boolean equals(int i) {
106 return false;
107 }
108 public boolean equals(boolean b) {
109 return false;
110 }
111 public boolean equals(Identifier id) {
112 return false;
113 }
114 public boolean equals(String s) {
115 return false;
116 }
117
118 /**
119 * Check if the expression must be a null reference.
120 */
121 public boolean isNull() {
122 return false;
123 }
124
125 /**
126 * Check if the expression cannot be a null reference.
127 */
128 public boolean isNonNull() {
129 return false;
130 }
131
132 /**
133 * Check if the expression is equal to its default static value
134 */
135 public boolean equalsDefault() {
136 return false;
137 }
138
139
140 /**
141 * Convert an expresion to a type
142 */
143 Type toType(Environment env, Context ctx) {
144 env.error(where, "invalid.type.expr");
145 return Type.tError;
146 }
147
148 /**
149 * Convert an expresion to a type in a context where a qualified
150 * type name is expected, e.g., in the prefix of a qualified type
151 * name.
152 */
153 /*-----------------------------------------------------*
154 Type toQualifiedType(Environment env, Context ctx) {
155 env.error(where, "invalid.type.expr");
156 return Type.tError;
157 }
158 *-----------------------------------------------------*/
159
160 /**
161 * See if this expression fits in the given type.
162 * This is useful because some larger numbers fit into
163 * smaller types.
164 * <p>
165 * If it is an "int" constant expression, inline it, if necessary,
166 * to examine its numerical value. See JLS 5.2 and 15.24.
167 */
168 public boolean fitsType(Environment env, Context ctx, Type t) {
169 try {
170 if (env.isMoreSpecific(this.type, t)) {
171 return true;
172 }
173 if (this.type.isType(TC_INT) && this.isConstant() && ctx != null) {
174 // Tentative inlining is harmless for constant expressions.
175 Expression n = this.inlineValue(env, ctx);
176 if (n != this && n instanceof ConstantExpression) {
177 return n.fitsType(env, ctx, t);
178 }
179 }
180 return false;
181 } catch (ClassNotFound e) {
182 return false;
183 }
184 }
185
186 /** @deprecated (for backward compatibility) */
187 @Deprecated
188 public boolean fitsType(Environment env, Type t) {
189 return fitsType(env, (Context) null, t);
190 }
191
192 /**
193 * Check an expression
194 */
195 public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
196 return vset;
197 }
198 public Vset checkInitializer(Environment env, Context ctx, Vset vset, Type t, Hashtable exp) {
199 return checkValue(env, ctx, vset, exp);
200 }
201 public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
202 throw new CompilerError("check failed");
203 }
204
205 public Vset checkLHS(Environment env, Context ctx,
206 Vset vset, Hashtable exp) {
207 env.error(where, "invalid.lhs.assignment");
208 type = Type.tError;
209 return vset;
210 }
211
212 /**
213 * Return a <code>FieldUpdater</code> object to be used in updating the
214 * value of the location denoted by <code>this</code>, which must be an
215 * expression suitable for the left-hand side of an assignment.
216 * This is used for implementing assignments to private fields for which
217 * an access method is required. Returns null if no access method is
218 * needed, in which case the assignment is handled in the usual way, by
219 * direct access. Only simple assignment expressions are handled here
220 * Assignment operators and pre/post increment/decrement operators are
221 * are handled by 'getUpdater' below.
222 * <p>
223 * Called during the checking phase.
224 */
225
226 public FieldUpdater getAssigner(Environment env, Context ctx) {
227 throw new CompilerError("getAssigner lhs");
228 }
229
230 /**
231 * Return a <code>FieldUpdater</code> object to be used in updating the value of the
232 * location denoted by <code>this</code>, which must be an expression suitable for the
233 * left-hand side of an assignment. This is used for implementing the assignment
234 * operators and the increment/decrement operators on private fields that require an
235 * access method, e.g., uplevel from an inner class. Returns null if no access method
236 * is needed.
237 * <p>
238 * Called during the checking phase.
239 */
240
241 public FieldUpdater getUpdater(Environment env, Context ctx) {
242 throw new CompilerError("getUpdater lhs");
243 }
244
245 public Vset checkAssignOp(Environment env, Context ctx,
246 Vset vset, Hashtable exp, Expression outside) {
247 if (outside instanceof IncDecExpression)
248 env.error(where, "invalid.arg", opNames[outside.op]);
249 else
250 env.error(where, "invalid.lhs.assignment");
251 type = Type.tError;
252 return vset;
253 }
254
255 /**
256 * Check something that might be an AmbiguousName (refman 6.5.2).
257 * A string of dot-separated identifiers might be, in order of preference:
258 * <nl>
259 * <li> a variable name followed by fields or types
260 * <li> a type name followed by fields or types
261 * <li> a package name followed a type and then fields or types
262 * </nl>
263 * If a type name is found, it rewrites itself as a <tt>TypeExpression</tt>.
264 * If a node decides it can only be a package prefix, it sets its
265 * type to <tt>Type.tPackage</tt>. The caller must detect this
266 * and act appropriately to verify the full package name.
267 * @arg loc the expression containing the ambiguous expression
268 */
269 public Vset checkAmbigName(Environment env, Context ctx, Vset vset, Hashtable exp,
270 UnaryExpression loc) {
271 return checkValue(env, ctx, vset, exp);
272 }
273
274 /**
275 * Check a condition. Return a ConditionVars(), which indicates when
276 * which variables are set if the condition is true, and which are set if
277 * the condition is false.
278 */
279 public ConditionVars checkCondition(Environment env, Context ctx,
280 Vset vset, Hashtable exp) {
281 ConditionVars cvars = new ConditionVars();
282 checkCondition(env, ctx, vset, exp, cvars);
283 return cvars;
284 }
285
286 /*
287 * Check a condition.
288 *
289 * cvars is modified so that
290 * cvar.vsTrue indicates variables with a known value if result = true
291 * cvars.vsFalse indicates variables with a known value if !result
292 *
293 * The default action is to simply call checkValue on the expression, and
294 * to see both vsTrue and vsFalse to the result.
295 */
296
297 public void checkCondition(Environment env, Context ctx,
298 Vset vset, Hashtable exp, ConditionVars cvars) {
299 cvars.vsTrue = cvars.vsFalse = checkValue(env, ctx, vset, exp);
300 // unshare side effects:
301 cvars.vsFalse = cvars.vsFalse.copy();
302 }
303
304 /**
305 * Evaluate.
306 *
307 * Attempt to compute the value of an expression node. If all operands are
308 * literal constants of the same kind (e.g., IntegerExpression nodes), a
309 * new constant node of the proper type is returned representing the value
310 * as computed at compile-time. Otherwise, the original node 'this' is
311 * returned.
312 */
313 Expression eval() {
314 return this;
315 }
316
317 /**
318 * Simplify.
319 *
320 * Attempt to simplify an expression node by returning a semantically-
321 * equivalent expression that is presumably less costly to execute. There
322 * is some overlap with the intent of 'eval', as compile-time evaluation of
323 * conditional expressions and the short-circuit boolean operators is
324 * performed here. Other simplifications include logical identities
325 * involving logical negation and comparisons. If no simplification is
326 * possible, the original node 'this' is returned. It is assumed that the
327 * children of the node have previously been recursively simplified and
328 * evaluated. A result of 'null' indicates that the expression may be
329 * elided entirely.
330 */
331 Expression simplify() {
332 return this;
333 }
334
335 /**
336 * Inline.
337 *
338 * Recursively simplify each child of an expression node, destructively
339 * replacing the child with the simplified result. Also attempts to
340 * simplify the current node 'this', and returns the simplified result.
341 *
342 * The name 'inline' is somthing of a misnomer, as these methods are
343 * responsible for compile-time expression simplification in general.
344 * The 'eval' and 'simplify' methods apply to a single expression node
345 * only -- it is 'inline' and 'inlineValue' that drive the simplification
346 * of entire expressions.
347 */
348 public Expression inline(Environment env, Context ctx) {
349 return null;
350 }
351 public Expression inlineValue(Environment env, Context ctx) {
352 return this;
353 }
354
355 /**
356 * Attempt to evaluate this expression. If this expression
357 * yields a value, append it to the StringBuffer `buffer'.
358 * If this expression cannot be evaluated at this time (for
359 * example if it contains a division by zero, a non-constant
360 * subexpression, or a subexpression which "refuses" to evaluate)
361 * then return `null' to indicate failure.
362 *
363 * It is anticipated that this method will be called to evaluate
364 * concatenations of compile-time constant strings. The call
365 * originates from AddExpression#inlineValue().
366 *
367 * See AddExpression#inlineValueSB() for detailed comments.
368 */
369 protected StringBuffer inlineValueSB(Environment env,
370 Context ctx,
371 StringBuffer buffer) {
372 Expression inlined = inlineValue(env, ctx);
373 Object val = inlined.getValue();
374
375 if (val == null && !inlined.isNull()){
376 // This (supposedly constant) expression refuses to yield
377 // a value. This can happen, in particular, when we are
378 // trying to evaluate a division by zero. It can also
379 // happen in cases where isConstant() is able to classify
380 // expressions as constant that the compiler's inlining
381 // mechanisms aren't able to evaluate; this is rare,
382 // and all such cases that we have found so far
383 // (e.g. 4082814, 4106244) have been plugged up.
384 //
385 // We return a null to indicate that we have failed to
386 // evaluate the concatenation.
387 return null;
388 }
389
390 // For boolean and character expressions, getValue() returns
391 // an Integer. We need to take care, when appending the result
392 // of getValue(), that we preserve the type.
393 // Fix for 4103959, 4102672.
394 if (type == Type.tChar) {
395 buffer.append((char)((Integer)val).intValue());
396 } else if (type == Type.tBoolean) {
397 buffer.append(((Integer)val).intValue() != 0);
398 } else {
399 buffer.append(val);
400 }
401
402 return buffer;
403 }
404
405 public Expression inlineLHS(Environment env, Context ctx) {
406 return null;
407 }
408
409 /**
410 * The cost of inlining this expression.
411 * This cost controls the inlining of methods, and does not determine
412 * the compile-time simplifications performed by 'inline' and friends.
413 */
414 public int costInline(int thresh, Environment env, Context ctx) {
415 return 1;
416 }
417
418 /**
419 * Code
420 */
421 void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
422 if (type.isType(TC_BOOLEAN)) {
423 codeValue(env, ctx, asm);
424 asm.add(where, whenTrue ? opc_ifne : opc_ifeq, lbl, whenTrue);
425 } else {
426 throw new CompilerError("codeBranch " + opNames[op]);
427 }
428 }
429 public void codeValue(Environment env, Context ctx, Assembler asm) {
430 if (type.isType(TC_BOOLEAN)) {
431 Label l1 = new Label();
432 Label l2 = new Label();
433
434 codeBranch(env, ctx, asm, l1, true);
435 asm.add(true, where, opc_ldc, new Integer(0));
436 asm.add(true, where, opc_goto, l2);
437 asm.add(l1);
438 asm.add(true, where, opc_ldc, new Integer(1));
439 asm.add(l2);
440 } else {
441 throw new CompilerError("codeValue");
442 }
443 }
444 public void code(Environment env, Context ctx, Assembler asm) {
445 codeValue(env, ctx, asm);
446
447 switch (type.getTypeCode()) {
448 case TC_VOID:
449 break;
450
451 case TC_DOUBLE:
452 case TC_LONG:
453 asm.add(where, opc_pop2);
454 break;
455
456 default:
457 asm.add(where, opc_pop);
458 break;
459 }
460 }
461 int codeLValue(Environment env, Context ctx, Assembler asm) {
462 print(System.out);
463 throw new CompilerError("invalid lhs");
464 }
465 void codeLoad(Environment env, Context ctx, Assembler asm) {
466 print(System.out);
467 throw new CompilerError("invalid load");
468 }
469 void codeStore(Environment env, Context ctx, Assembler asm) {
470 print(System.out);
471 throw new CompilerError("invalid store");
472 }
473
474 /**
475 * Convert this expression to a string.
476 */
477 void ensureString(Environment env, Context ctx, Assembler asm)
478 throws ClassNotFound, AmbiguousMember
479 {
480 if (type == Type.tString && isNonNull()) {
481 return;
482 }
483 // Make sure it's a non-null string.
484 ClassDefinition sourceClass = ctx.field.getClassDefinition();
485 ClassDeclaration stClass = env.getClassDeclaration(Type.tString);
486 ClassDefinition stClsDef = stClass.getClassDefinition(env);
487 // FIX FOR 4071548
488 // We use 'String.valueOf' to do the conversion, in order to
489 // correctly handle null references and efficiently handle
490 // primitive types. For reference types, we force the argument
491 // to be interpreted as of 'Object' type, thus avoiding the
492 // the special-case overloading of 'valueOf' for character arrays.
493 // This special treatment would conflict with JLS 15.17.1.1.
494 if (type.inMask(TM_REFERENCE)) {
495 // Reference type
496 if (type != Type.tString) {
497 // Convert non-string object to string. If object is
498 // a string, we don't need to convert it, except in the
499 // case that it is null, which is handled below.
500 Type argType1[] = {Type.tObject};
501 MemberDefinition f1 =
502 stClsDef.matchMethod(env, sourceClass, idValueOf, argType1);
503 asm.add(where, opc_invokestatic, f1);
504 }
505 // FIX FOR 4030173
506 // If the argument was null, then value is "null", but if the
507 // argument was not null, 'toString' was called and could have
508 // returned null. We call 'valueOf' again to make sure that
509 // the result is a non-null string. See JLS 15.17.1.1. The
510 // approach taken here minimizes code size -- open code would
511 // be faster. The 'toString' method for an array class cannot
512 // be overridden, thus we know that it will never return null.
513 if (!type.inMask(TM_ARRAY|TM_NULL)) {
514 Type argType2[] = {Type.tString};
515 MemberDefinition f2 =
516 stClsDef.matchMethod(env, sourceClass, idValueOf, argType2);
517 asm.add(where, opc_invokestatic, f2);
518 }
519 } else {
520 // Primitive type
521 Type argType[] = {type};
522 MemberDefinition f =
523 stClsDef.matchMethod(env, sourceClass, idValueOf, argType);
524 asm.add(where, opc_invokestatic, f);
525 }
526 }
527
528 /**
529 * Convert this expression to a string and append it to the string
530 * buffer on the top of the stack.
531 * If the needBuffer argument is true, the string buffer needs to be
532 * created, initialized, and pushed on the stack, first.
533 */
534 void codeAppend(Environment env, Context ctx, Assembler asm,
535 ClassDeclaration sbClass, boolean needBuffer)
536 throws ClassNotFound, AmbiguousMember
537 {
538 ClassDefinition sourceClass = ctx.field.getClassDefinition();
539 ClassDefinition sbClsDef = sbClass.getClassDefinition(env);
540 MemberDefinition f;
541 if (needBuffer) {
542 // need to create the string buffer
543 asm.add(where, opc_new, sbClass); // create the class
544 asm.add(where, opc_dup);
545 if (equals("")) {
546 // make an empty string buffer
547 f = sbClsDef.matchMethod(env, sourceClass, idInit);
548 } else {
549 // optimize by initializing the buffer with the string
550 codeValue(env, ctx, asm);
551 ensureString(env, ctx, asm);
552 Type argType[] = {Type.tString};
553 f = sbClsDef.matchMethod(env, sourceClass, idInit, argType);
554 }
555 asm.add(where, opc_invokespecial, f);
556 } else {
557 // append this item to the string buffer
558 codeValue(env, ctx, asm);
559 // FIX FOR 4071548
560 // 'StringBuffer.append' converts its argument as if by
561 // 'valueOf', treating character arrays specially. This
562 // violates JLS 15.17.1.1, which requires that concatenation
563 // convert non-primitive arguments using 'toString'. We force
564 // the treatment of all reference types as type 'Object', thus
565 // invoking an overloading of 'append' that has the required
566 // semantics.
567 Type argType[] =
568 { (type.inMask(TM_REFERENCE) && type != Type.tString)
569 ? Type.tObject
570 : type };
571 f = sbClsDef.matchMethod(env, sourceClass, idAppend, argType);
572 asm.add(where, opc_invokevirtual, f);
573 }
574 }
575
576 /**
577 * Code
578 */
579 void codeDup(Environment env, Context ctx, Assembler asm, int items, int depth) {
580 switch (items) {
581 case 0:
582 return;
583
584 case 1:
585 switch (depth) {
586 case 0:
587 asm.add(where, opc_dup);
588 return;
589 case 1:
590 asm.add(where, opc_dup_x1);
591 return;
592 case 2:
593 asm.add(where, opc_dup_x2);
594 return;
595
596 }
597 break;
598 case 2:
599 switch (depth) {
600 case 0:
601 asm.add(where, opc_dup2);
602 return;
603 case 1:
604 asm.add(where, opc_dup2_x1);
605 return;
606 case 2:
607 asm.add(where, opc_dup2_x2);
608 return;
609
610 }
611 break;
612 }
613 throw new CompilerError("can't dup: " + items + ", " + depth);
614 }
615
616 void codeConversion(Environment env, Context ctx, Assembler asm, Type f, Type t) {
617 int from = f.getTypeCode();
618 int to = t.getTypeCode();
619
620 switch (to) {
621 case TC_BOOLEAN:
622 if (from != TC_BOOLEAN) {
623 break;
624 }
625 return;
626 case TC_BYTE:
627 if (from != TC_BYTE) {
628 codeConversion(env, ctx, asm, f, Type.tInt);
629 asm.add(where, opc_i2b);
630 }
631 return;
632 case TC_CHAR:
633 if (from != TC_CHAR) {
634 codeConversion(env, ctx, asm, f, Type.tInt);
635 asm.add(where, opc_i2c);
636 }
637 return;
638 case TC_SHORT:
639 if (from != TC_SHORT) {
640 codeConversion(env, ctx, asm, f, Type.tInt);
641 asm.add(where, opc_i2s);
642 }
643 return;
644 case TC_INT:
645 switch (from) {
646 case TC_BYTE:
647 case TC_CHAR:
648 case TC_SHORT:
649 case TC_INT:
650 return;
651 case TC_LONG:
652 asm.add(where, opc_l2i);
653 return;
654 case TC_FLOAT:
655 asm.add(where, opc_f2i);
656 return;
657 case TC_DOUBLE:
658 asm.add(where, opc_d2i);
659 return;
660 }
661 break;
662 case TC_LONG:
663 switch (from) {
664 case TC_BYTE:
665 case TC_CHAR:
666 case TC_SHORT:
667 case TC_INT:
668 asm.add(where, opc_i2l);
669 return;
670 case TC_LONG:
671 return;
672 case TC_FLOAT:
673 asm.add(where, opc_f2l);
674 return;
675 case TC_DOUBLE:
676 asm.add(where, opc_d2l);
677 return;
678 }
679 break;
680 case TC_FLOAT:
681 switch (from) {
682 case TC_BYTE:
683 case TC_CHAR:
684 case TC_SHORT:
685 case TC_INT:
686 asm.add(where, opc_i2f);
687 return;
688 case TC_LONG:
689 asm.add(where, opc_l2f);
690 return;
691 case TC_FLOAT:
692 return;
693 case TC_DOUBLE:
694 asm.add(where, opc_d2f);
695 return;
696 }
697 break;
698 case TC_DOUBLE:
699 switch (from) {
700 case TC_BYTE:
701 case TC_CHAR:
702 case TC_SHORT:
703 case TC_INT:
704 asm.add(where, opc_i2d);
705 return;
706 case TC_LONG:
707 asm.add(where, opc_l2d);
708 return;
709 case TC_FLOAT:
710 asm.add(where, opc_f2d);
711 return;
712 case TC_DOUBLE:
713 return;
714 }
715 break;
716
717 case TC_CLASS:
718 switch (from) {
719 case TC_NULL:
720 return;
721 case TC_CLASS:
722 case TC_ARRAY:
723 try {
724 if (!env.implicitCast(f, t)) {
725 asm.add(where, opc_checkcast, env.getClassDeclaration(t));
726 }
727 } catch (ClassNotFound e) {
728 throw new CompilerError(e);
729 }
730 return;
731 }
732
733 break;
734
735 case TC_ARRAY:
736 switch (from) {
737 case TC_NULL:
738 return;
739 case TC_CLASS:
740 case TC_ARRAY:
741 try {
742 if (!env.implicitCast(f, t)) {
743 asm.add(where, opc_checkcast, t);
744 }
745 return;
746 } catch (ClassNotFound e) {
747 throw new CompilerError(e);
748 }
749 }
750 break;
751 }
752 throw new CompilerError("codeConversion: " + from + ", " + to);
753 }
754
755 /**
756 * Check if the first thing is a constructor invocation
757 */
758 public Expression firstConstructor() {
759 return null;
760 }
761
762 /**
763 * Create a copy of the expression for method inlining
764 */
765 public Expression copyInline(Context ctx) {
766 return (Expression)clone();
767 }
768
769 /**
770 * Print
771 */
772 public void print(PrintStream out) {
773 out.print(opNames[op]);
774 }
775}