Makefile fixup
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ast / BinaryExpression.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.internal.compiler.ASTVisitor;
14 import org.eclipse.jdt.internal.compiler.impl.*;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18
19 public class BinaryExpression extends OperatorExpression {
20
21         public Expression left, right;
22         public Constant optimizedBooleanConstant;
23
24         public BinaryExpression(Expression left, Expression right, int operator) {
25
26                 this.left = left;
27                 this.right = right;
28                 this.bits |= operator << OperatorSHIFT; // encode operator
29                 this.sourceStart = left.sourceStart;
30                 this.sourceEnd = right.sourceEnd;
31         }
32
33         public FlowInfo analyseCode(
34                 BlockScope currentScope,
35                 FlowContext flowContext,
36                 FlowInfo flowInfo) {
37
38                 return right
39                         .analyseCode(
40                                 currentScope,
41                                 flowContext,
42                                 left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
43                         .unconditionalInits();
44         }
45
46         public void computeConstant(BlockScope scope, int leftId, int rightId) {
47
48                 //compute the constant when valid
49                 if ((this.left.constant != Constant.NotAConstant)
50                         && (this.right.constant != Constant.NotAConstant)) {
51                         try {
52                                 this.constant =
53                                         Constant.computeConstantOperation(
54                                                 this.left.constant,
55                                                 leftId,
56                                                 (this.bits & OperatorMASK) >> OperatorSHIFT,
57                                                 this.right.constant,
58                                                 rightId);
59                         } catch (ArithmeticException e) {
60                                 this.constant = Constant.NotAConstant;
61                                 // 1.2 no longer throws an exception at compile-time
62                                 //scope.problemReporter().compileTimeConstantThrowsArithmeticException(this);
63                         }
64                 } else {
65                         this.constant = Constant.NotAConstant;
66                         //add some work for the boolean operators & |  
67                         this.optimizedBooleanConstant(
68                                 leftId,
69                                 (this.bits & OperatorMASK) >> OperatorSHIFT,
70                                 rightId);
71                 }
72         }
73
74         public Constant optimizedBooleanConstant() {
75
76                 return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant;
77         }
78
79         /**
80          * Code generation for a binary operation
81          */
82         public void generateCode(
83                 BlockScope currentScope,
84                 CodeStream codeStream,
85                 boolean valueRequired) {
86
87                 int pc = codeStream.position;
88                 Label falseLabel, endLabel;
89                 if (constant != Constant.NotAConstant) {
90                         if (valueRequired)
91                                 codeStream.generateConstant(constant, implicitConversion);
92                         codeStream.recordPositionsFrom(pc, this.sourceStart);
93                         return;
94                 }
95                 bits |= OnlyValueRequiredMASK;
96                 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
97                         case PLUS :
98                                 switch (bits & ReturnTypeIDMASK) {
99                                         case T_String :
100                                                 codeStream.generateStringAppend(currentScope, left, right);
101                                                 if (!valueRequired)
102                                                         codeStream.pop();
103                                                 break;
104                                         case T_int :
105                                                 left.generateCode(currentScope, codeStream, valueRequired);
106                                                 right.generateCode(currentScope, codeStream, valueRequired);
107                                                 if (valueRequired)
108                                                         codeStream.iadd();
109                                                 break;
110                                         case T_long :
111                                                 left.generateCode(currentScope, codeStream, valueRequired);
112                                                 right.generateCode(currentScope, codeStream, valueRequired);
113                                                 if (valueRequired)
114                                                         codeStream.ladd();
115                                                 break;
116                                         case T_double :
117                                                 left.generateCode(currentScope, codeStream, valueRequired);
118                                                 right.generateCode(currentScope, codeStream, valueRequired);
119                                                 if (valueRequired)
120                                                         codeStream.dadd();
121                                                 break;
122                                         case T_float :
123                                                 left.generateCode(currentScope, codeStream, valueRequired);
124                                                 right.generateCode(currentScope, codeStream, valueRequired);
125                                                 if (valueRequired)
126                                                         codeStream.fadd();
127                                                 break;
128                                 }
129                                 break;
130                         case MINUS :
131                                 switch (bits & ReturnTypeIDMASK) {
132                                         case T_int :
133                                                 left.generateCode(currentScope, codeStream, valueRequired);
134                                                 right.generateCode(currentScope, codeStream, valueRequired);
135                                                 if (valueRequired)
136                                                         codeStream.isub();
137                                                 break;
138                                         case T_long :
139                                                 left.generateCode(currentScope, codeStream, valueRequired);
140                                                 right.generateCode(currentScope, codeStream, valueRequired);
141                                                 if (valueRequired)
142                                                         codeStream.lsub();
143                                                 break;
144                                         case T_double :
145                                                 left.generateCode(currentScope, codeStream, valueRequired);
146                                                 right.generateCode(currentScope, codeStream, valueRequired);
147                                                 if (valueRequired)
148                                                         codeStream.dsub();
149                                                 break;
150                                         case T_float :
151                                                 left.generateCode(currentScope, codeStream, valueRequired);
152                                                 right.generateCode(currentScope, codeStream, valueRequired);
153                                                 if (valueRequired)
154                                                         codeStream.fsub();
155                                                 break;
156                                 }
157                                 break;
158                         case MULTIPLY :
159                                 switch (bits & ReturnTypeIDMASK) {
160                                         case T_int :
161                                                 left.generateCode(currentScope, codeStream, valueRequired);
162                                                 right.generateCode(currentScope, codeStream, valueRequired);
163                                                 if (valueRequired)
164                                                         codeStream.imul();
165                                                 break;
166                                         case T_long :
167                                                 left.generateCode(currentScope, codeStream, valueRequired);
168                                                 right.generateCode(currentScope, codeStream, valueRequired);
169                                                 if (valueRequired)
170                                                         codeStream.lmul();
171                                                 break;
172                                         case T_double :
173                                                 left.generateCode(currentScope, codeStream, valueRequired);
174                                                 right.generateCode(currentScope, codeStream, valueRequired);
175                                                 if (valueRequired)
176                                                         codeStream.dmul();
177                                                 break;
178                                         case T_float :
179                                                 left.generateCode(currentScope, codeStream, valueRequired);
180                                                 right.generateCode(currentScope, codeStream, valueRequired);
181                                                 if (valueRequired)
182                                                         codeStream.fmul();
183                                                 break;
184                                 }
185                                 break;
186                         case DIVIDE :
187                                 switch (bits & ReturnTypeIDMASK) {
188                                         case T_int :
189                                                 left.generateCode(currentScope, codeStream, true);
190                                                 right.generateCode(currentScope, codeStream, true);
191                                                 codeStream.idiv();
192                                                 if (!valueRequired)
193                                                         codeStream.pop();
194                                                 break;
195                                         case T_long :
196                                                 left.generateCode(currentScope, codeStream, true);
197                                                 right.generateCode(currentScope, codeStream, true);
198                                                 codeStream.ldiv();
199                                                 if (!valueRequired)
200                                                         codeStream.pop2();
201                                                 break;
202                                         case T_double :
203                                                 left.generateCode(currentScope, codeStream, valueRequired);
204                                                 right.generateCode(currentScope, codeStream, valueRequired);
205                                                 if (valueRequired)
206                                                         codeStream.ddiv();
207                                                 break;
208                                         case T_float :
209                                                 left.generateCode(currentScope, codeStream, valueRequired);
210                                                 right.generateCode(currentScope, codeStream, valueRequired);
211                                                 if (valueRequired)
212                                                         codeStream.fdiv();
213                                                 break;
214                                 }
215                                 break;
216                         case REMAINDER :
217                                 switch (bits & ReturnTypeIDMASK) {
218                                         case T_int :
219                                                 left.generateCode(currentScope, codeStream, true);
220                                                 right.generateCode(currentScope, codeStream, true);
221                                                 codeStream.irem();
222                                                 if (!valueRequired)
223                                                         codeStream.pop();
224                                                 break;
225                                         case T_long :
226                                                 left.generateCode(currentScope, codeStream, true);
227                                                 right.generateCode(currentScope, codeStream, true);
228                                                 codeStream.lrem();
229                                                 if (!valueRequired)
230                                                         codeStream.pop2();
231                                                 break;
232                                         case T_double :
233                                                 left.generateCode(currentScope, codeStream, valueRequired);
234                                                 right.generateCode(currentScope, codeStream, valueRequired);
235                                                 if (valueRequired)
236                                                         codeStream.drem();
237                                                 break;
238                                         case T_float :
239                                                 left.generateCode(currentScope, codeStream, valueRequired);
240                                                 right.generateCode(currentScope, codeStream, valueRequired);
241                                                 if (valueRequired)
242                                                         codeStream.frem();
243                                                 break;
244                                 }
245                                 break;
246                         case AND :
247                                 switch (bits & ReturnTypeIDMASK) {
248                                         case T_int :
249                                                 // 0 & x
250                                                 if ((left.constant != Constant.NotAConstant)
251                                                         && (left.constant.typeID() == T_int)
252                                                         && (left.constant.intValue() == 0)) {
253                                                         right.generateCode(currentScope, codeStream, false);
254                                                         if (valueRequired)
255                                                                 codeStream.iconst_0();
256                                                 } else {
257                                                         // x & 0
258                                                         if ((right.constant != Constant.NotAConstant)
259                                                                 && (right.constant.typeID() == T_int)
260                                                                 && (right.constant.intValue() == 0)) {
261                                                                 left.generateCode(currentScope, codeStream, false);
262                                                                 if (valueRequired)
263                                                                         codeStream.iconst_0();
264                                                         } else {
265                                                                 left.generateCode(currentScope, codeStream, valueRequired);
266                                                                 right.generateCode(currentScope, codeStream, valueRequired);
267                                                                 if (valueRequired)
268                                                                         codeStream.iand();
269                                                         }
270                                                 }
271                                                 break;
272                                         case T_long :
273                                                 // 0 & x
274                                                 if ((left.constant != Constant.NotAConstant)
275                                                         && (left.constant.typeID() == T_long)
276                                                         && (left.constant.longValue() == 0L)) {
277                                                         right.generateCode(currentScope, codeStream, false);
278                                                         if (valueRequired)
279                                                                 codeStream.lconst_0();
280                                                 } else {
281                                                         // x & 0
282                                                         if ((right.constant != Constant.NotAConstant)
283                                                                 && (right.constant.typeID() == T_long)
284                                                                 && (right.constant.longValue() == 0L)) {
285                                                                 left.generateCode(currentScope, codeStream, false);
286                                                                 if (valueRequired)
287                                                                         codeStream.lconst_0();
288                                                         } else {
289                                                                 left.generateCode(currentScope, codeStream, valueRequired);
290                                                                 right.generateCode(currentScope, codeStream, valueRequired);
291                                                                 if (valueRequired)
292                                                                         codeStream.land();
293                                                         }
294                                                 }
295                                                 break;
296                                         case T_boolean : // logical and
297                                                 generateOptimizedLogicalAnd(
298                                                         currentScope,
299                                                         codeStream,
300                                                         null,
301                                                         (falseLabel = new Label(codeStream)),
302                                                         valueRequired);
303                                                 /* improving code gen for such a case: boolean b = i < 0 && false;
304                                                  * since the label has never been used, we have the inlined value on the stack. */
305                                                 if (falseLabel.hasForwardReferences()) {
306                                                         if (valueRequired) {
307                                                                 codeStream.iconst_1();
308                                                                 if ((bits & ValueForReturnMASK) != 0) {
309                                                                         codeStream.ireturn();
310                                                                         falseLabel.place();
311                                                                         codeStream.iconst_0();
312                                                                 } else {
313                                                                         codeStream.goto_(endLabel = new Label(codeStream));
314                                                                         codeStream.decrStackSize(1);
315                                                                         falseLabel.place();
316                                                                         codeStream.iconst_0();
317                                                                         endLabel.place();
318                                                                 }
319                                                         } else {
320                                                                 falseLabel.place();
321                                                         }
322                                                 }
323                                 }
324                                 break;
325                         case OR :
326                                 switch (bits & ReturnTypeIDMASK) {
327                                         case T_int :
328                                                 // 0 | x
329                                                 if ((left.constant != Constant.NotAConstant)
330                                                         && (left.constant.typeID() == T_int)
331                                                         && (left.constant.intValue() == 0)) {
332                                                         right.generateCode(currentScope, codeStream, valueRequired);
333                                                 } else {
334                                                         // x | 0
335                                                         if ((right.constant != Constant.NotAConstant)
336                                                                 && (right.constant.typeID() == T_int)
337                                                                 && (right.constant.intValue() == 0)) {
338                                                                 left.generateCode(currentScope, codeStream, valueRequired);
339                                                         } else {
340                                                                 left.generateCode(currentScope, codeStream, valueRequired);
341                                                                 right.generateCode(currentScope, codeStream, valueRequired);
342                                                                 if (valueRequired)
343                                                                         codeStream.ior();
344                                                         }
345                                                 }
346                                                 break;
347                                         case T_long :
348                                                 // 0 | x
349                                                 if ((left.constant != Constant.NotAConstant)
350                                                         && (left.constant.typeID() == T_long)
351                                                         && (left.constant.longValue() == 0L)) {
352                                                         right.generateCode(currentScope, codeStream, valueRequired);
353                                                 } else {
354                                                         // x | 0
355                                                         if ((right.constant != Constant.NotAConstant)
356                                                                 && (right.constant.typeID() == T_long)
357                                                                 && (right.constant.longValue() == 0L)) {
358                                                                 left.generateCode(currentScope, codeStream, valueRequired);
359                                                         } else {
360                                                                 left.generateCode(currentScope, codeStream, valueRequired);
361                                                                 right.generateCode(currentScope, codeStream, valueRequired);
362                                                                 if (valueRequired)
363                                                                         codeStream.lor();
364                                                         }
365                                                 }
366                                                 break;
367                                         case T_boolean : // logical or
368                                                 generateOptimizedLogicalOr(
369                                                         currentScope,
370                                                         codeStream,
371                                                         null,
372                                                         (falseLabel = new Label(codeStream)),
373                                                         valueRequired);
374                                                 /* improving code gen for such a case: boolean b = i < 0 || true;
375                                                  * since the label has never been used, we have the inlined value on the stack. */
376                                                 if (falseLabel.hasForwardReferences()) {
377                                                         if (valueRequired) {
378                                                                 codeStream.iconst_1();
379                                                                 if ((bits & ValueForReturnMASK) != 0) {
380                                                                         codeStream.ireturn();
381                                                                         falseLabel.place();
382                                                                         codeStream.iconst_0();
383                                                                 } else {
384                                                                         codeStream.goto_(endLabel = new Label(codeStream));
385                                                                         codeStream.decrStackSize(1);
386                                                                         falseLabel.place();
387                                                                         codeStream.iconst_0();
388                                                                         endLabel.place();
389                                                                 }
390                                                         } else {
391                                                                 falseLabel.place();
392                                                         }
393                                                 }
394                                 }
395                                 break;
396                         case XOR :
397                                 switch (bits & ReturnTypeIDMASK) {
398                                         case T_int :
399                                                 // 0 ^ x
400                                                 if ((left.constant != Constant.NotAConstant)
401                                                         && (left.constant.typeID() == T_int)
402                                                         && (left.constant.intValue() == 0)) {
403                                                         right.generateCode(currentScope, codeStream, valueRequired);
404                                                 } else {
405                                                         // x ^ 0
406                                                         if ((right.constant != Constant.NotAConstant)
407                                                                 && (right.constant.typeID() == T_int)
408                                                                 && (right.constant.intValue() == 0)) {
409                                                                 left.generateCode(currentScope, codeStream, valueRequired);
410                                                         } else {
411                                                                 left.generateCode(currentScope, codeStream, valueRequired);
412                                                                 right.generateCode(currentScope, codeStream, valueRequired);
413                                                                 if (valueRequired)
414                                                                         codeStream.ixor();
415                                                         }
416                                                 }
417                                                 break;
418                                         case T_long :
419                                                 // 0 ^ x
420                                                 if ((left.constant != Constant.NotAConstant)
421                                                         && (left.constant.typeID() == T_long)
422                                                         && (left.constant.longValue() == 0L)) {
423                                                         right.generateCode(currentScope, codeStream, valueRequired);
424                                                 } else {
425                                                         // x ^ 0
426                                                         if ((right.constant != Constant.NotAConstant)
427                                                                 && (right.constant.typeID() == T_long)
428                                                                 && (right.constant.longValue() == 0L)) {
429                                                                 left.generateCode(currentScope, codeStream, valueRequired);
430                                                         } else {
431                                                                 left.generateCode(currentScope, codeStream, valueRequired);
432                                                                 right.generateCode(currentScope, codeStream, valueRequired);
433                                                                 if (valueRequired)
434                                                                         codeStream.lxor();
435                                                         }
436                                                 }
437                                                 break;
438                                         case T_boolean :
439                                                 generateOptimizedLogicalXor(
440                                                         currentScope,
441                                                         codeStream,
442                                                         null,
443                                                         (falseLabel = new Label(codeStream)),
444                                                         valueRequired);
445                                                 /* improving code gen for such a case: boolean b = i < 0 ^ bool;
446                                                  * since the label has never been used, we have the inlined value on the stack. */
447                                                 if (falseLabel.hasForwardReferences()) {
448                                                         if (valueRequired) {
449                                                                 codeStream.iconst_1();
450                                                                 if ((bits & ValueForReturnMASK) != 0) {
451                                                                         codeStream.ireturn();
452                                                                         falseLabel.place();
453                                                                         codeStream.iconst_0();
454                                                                 } else {
455                                                                         codeStream.goto_(endLabel = new Label(codeStream));
456                                                                         codeStream.decrStackSize(1);
457                                                                         falseLabel.place();
458                                                                         codeStream.iconst_0();
459                                                                         endLabel.place();
460                                                                 }
461                                                         } else {
462                                                                 falseLabel.place();
463                                                         }
464                                                 }
465                                 }
466                                 break;
467                         case LEFT_SHIFT :
468                                 switch (bits & ReturnTypeIDMASK) {
469                                         case T_int :
470                                                 left.generateCode(currentScope, codeStream, valueRequired);
471                                                 right.generateCode(currentScope, codeStream, valueRequired);
472                                                 if (valueRequired)
473                                                         codeStream.ishl();
474                                                 break;
475                                         case T_long :
476                                                 left.generateCode(currentScope, codeStream, valueRequired);
477                                                 right.generateCode(currentScope, codeStream, valueRequired);
478                                                 if (valueRequired)
479                                                         codeStream.lshl();
480                                 }
481                                 break;
482                         case RIGHT_SHIFT :
483                                 switch (bits & ReturnTypeIDMASK) {
484                                         case T_int :
485                                                 left.generateCode(currentScope, codeStream, valueRequired);
486                                                 right.generateCode(currentScope, codeStream, valueRequired);
487                                                 if (valueRequired)
488                                                         codeStream.ishr();
489                                                 break;
490                                         case T_long :
491                                                 left.generateCode(currentScope, codeStream, valueRequired);
492                                                 right.generateCode(currentScope, codeStream, valueRequired);
493                                                 if (valueRequired)
494                                                         codeStream.lshr();
495                                 }
496                                 break;
497                         case UNSIGNED_RIGHT_SHIFT :
498                                 switch (bits & ReturnTypeIDMASK) {
499                                         case T_int :
500                                                 left.generateCode(currentScope, codeStream, valueRequired);
501                                                 right.generateCode(currentScope, codeStream, valueRequired);
502                                                 if (valueRequired)
503                                                         codeStream.iushr();
504                                                 break;
505                                         case T_long :
506                                                 left.generateCode(currentScope, codeStream, valueRequired);
507                                                 right.generateCode(currentScope, codeStream, valueRequired);
508                                                 if (valueRequired)
509                                                         codeStream.lushr();
510                                 }
511                                 break;
512                         case GREATER :
513                                 generateOptimizedGreaterThan(
514                                         currentScope,
515                                         codeStream,
516                                         null,
517                                         (falseLabel = new Label(codeStream)),
518                                         valueRequired);
519                                 if (valueRequired) {
520                                         codeStream.iconst_1();
521                                         if ((bits & ValueForReturnMASK) != 0) {
522                                                 codeStream.ireturn();
523                                                 falseLabel.place();
524                                                 codeStream.iconst_0();
525                                         } else {
526                                                 codeStream.goto_(endLabel = new Label(codeStream));
527                                                 codeStream.decrStackSize(1);
528                                                 falseLabel.place();
529                                                 codeStream.iconst_0();
530                                                 endLabel.place();
531                                         }
532                                 }
533                                 break;
534                         case GREATER_EQUAL :
535                                 generateOptimizedGreaterThanOrEqual(
536                                         currentScope,
537                                         codeStream,
538                                         null,
539                                         (falseLabel = new Label(codeStream)),
540                                         valueRequired);
541                                 if (valueRequired) {
542                                         codeStream.iconst_1();
543                                         if ((bits & ValueForReturnMASK) != 0) {
544                                                 codeStream.ireturn();
545                                                 falseLabel.place();
546                                                 codeStream.iconst_0();
547                                         } else {
548                                                 codeStream.goto_(endLabel = new Label(codeStream));
549                                                 codeStream.decrStackSize(1);
550                                                 falseLabel.place();
551                                                 codeStream.iconst_0();
552                                                 endLabel.place();
553                                         }
554                                 }
555                                 break;
556                         case LESS :
557                                 generateOptimizedLessThan(
558                                         currentScope,
559                                         codeStream,
560                                         null,
561                                         (falseLabel = new Label(codeStream)),
562                                         valueRequired);
563                                 if (valueRequired) {
564                                         codeStream.iconst_1();
565                                         if ((bits & ValueForReturnMASK) != 0) {
566                                                 codeStream.ireturn();
567                                                 falseLabel.place();
568                                                 codeStream.iconst_0();
569                                         } else {
570                                                 codeStream.goto_(endLabel = new Label(codeStream));
571                                                 codeStream.decrStackSize(1);
572                                                 falseLabel.place();
573                                                 codeStream.iconst_0();
574                                                 endLabel.place();
575                                         }
576                                 }
577                                 break;
578                         case LESS_EQUAL :
579                                 generateOptimizedLessThanOrEqual(
580                                         currentScope,
581                                         codeStream,
582                                         null,
583                                         (falseLabel = new Label(codeStream)),
584                                         valueRequired);
585                                 if (valueRequired) {
586                                         codeStream.iconst_1();
587                                         if ((bits & ValueForReturnMASK) != 0) {
588                                                 codeStream.ireturn();
589                                                 falseLabel.place();
590                                                 codeStream.iconst_0();
591                                         } else {
592                                                 codeStream.goto_(endLabel = new Label(codeStream));
593                                                 codeStream.decrStackSize(1);
594                                                 falseLabel.place();
595                                                 codeStream.iconst_0();
596                                                 endLabel.place();
597                                         }
598                                 }
599                 }
600                 if (valueRequired) {
601                         codeStream.generateImplicitConversion(implicitConversion);
602                 }
603                 codeStream.recordPositionsFrom(pc, this.sourceStart);
604         }
605
606         /**
607          * Boolean operator code generation
608          *      Optimized operations are: <, <=, >, >=, &, |, ^
609          */
610         public void generateOptimizedBoolean(
611                 BlockScope currentScope,
612                 CodeStream codeStream,
613                 Label trueLabel,
614                 Label falseLabel,
615                 boolean valueRequired) {
616
617                 if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
618                         super.generateOptimizedBoolean(
619                                 currentScope,
620                                 codeStream,
621                                 trueLabel,
622                                 falseLabel,
623                                 valueRequired);
624                         return;
625                 }
626                 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
627                         case LESS :
628                                 generateOptimizedLessThan(
629                                         currentScope,
630                                         codeStream,
631                                         trueLabel,
632                                         falseLabel,
633                                         valueRequired);
634                                 return;
635                         case LESS_EQUAL :
636                                 generateOptimizedLessThanOrEqual(
637                                         currentScope,
638                                         codeStream,
639                                         trueLabel,
640                                         falseLabel,
641                                         valueRequired);
642                                 return;
643                         case GREATER :
644                                 generateOptimizedGreaterThan(
645                                         currentScope,
646                                         codeStream,
647                                         trueLabel,
648                                         falseLabel,
649                                         valueRequired);
650                                 return;
651                         case GREATER_EQUAL :
652                                 generateOptimizedGreaterThanOrEqual(
653                                         currentScope,
654                                         codeStream,
655                                         trueLabel,
656                                         falseLabel,
657                                         valueRequired);
658                                 return;
659                         case AND :
660                                 generateOptimizedLogicalAnd(
661                                         currentScope,
662                                         codeStream,
663                                         trueLabel,
664                                         falseLabel,
665                                         valueRequired);
666                                 return;
667                         case OR :
668                                 generateOptimizedLogicalOr(
669                                         currentScope,
670                                         codeStream,
671                                         trueLabel,
672                                         falseLabel,
673                                         valueRequired);
674                                 return;
675                         case XOR :
676                                 generateOptimizedLogicalXor(
677                                         currentScope,
678                                         codeStream,
679                                         trueLabel,
680                                         falseLabel,
681                                         valueRequired);
682                                 return;
683                 }
684                 super.generateOptimizedBoolean(
685                         currentScope,
686                         codeStream,
687                         trueLabel,
688                         falseLabel,
689                         valueRequired);
690         }
691
692         /**
693          * Boolean generation for >
694          */
695         public void generateOptimizedGreaterThan(
696                 BlockScope currentScope,
697                 CodeStream codeStream,
698                 Label trueLabel,
699                 Label falseLabel,
700                 boolean valueRequired) {
701
702                 int promotedTypeID = left.implicitConversion >> 4;
703                 // both sides got promoted in the same way
704                 if (promotedTypeID == T_int) {
705                         // 0 > x
706                         if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
707                                 right.generateCode(currentScope, codeStream, valueRequired);
708                                 if (valueRequired) {
709                                         if (falseLabel == null) {
710                                                 if (trueLabel != null) {
711                                                         // implicitly falling through the FALSE case
712                                                         codeStream.iflt(trueLabel);
713                                                 }
714                                         } else {
715                                                 if (trueLabel == null) {
716                                                         // implicitly falling through the TRUE case
717                                                         codeStream.ifge(falseLabel);
718                                                 } else {
719                                                         // no implicit fall through TRUE/FALSE --> should never occur
720                                                 }
721                                         }
722                                 }
723                                 // reposition the endPC
724                                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
725                                 return;
726                         }
727                         // x > 0
728                         if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
729                                 left.generateCode(currentScope, codeStream, valueRequired);
730                                 if (valueRequired) {
731                                         if (falseLabel == null) {
732                                                 if (trueLabel != null) {
733                                                         // implicitly falling through the FALSE case
734                                                         codeStream.ifgt(trueLabel);
735                                                 }
736                                         } else {
737                                                 if (trueLabel == null) {
738                                                         // implicitly falling through the TRUE case
739                                                         codeStream.ifle(falseLabel);
740                                                 } else {
741                                                         // no implicit fall through TRUE/FALSE --> should never occur
742                                                 }
743                                         }
744                                 }
745                                 // reposition the endPC
746                                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
747                                 return;
748                         }
749                 }
750                 // default comparison
751                 left.generateCode(currentScope, codeStream, valueRequired);
752                 right.generateCode(currentScope, codeStream, valueRequired);
753                 if (valueRequired) {
754                         if (falseLabel == null) {
755                                 if (trueLabel != null) {
756                                         // implicit falling through the FALSE case
757                                         switch (promotedTypeID) {
758                                                 case T_int :
759                                                         codeStream.if_icmpgt(trueLabel);
760                                                         break;
761                                                 case T_float :
762                                                         codeStream.fcmpl();
763                                                         codeStream.ifgt(trueLabel);
764                                                         break;
765                                                 case T_long :
766                                                         codeStream.lcmp();
767                                                         codeStream.ifgt(trueLabel);
768                                                         break;
769                                                 case T_double :
770                                                         codeStream.dcmpl();
771                                                         codeStream.ifgt(trueLabel);
772                                         }
773                                         // reposition the endPC
774                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
775                                         return;
776                                 }
777                         } else {
778                                 if (trueLabel == null) {
779                                         // implicit falling through the TRUE case
780                                         switch (promotedTypeID) {
781                                                 case T_int :
782                                                         codeStream.if_icmple(falseLabel);
783                                                         break;
784                                                 case T_float :
785                                                         codeStream.fcmpl();
786                                                         codeStream.ifle(falseLabel);
787                                                         break;
788                                                 case T_long :
789                                                         codeStream.lcmp();
790                                                         codeStream.ifle(falseLabel);
791                                                         break;
792                                                 case T_double :
793                                                         codeStream.dcmpl();
794                                                         codeStream.ifle(falseLabel);
795                                         }
796                                         // reposition the endPC
797                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
798                                         return;
799                                 } else {
800                                         // no implicit fall through TRUE/FALSE --> should never occur
801                                 }
802                         }
803                 }
804         }
805
806         /**
807          * Boolean generation for >=
808          */
809         public void generateOptimizedGreaterThanOrEqual(
810                 BlockScope currentScope,
811                 CodeStream codeStream,
812                 Label trueLabel,
813                 Label falseLabel,
814                 boolean valueRequired) {
815
816                 int promotedTypeID = left.implicitConversion >> 4;
817                 // both sides got promoted in the same way
818                 if (promotedTypeID == T_int) {
819                         // 0 >= x
820                         if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
821                                 right.generateCode(currentScope, codeStream, valueRequired);
822                                 if (valueRequired) {
823                                         if (falseLabel == null) {
824                                                 if (trueLabel != null) {
825                                                         // implicitly falling through the FALSE case
826                                                         codeStream.ifle(trueLabel);
827                                                 }
828                                         } else {
829                                                 if (trueLabel == null) {
830                                                         // implicitly falling through the TRUE case
831                                                         codeStream.ifgt(falseLabel);
832                                                 } else {
833                                                         // no implicit fall through TRUE/FALSE --> should never occur
834                                                 }
835                                         }
836                                 }
837                                 // reposition the endPC
838                                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
839                                 return;
840                         }
841                         // x >= 0
842                         if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
843                                 left.generateCode(currentScope, codeStream, valueRequired);
844                                 if (valueRequired) {
845                                         if (falseLabel == null) {
846                                                 if (trueLabel != null) {
847                                                         // implicitly falling through the FALSE case
848                                                         codeStream.ifge(trueLabel);
849                                                 }
850                                         } else {
851                                                 if (trueLabel == null) {
852                                                         // implicitly falling through the TRUE case
853                                                         codeStream.iflt(falseLabel);
854                                                 } else {
855                                                         // no implicit fall through TRUE/FALSE --> should never occur
856                                                 }
857                                         }
858                                 }
859                                 // reposition the endPC
860                                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
861                                 return;
862                         }
863                 }
864                 // default comparison
865                 left.generateCode(currentScope, codeStream, valueRequired);
866                 right.generateCode(currentScope, codeStream, valueRequired);
867                 if (valueRequired) {
868                         if (falseLabel == null) {
869                                 if (trueLabel != null) {
870                                         // implicit falling through the FALSE case
871                                         switch (promotedTypeID) {
872                                                 case T_int :
873                                                         codeStream.if_icmpge(trueLabel);
874                                                         break;
875                                                 case T_float :
876                                                         codeStream.fcmpl();
877                                                         codeStream.ifge(trueLabel);
878                                                         break;
879                                                 case T_long :
880                                                         codeStream.lcmp();
881                                                         codeStream.ifge(trueLabel);
882                                                         break;
883                                                 case T_double :
884                                                         codeStream.dcmpl();
885                                                         codeStream.ifge(trueLabel);
886                                         }
887                                         // reposition the endPC
888                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
889                                         return;
890                                 }
891                         } else {
892                                 if (trueLabel == null) {
893                                         // implicit falling through the TRUE case
894                                         switch (promotedTypeID) {
895                                                 case T_int :
896                                                         codeStream.if_icmplt(falseLabel);
897                                                         break;
898                                                 case T_float :
899                                                         codeStream.fcmpl();
900                                                         codeStream.iflt(falseLabel);
901                                                         break;
902                                                 case T_long :
903                                                         codeStream.lcmp();
904                                                         codeStream.iflt(falseLabel);
905                                                         break;
906                                                 case T_double :
907                                                         codeStream.dcmpl();
908                                                         codeStream.iflt(falseLabel);
909                                         }
910                                         // reposition the endPC
911                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
912                                         return;
913                                 } else {
914                                         // no implicit fall through TRUE/FALSE --> should never occur
915                                 }
916                         }
917                 }
918         }
919
920         /**
921          * Boolean generation for <
922          */
923         public void generateOptimizedLessThan(
924                 BlockScope currentScope,
925                 CodeStream codeStream,
926                 Label trueLabel,
927                 Label falseLabel,
928                 boolean valueRequired) {
929
930                 int promotedTypeID = left.implicitConversion >> 4;
931                 // both sides got promoted in the same way
932                 if (promotedTypeID == T_int) {
933                         // 0 < x
934                         if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
935                                 right.generateCode(currentScope, codeStream, valueRequired);
936                                 if (valueRequired) {
937                                         if (falseLabel == null) {
938                                                 if (trueLabel != null) {
939                                                         // implicitly falling through the FALSE case
940                                                         codeStream.ifgt(trueLabel);
941                                                 }
942                                         } else {
943                                                 if (trueLabel == null) {
944                                                         // implicitly falling through the TRUE case
945                                                         codeStream.ifle(falseLabel);
946                                                 } else {
947                                                         // no implicit fall through TRUE/FALSE --> should never occur
948                                                 }
949                                         }
950                                 }
951                                 codeStream.updateLastRecordedEndPC(codeStream.position);
952                                 return;
953                         }
954                         // x < 0
955                         if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
956                                 left.generateCode(currentScope, codeStream, valueRequired);
957                                 if (valueRequired) {
958                                         if (falseLabel == null) {
959                                                 if (trueLabel != null) {
960                                                         // implicitly falling through the FALSE case
961                                                         codeStream.iflt(trueLabel);
962                                                 }
963                                         } else {
964                                                 if (trueLabel == null) {
965                                                         // implicitly falling through the TRUE case
966                                                         codeStream.ifge(falseLabel);
967                                                 } else {
968                                                         // no implicit fall through TRUE/FALSE --> should never occur
969                                                 }
970                                         }
971                                 }
972                                 codeStream.updateLastRecordedEndPC(codeStream.position);
973                                 return;
974                         }
975                 }
976                 // default comparison
977                 left.generateCode(currentScope, codeStream, valueRequired);
978                 right.generateCode(currentScope, codeStream, valueRequired);
979                 if (valueRequired) {
980                         if (falseLabel == null) {
981                                 if (trueLabel != null) {
982                                         // implicit falling through the FALSE case
983                                         switch (promotedTypeID) {
984                                                 case T_int :
985                                                         codeStream.if_icmplt(trueLabel);
986                                                         break;
987                                                 case T_float :
988                                                         codeStream.fcmpg();
989                                                         codeStream.iflt(trueLabel);
990                                                         break;
991                                                 case T_long :
992                                                         codeStream.lcmp();
993                                                         codeStream.iflt(trueLabel);
994                                                         break;
995                                                 case T_double :
996                                                         codeStream.dcmpg();
997                                                         codeStream.iflt(trueLabel);
998                                         }
999                                         codeStream.updateLastRecordedEndPC(codeStream.position);
1000                                         return;
1001                                 }
1002                         } else {
1003                                 if (trueLabel == null) {
1004                                         // implicit falling through the TRUE case
1005                                         switch (promotedTypeID) {
1006                                                 case T_int :
1007                                                         codeStream.if_icmpge(falseLabel);
1008                                                         break;
1009                                                 case T_float :
1010                                                         codeStream.fcmpg();
1011                                                         codeStream.ifge(falseLabel);
1012                                                         break;
1013                                                 case T_long :
1014                                                         codeStream.lcmp();
1015                                                         codeStream.ifge(falseLabel);
1016                                                         break;
1017                                                 case T_double :
1018                                                         codeStream.dcmpg();
1019                                                         codeStream.ifge(falseLabel);
1020                                         }
1021                                         codeStream.updateLastRecordedEndPC(codeStream.position);
1022                                         return;
1023                                 } else {
1024                                         // no implicit fall through TRUE/FALSE --> should never occur
1025                                 }
1026                         }
1027                 }
1028         }
1029         
1030         /**
1031          * Boolean generation for <=
1032          */
1033         public void generateOptimizedLessThanOrEqual(
1034                 BlockScope currentScope,
1035                 CodeStream codeStream,
1036                 Label trueLabel,
1037                 Label falseLabel,
1038                 boolean valueRequired) {
1039
1040                 int promotedTypeID = left.implicitConversion >> 4;
1041                 // both sides got promoted in the same way
1042                 if (promotedTypeID == T_int) {
1043                         // 0 <= x
1044                         if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
1045                                 right.generateCode(currentScope, codeStream, valueRequired);
1046                                 if (valueRequired) {
1047                                         if (falseLabel == null) {
1048                                                 if (trueLabel != null) {
1049                                                         // implicitly falling through the FALSE case
1050                                                         codeStream.ifge(trueLabel);
1051                                                 }
1052                                         } else {
1053                                                 if (trueLabel == null) {
1054                                                         // implicitly falling through the TRUE case
1055                                                         codeStream.iflt(falseLabel);
1056                                                 } else {
1057                                                         // no implicit fall through TRUE/FALSE --> should never occur
1058                                                 }
1059                                         }
1060                                 }
1061                                 // reposition the endPC
1062                                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1063                                 return;
1064                         }
1065                         // x <= 0
1066                         if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
1067                                 left.generateCode(currentScope, codeStream, valueRequired);
1068                                 if (valueRequired) {
1069                                         if (falseLabel == null) {
1070                                                 if (trueLabel != null) {
1071                                                         // implicitly falling through the FALSE case
1072                                                         codeStream.ifle(trueLabel);
1073                                                 }
1074                                         } else {
1075                                                 if (trueLabel == null) {
1076                                                         // implicitly falling through the TRUE case
1077                                                         codeStream.ifgt(falseLabel);
1078                                                 } else {
1079                                                         // no implicit fall through TRUE/FALSE --> should never occur
1080                                                 }
1081                                         }
1082                                 }
1083                                 // reposition the endPC
1084                                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1085                                 return;
1086                         }
1087                 }
1088                 // default comparison
1089                 left.generateCode(currentScope, codeStream, valueRequired);
1090                 right.generateCode(currentScope, codeStream, valueRequired);
1091                 if (valueRequired) {
1092                         if (falseLabel == null) {
1093                                 if (trueLabel != null) {
1094                                         // implicit falling through the FALSE case
1095                                         switch (promotedTypeID) {
1096                                                 case T_int :
1097                                                         codeStream.if_icmple(trueLabel);
1098                                                         break;
1099                                                 case T_float :
1100                                                         codeStream.fcmpg();
1101                                                         codeStream.ifle(trueLabel);
1102                                                         break;
1103                                                 case T_long :
1104                                                         codeStream.lcmp();
1105                                                         codeStream.ifle(trueLabel);
1106                                                         break;
1107                                                 case T_double :
1108                                                         codeStream.dcmpg();
1109                                                         codeStream.ifle(trueLabel);
1110                                         }
1111                                         // reposition the endPC
1112                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1113                                         return;
1114                                 }
1115                         } else {
1116                                 if (trueLabel == null) {
1117                                         // implicit falling through the TRUE case
1118                                         switch (promotedTypeID) {
1119                                                 case T_int :
1120                                                         codeStream.if_icmpgt(falseLabel);
1121                                                         break;
1122                                                 case T_float :
1123                                                         codeStream.fcmpg();
1124                                                         codeStream.ifgt(falseLabel);
1125                                                         break;
1126                                                 case T_long :
1127                                                         codeStream.lcmp();
1128                                                         codeStream.ifgt(falseLabel);
1129                                                         break;
1130                                                 case T_double :
1131                                                         codeStream.dcmpg();
1132                                                         codeStream.ifgt(falseLabel);
1133                                         }
1134                                         // reposition the endPC
1135                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1136                                         return;
1137                                 } else {
1138                                         // no implicit fall through TRUE/FALSE --> should never occur
1139                                 }
1140                         }
1141                 }
1142         }
1143         
1144         /**
1145          * Boolean generation for &
1146          */
1147         public void generateOptimizedLogicalAnd(
1148                 BlockScope currentScope,
1149                 CodeStream codeStream,
1150                 Label trueLabel,
1151                 Label falseLabel,
1152                 boolean valueRequired) {
1153                         
1154                 Constant condConst;
1155                 if ((left.implicitConversion & 0xF) == T_boolean) {
1156                         if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
1157                                 if (condConst.booleanValue() == true) {
1158                                         // <something equivalent to true> & x
1159                                         left.generateOptimizedBoolean(
1160                                                 currentScope,
1161                                                 codeStream,
1162                                                 trueLabel,
1163                                                 falseLabel,
1164                                                 false);
1165                                         if ((bits & OnlyValueRequiredMASK) != 0) {
1166                                                 right.generateCode(currentScope, codeStream, valueRequired);
1167                                         } else {
1168                                                 right.generateOptimizedBoolean(
1169                                                         currentScope,
1170                                                         codeStream,
1171                                                         trueLabel,
1172                                                         falseLabel,
1173                                                         valueRequired);
1174                                         }
1175                                 } else {
1176                                         // <something equivalent to false> & x
1177                                         left.generateOptimizedBoolean(
1178                                                 currentScope,
1179                                                 codeStream,
1180                                                 trueLabel,
1181                                                 falseLabel,
1182                                                 false);
1183                                         Label internalTrueLabel = new Label(codeStream);
1184                                         right.generateOptimizedBoolean(
1185                                                 currentScope,
1186                                                 codeStream,
1187                                                 trueLabel,
1188                                                 falseLabel,
1189                                                 false);
1190                                         internalTrueLabel.place();
1191                                         if (valueRequired) {
1192                                                 if ((bits & OnlyValueRequiredMASK) != 0) {
1193                                                         codeStream.iconst_0();
1194                                                 } else {
1195                                                         if (falseLabel != null) {
1196                                                                 // implicit falling through the TRUE case
1197                                                                 codeStream.goto_(falseLabel);
1198                                                         }
1199                                                 }
1200                                         }
1201                                         // reposition the endPC
1202                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1203                                 }
1204                                 return;
1205                         }
1206                         if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
1207                                 if (condConst.booleanValue() == true) {
1208                                         // x & <something equivalent to true>
1209                                         if ((bits & OnlyValueRequiredMASK) != 0) {
1210                                                 left.generateCode(currentScope, codeStream, valueRequired);
1211                                         } else {
1212                                                 left.generateOptimizedBoolean(
1213                                                         currentScope,
1214                                                         codeStream,
1215                                                         trueLabel,
1216                                                         falseLabel,
1217                                                         valueRequired);
1218                                         }
1219                                         right.generateOptimizedBoolean(
1220                                                 currentScope,
1221                                                 codeStream,
1222                                                 trueLabel,
1223                                                 falseLabel,
1224                                                 false);
1225                                 } else {
1226                                         // x & <something equivalent to false>
1227                                         Label internalTrueLabel = new Label(codeStream);
1228                                         left.generateOptimizedBoolean(
1229                                                 currentScope,
1230                                                 codeStream,
1231                                                 internalTrueLabel,
1232                                                 falseLabel,
1233                                                 false);
1234                                         internalTrueLabel.place();
1235                                         right.generateOptimizedBoolean(
1236                                                 currentScope,
1237                                                 codeStream,
1238                                                 trueLabel,
1239                                                 falseLabel,
1240                                                 false);
1241                                         if (valueRequired) {
1242                                                 if ((bits & OnlyValueRequiredMASK) != 0) {
1243                                                         codeStream.iconst_0();
1244                                                 } else {
1245                                                         if (falseLabel != null) {
1246                                                                 // implicit falling through the TRUE case
1247                                                                 codeStream.goto_(falseLabel);
1248                                                         }
1249                                                 }
1250                                         }
1251                                         // reposition the endPC
1252                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1253                                 }
1254                                 return;
1255                         }
1256                 }
1257                 // default case
1258                 left.generateCode(currentScope, codeStream, valueRequired);
1259                 right.generateCode(currentScope, codeStream, valueRequired);
1260                 if (valueRequired) {
1261                         codeStream.iand();
1262                         if ((bits & OnlyValueRequiredMASK) == 0) {
1263                                 if (falseLabel == null) {
1264                                         if (trueLabel != null) {
1265                                                 // implicit falling through the FALSE case
1266                                                 codeStream.ifne(trueLabel);
1267                                         }
1268                                 } else {
1269                                         // implicit falling through the TRUE case
1270                                         if (trueLabel == null) {
1271                                                 codeStream.ifeq(falseLabel);
1272                                         } else {
1273                                                 // no implicit fall through TRUE/FALSE --> should never occur
1274                                         }
1275                                 }
1276                         }
1277                 }
1278                 // reposition the endPC
1279                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1280         }
1281         
1282         /**
1283          * Boolean generation for |
1284          */
1285         public void generateOptimizedLogicalOr(
1286                 BlockScope currentScope,
1287                 CodeStream codeStream,
1288                 Label trueLabel,
1289                 Label falseLabel,
1290                 boolean valueRequired) {
1291                         
1292                 Constant condConst;
1293                 if ((left.implicitConversion & 0xF) == T_boolean) {
1294                         if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
1295                                 if (condConst.booleanValue() == true) {
1296                                         // <something equivalent to true> | x
1297                                         left.generateOptimizedBoolean(
1298                                                 currentScope,
1299                                                 codeStream,
1300                                                 trueLabel,
1301                                                 falseLabel,
1302                                                 false);
1303                                         Label internalFalseLabel = new Label(codeStream);
1304                                         right.generateOptimizedBoolean(
1305                                                 currentScope,
1306                                                 codeStream,
1307                                                 trueLabel,
1308                                                 internalFalseLabel,
1309                                                 false);
1310                                         internalFalseLabel.place();
1311                                         if (valueRequired) {
1312                                                 if ((bits & OnlyValueRequiredMASK) != 0) {
1313                                                         codeStream.iconst_1();
1314                                                 } else {
1315                                                         if (trueLabel != null) {
1316                                                                 codeStream.goto_(trueLabel);
1317                                                         }
1318                                                 }
1319                                         }
1320                                         // reposition the endPC
1321                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1322                                 } else {
1323                                         // <something equivalent to false> | x
1324                                         left.generateOptimizedBoolean(
1325                                                 currentScope,
1326                                                 codeStream,
1327                                                 trueLabel,
1328                                                 falseLabel,
1329                                                 false);
1330                                         if ((bits & OnlyValueRequiredMASK) != 0) {
1331                                                 right.generateCode(currentScope, codeStream, valueRequired);
1332                                         } else {
1333                                                 right.generateOptimizedBoolean(
1334                                                         currentScope,
1335                                                         codeStream,
1336                                                         trueLabel,
1337                                                         falseLabel,
1338                                                         valueRequired);
1339                                         }
1340                                 }
1341                                 return;
1342                         }
1343                         if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
1344                                 if (condConst.booleanValue() == true) {
1345                                         // x | <something equivalent to true>
1346                                         Label internalFalseLabel = new Label(codeStream);
1347                                         left.generateOptimizedBoolean(
1348                                                 currentScope,
1349                                                 codeStream,
1350                                                 trueLabel,
1351                                                 internalFalseLabel,
1352                                                 false);
1353                                         internalFalseLabel.place();
1354                                         right.generateOptimizedBoolean(
1355                                                 currentScope,
1356                                                 codeStream,
1357                                                 trueLabel,
1358                                                 falseLabel,
1359                                                 false);
1360                                         if (valueRequired) {
1361                                                 if ((bits & OnlyValueRequiredMASK) != 0) {
1362                                                         codeStream.iconst_1();
1363                                                 } else {
1364                                                         if (trueLabel != null) {
1365                                                                 codeStream.goto_(trueLabel);
1366                                                         }
1367                                                 }
1368                                         }
1369                                         // reposition the endPC
1370                                         codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1371                                 } else {
1372                                         // x | <something equivalent to false>
1373                                         if ((bits & OnlyValueRequiredMASK) != 0) {
1374                                                 left.generateCode(currentScope, codeStream, valueRequired);
1375                                         } else {
1376                                                 left.generateOptimizedBoolean(
1377                                                         currentScope,
1378                                                         codeStream,
1379                                                         trueLabel,
1380                                                         falseLabel,
1381                                                         valueRequired);
1382                                         }
1383                                         right.generateOptimizedBoolean(
1384                                                 currentScope,
1385                                                 codeStream,
1386                                                 trueLabel,
1387                                                 falseLabel,
1388                                                 false);
1389                                 }
1390                                 return;
1391                         }
1392                 }
1393                 // default case
1394                 left.generateCode(currentScope, codeStream, valueRequired);
1395                 right.generateCode(currentScope, codeStream, valueRequired);
1396                 if (valueRequired) {
1397                         codeStream.ior();
1398                         if ((bits & OnlyValueRequiredMASK) == 0) {
1399                                 if (falseLabel == null) {
1400                                         if (trueLabel != null) {
1401                                                 // implicit falling through the FALSE case
1402                                                 codeStream.ifne(trueLabel);
1403                                         }
1404                                 } else {
1405                                         // implicit falling through the TRUE case
1406                                         if (trueLabel == null) {
1407                                                 codeStream.ifeq(falseLabel);
1408                                         } else {
1409                                                 // no implicit fall through TRUE/FALSE --> should never occur
1410                                         }
1411                                 }
1412                         }
1413                 }
1414                 // reposition the endPC
1415                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1416         }
1417         
1418         /**
1419          * Boolean generation for ^
1420          */
1421         public void generateOptimizedLogicalXor(
1422                 BlockScope currentScope,
1423                 CodeStream codeStream,
1424                 Label trueLabel,
1425                 Label falseLabel,
1426                 boolean valueRequired) {
1427                         
1428                 Constant condConst;
1429                 if ((left.implicitConversion & 0xF) == T_boolean) {
1430                         if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
1431                                 if (condConst.booleanValue() == true) {
1432                                         // <something equivalent to true> ^ x
1433                                         left.generateOptimizedBoolean(
1434                                                 currentScope,
1435                                                 codeStream,
1436                                                 trueLabel,
1437                                                 falseLabel,
1438                                                 false);
1439                                         right.generateOptimizedBoolean(
1440                                                 currentScope,
1441                                                 codeStream,
1442                                                 falseLabel,
1443                                                 trueLabel,
1444                                                 valueRequired);
1445                                 } else {
1446                                         // <something equivalent to false> ^ x
1447                                         left.generateOptimizedBoolean(
1448                                                 currentScope,
1449                                                 codeStream,
1450                                                 trueLabel,
1451                                                 falseLabel,
1452                                                 false);
1453                                         if ((bits & OnlyValueRequiredMASK) != 0) {
1454                                                 right.generateCode(currentScope, codeStream, valueRequired);
1455                                         } else {
1456                                                 right.generateOptimizedBoolean(
1457                                                         currentScope,
1458                                                         codeStream,
1459                                                         trueLabel,
1460                                                         falseLabel,
1461                                                         valueRequired);
1462                                         }
1463                                 }
1464                                 return;
1465                         }
1466                         if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
1467                                 if (condConst.booleanValue() == true) {
1468                                         // x ^ <something equivalent to true>
1469                                         left.generateOptimizedBoolean(
1470                                                 currentScope,
1471                                                 codeStream,
1472                                                 falseLabel,
1473                                                 trueLabel,
1474                                                 valueRequired);
1475                                         right.generateOptimizedBoolean(
1476                                                 currentScope,
1477                                                 codeStream,
1478                                                 trueLabel,
1479                                                 falseLabel,
1480                                                 false);
1481                                 } else {
1482                                         // x ^ <something equivalent to false>
1483                                         if ((bits & OnlyValueRequiredMASK) != 0) {
1484                                                 left.generateCode(currentScope, codeStream, valueRequired);
1485                                         } else {
1486                                                 left.generateOptimizedBoolean(
1487                                                         currentScope,
1488                                                         codeStream,
1489                                                         trueLabel,
1490                                                         falseLabel,
1491                                                         valueRequired);
1492                                         }
1493                                         right.generateOptimizedBoolean(
1494                                                 currentScope,
1495                                                 codeStream,
1496                                                 trueLabel,
1497                                                 falseLabel,
1498                                                 false);
1499                                 }
1500                                 return;
1501                         }
1502                 }
1503                 // default case
1504                 left.generateCode(currentScope, codeStream, valueRequired);
1505                 right.generateCode(currentScope, codeStream, valueRequired);
1506                 if (valueRequired) {
1507                         codeStream.ixor();
1508                         if ((bits & OnlyValueRequiredMASK) == 0) {
1509                                 if (falseLabel == null) {
1510                                         if (trueLabel != null) {
1511                                                 // implicit falling through the FALSE case
1512                                                 codeStream.ifne(trueLabel);
1513                                         }
1514                                 } else {
1515                                         // implicit falling through the TRUE case
1516                                         if (trueLabel == null) {
1517                                                 codeStream.ifeq(falseLabel);
1518                                         } else {
1519                                                 // no implicit fall through TRUE/FALSE --> should never occur
1520                                         }
1521                                 }
1522                         }
1523                 }
1524                 // reposition the endPC
1525                 codeStream.updateLastRecordedEndPC(codeStream.position);                                        
1526         }
1527         
1528         public void generateOptimizedStringBuffer(
1529                 BlockScope blockScope,
1530                 CodeStream codeStream,
1531                 int typeID) {
1532                         
1533                 /* In the case trying to make a string concatenation, there is no need to create a new
1534                  * string buffer, thus use a lower-level API for code generation involving only the
1535                  * appending of arguments to the existing StringBuffer
1536                  */
1537
1538                 if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
1539                         && ((bits & ReturnTypeIDMASK) == T_String)) {
1540                         if (constant != NotAConstant) {
1541                                 codeStream.generateConstant(constant, implicitConversion);
1542                                 codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF);
1543                         } else {
1544                                 int pc = codeStream.position;
1545                                 left.generateOptimizedStringBuffer(
1546                                         blockScope,
1547                                         codeStream,
1548                                         left.implicitConversion & 0xF);
1549                                 codeStream.recordPositionsFrom(pc, left.sourceStart);
1550                                 pc = codeStream.position;
1551                                 right.generateOptimizedStringBuffer(
1552                                         blockScope,
1553                                         codeStream,
1554                                         right.implicitConversion & 0xF);
1555                                 codeStream.recordPositionsFrom(pc, right.sourceStart);
1556                         }
1557                 } else {
1558                         super.generateOptimizedStringBuffer(blockScope, codeStream, typeID);
1559                 }
1560         }
1561         
1562         public void generateOptimizedStringBufferCreation(
1563                 BlockScope blockScope,
1564                 CodeStream codeStream,
1565                 int typeID) {
1566                         
1567                 /* In the case trying to make a string concatenation, there is no need to create a new
1568                  * string buffer, thus use a lower-level API for code generation involving only the 
1569                  * appending of arguments to the existing StringBuffer
1570                  */
1571
1572                 if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
1573                         && ((bits & ReturnTypeIDMASK) == T_String)) {
1574                         if (constant != NotAConstant) {
1575                                 codeStream.newStringBuffer(); // new: java.lang.StringBuffer
1576                                 codeStream.dup();
1577                                 codeStream.ldc(constant.stringValue());
1578                                 codeStream.invokeStringBufferStringConstructor();
1579                                 // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
1580                         } else {
1581                                 int pc = codeStream.position;
1582                                 left.generateOptimizedStringBufferCreation(
1583                                         blockScope,
1584                                         codeStream,
1585                                         left.implicitConversion & 0xF);
1586                                 codeStream.recordPositionsFrom(pc, left.sourceStart);
1587                                 pc = codeStream.position;
1588                                 right.generateOptimizedStringBuffer(
1589                                         blockScope,
1590                                         codeStream,
1591                                         right.implicitConversion & 0xF);
1592                                 codeStream.recordPositionsFrom(pc, right.sourceStart);
1593                         }
1594                 } else {
1595                         super.generateOptimizedStringBufferCreation(blockScope, codeStream, typeID);
1596                 }
1597         }
1598         
1599         public boolean isCompactableOperation() {
1600                 
1601                 return true;
1602         }
1603         
1604         public void optimizedBooleanConstant(int leftId, int operator, int rightId) {
1605
1606                 switch (operator) {
1607                         case AND :
1608                                 if ((leftId != T_boolean) || (rightId != T_boolean))
1609                                         return;
1610                         case AND_AND :
1611                                 Constant cst;
1612                                 if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
1613                                         if (cst.booleanValue() == false) { // left is equivalent to false
1614                                                 optimizedBooleanConstant = cst; // constant(false)
1615                                                 return;
1616                                         } else { //left is equivalent to true
1617                                                 if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1618                                                         optimizedBooleanConstant = cst;
1619                                                         // the conditional result is equivalent to the right conditional value
1620                                                 }
1621                                                 return;
1622                                         }
1623                                 }
1624                                 if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1625                                         if (cst.booleanValue() == false) { // right is equivalent to false
1626                                                 optimizedBooleanConstant = cst; // constant(false)
1627                                         }
1628                                 }
1629                                 return;
1630                         case OR :
1631                                 if ((leftId != T_boolean) || (rightId != T_boolean))
1632                                         return;
1633                         case OR_OR :
1634                                 if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
1635                                         if (cst.booleanValue() == true) { // left is equivalent to true
1636                                                 optimizedBooleanConstant = cst; // constant(true)
1637                                                 return;
1638                                         } else { //left is equivalent to false
1639                                                 if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1640                                                         optimizedBooleanConstant = cst;
1641                                                 }
1642                                                 return;
1643                                         }
1644                                 }
1645                                 if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
1646                                         if (cst.booleanValue() == true) { // right is equivalent to true
1647                                                 optimizedBooleanConstant = cst; // constant(true)
1648                                         }
1649                                 }
1650                 }
1651         }
1652
1653         public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
1654
1655                 left.printExpression(indent, output).append(' ').append(operatorToString()).append(' ');
1656                 return right.printExpression(0, output);
1657         }
1658                 
1659         public TypeBinding resolveType(BlockScope scope) {
1660
1661                 boolean leftIsCast, rightIsCast;
1662                 if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= IgnoreNeedForCastCheckMASK; // will check later on
1663                 TypeBinding leftType = left.resolveType(scope);
1664
1665                 if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= IgnoreNeedForCastCheckMASK; // will check later on
1666                 TypeBinding rightType = right.resolveType(scope);
1667
1668                 // use the id of the type to navigate into the table
1669                 if (leftType == null || rightType == null) {
1670                         constant = Constant.NotAConstant;
1671                         return null;
1672                 }
1673                 int leftTypeId = leftType.id;
1674                 int rightTypeId = rightType.id;
1675                 if (leftTypeId > 15
1676                         || rightTypeId > 15) { // must convert String + Object || Object + String
1677                         if (leftTypeId == T_String) {
1678                                 rightTypeId = T_Object;
1679                         } else if (rightTypeId == T_String) {
1680                                 leftTypeId = T_Object;
1681                         } else {
1682                                 constant = Constant.NotAConstant;
1683                                 scope.problemReporter().invalidOperator(this, leftType, rightType);
1684                                 return null;
1685                         }
1686                 }
1687                 if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
1688                         if (leftTypeId == T_String
1689                                         && rightType.isArrayType()
1690                                         && ((ArrayBinding) rightType).elementsType(scope) == CharBinding) {
1691                                 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(right);
1692                                         } else if (rightTypeId == T_String
1693                                                         && leftType.isArrayType()
1694                                                         && ((ArrayBinding) leftType).elementsType(scope) == CharBinding) {
1695                                 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(left);
1696                         }
1697                 }
1698
1699                 // the code is an int
1700                 // (cast)  left   Op (cast)  right --> result
1701                 //  0000   0000       0000   0000      0000
1702                 //  <<16   <<12       <<8    <<4       <<0
1703
1704                 // Don't test for result = 0. If it is zero, some more work is done.
1705                 // On the one hand when it is not zero (correct code) we avoid doing the test   
1706                 int operator = (bits & OperatorMASK) >> OperatorSHIFT;
1707                 int operatorSignature = OperatorSignatures[operator][(leftTypeId << 4) + rightTypeId];
1708                 left.implicitConversion = operatorSignature >>> 12;
1709                 right.implicitConversion = (operatorSignature >>> 4) & 0x000FF;
1710
1711                 bits |= operatorSignature & 0xF;
1712                 switch (operatorSignature & 0xF) { // record the current ReturnTypeID
1713                         // only switch on possible result type.....
1714                         case T_boolean :
1715                                 this.resolvedType = BooleanBinding;
1716                                 break;
1717                         case T_byte :
1718                                 this.resolvedType = ByteBinding;
1719                                 break;
1720                         case T_char :
1721                                 this.resolvedType = CharBinding;
1722                                 break;
1723                         case T_double :
1724                                 this.resolvedType = DoubleBinding;
1725                                 break;
1726                         case T_float :
1727                                 this.resolvedType = FloatBinding;
1728                                 break;
1729                         case T_int :
1730                                 this.resolvedType = IntBinding;
1731                                 break;
1732                         case T_long :
1733                                 this.resolvedType = LongBinding;
1734                                 break;
1735                         case T_String :
1736                                 this.resolvedType = scope.getJavaLangString();
1737                                 break;
1738                         default : //error........
1739                                 constant = Constant.NotAConstant;
1740                                 scope.problemReporter().invalidOperator(this, leftType, rightType);
1741                                 return null;
1742                 }
1743
1744                 // check need for operand cast
1745                 if (leftIsCast || rightIsCast) {
1746                         CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, left, leftTypeId, leftIsCast, right, rightTypeId, rightIsCast);
1747                 }
1748                 // compute the constant when valid
1749                 computeConstant(scope, leftTypeId, rightTypeId);
1750                 return this.resolvedType;
1751         }
1752
1753         public void traverse(ASTVisitor visitor, BlockScope scope) {
1754                 
1755                 if (visitor.visit(this, scope)) {
1756                         left.traverse(visitor, scope);
1757                         right.traverse(visitor, scope);
1758                 }
1759                 visitor.endVisit(this, scope);
1760         }
1761 }