1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.impl.*;
15 import net.sourceforge.phpdt.internal.compiler.codegen.*;
16 import net.sourceforge.phpdt.internal.compiler.flow.*;
17 import net.sourceforge.phpdt.internal.compiler.lookup.*;
19 public class BinaryExpression extends OperatorExpression {
21 public Expression left, right;
22 public Constant optimizedBooleanConstant;
24 public BinaryExpression(Expression left, Expression right, int operator) {
28 this.bits |= operator << OperatorSHIFT; // encode operator
29 this.sourceStart = left.sourceStart;
30 this.sourceEnd = right.sourceEnd;
33 public FlowInfo analyseCode(
34 BlockScope currentScope,
35 FlowContext flowContext,
42 left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
43 .unconditionalInits();
46 public void computeConstant(BlockScope scope, int leftId, int rightId) {
48 //compute the constant when valid
49 if ((left.constant != Constant.NotAConstant)
50 && (right.constant != Constant.NotAConstant)) {
53 Constant.computeConstantOperation(
56 (bits & OperatorMASK) >> OperatorSHIFT,
59 } catch (ArithmeticException e) {
60 constant = Constant.NotAConstant;
61 // 1.2 no longer throws an exception at compile-time
62 //scope.problemReporter().compileTimeConstantThrowsArithmeticException(this);
65 constant = Constant.NotAConstant;
66 //add some work for the boolean operators & |
67 optimizedBooleanConstant(
69 (bits & OperatorMASK) >> OperatorSHIFT,
74 public Constant conditionalConstant() {
76 return optimizedBooleanConstant == null ? constant : optimizedBooleanConstant;
80 * Code generation for a binary operation
82 public void generateCode(
83 BlockScope currentScope,
84 CodeStream codeStream,
85 boolean valueRequired) {
87 int pc = codeStream.position;
88 Label falseLabel, endLabel;
89 if (constant != Constant.NotAConstant) {
91 codeStream.generateConstant(constant, implicitConversion);
92 codeStream.recordPositionsFrom(pc, this.sourceStart);
95 bits |= OnlyValueRequiredMASK;
96 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
98 switch (bits & ReturnTypeIDMASK) {
100 codeStream.generateStringAppend(currentScope, left, right);
105 left.generateCode(currentScope, codeStream, valueRequired);
106 right.generateCode(currentScope, codeStream, valueRequired);
111 left.generateCode(currentScope, codeStream, valueRequired);
112 right.generateCode(currentScope, codeStream, valueRequired);
117 left.generateCode(currentScope, codeStream, valueRequired);
118 right.generateCode(currentScope, codeStream, valueRequired);
123 left.generateCode(currentScope, codeStream, valueRequired);
124 right.generateCode(currentScope, codeStream, valueRequired);
131 switch (bits & ReturnTypeIDMASK) {
133 left.generateCode(currentScope, codeStream, valueRequired);
134 right.generateCode(currentScope, codeStream, valueRequired);
139 left.generateCode(currentScope, codeStream, valueRequired);
140 right.generateCode(currentScope, codeStream, valueRequired);
145 left.generateCode(currentScope, codeStream, valueRequired);
146 right.generateCode(currentScope, codeStream, valueRequired);
151 left.generateCode(currentScope, codeStream, valueRequired);
152 right.generateCode(currentScope, codeStream, valueRequired);
159 switch (bits & ReturnTypeIDMASK) {
161 left.generateCode(currentScope, codeStream, valueRequired);
162 right.generateCode(currentScope, codeStream, valueRequired);
167 left.generateCode(currentScope, codeStream, valueRequired);
168 right.generateCode(currentScope, codeStream, valueRequired);
173 left.generateCode(currentScope, codeStream, valueRequired);
174 right.generateCode(currentScope, codeStream, valueRequired);
179 left.generateCode(currentScope, codeStream, valueRequired);
180 right.generateCode(currentScope, codeStream, valueRequired);
187 switch (bits & ReturnTypeIDMASK) {
189 left.generateCode(currentScope, codeStream, true);
190 right.generateCode(currentScope, codeStream, true);
196 left.generateCode(currentScope, codeStream, true);
197 right.generateCode(currentScope, codeStream, true);
203 left.generateCode(currentScope, codeStream, valueRequired);
204 right.generateCode(currentScope, codeStream, valueRequired);
209 left.generateCode(currentScope, codeStream, valueRequired);
210 right.generateCode(currentScope, codeStream, valueRequired);
217 switch (bits & ReturnTypeIDMASK) {
219 left.generateCode(currentScope, codeStream, true);
220 right.generateCode(currentScope, codeStream, true);
226 left.generateCode(currentScope, codeStream, true);
227 right.generateCode(currentScope, codeStream, true);
233 left.generateCode(currentScope, codeStream, valueRequired);
234 right.generateCode(currentScope, codeStream, valueRequired);
239 left.generateCode(currentScope, codeStream, valueRequired);
240 right.generateCode(currentScope, codeStream, valueRequired);
247 switch (bits & ReturnTypeIDMASK) {
250 if ((left.constant != Constant.NotAConstant)
251 && (left.constant.typeID() == T_int)
252 && (left.constant.intValue() == 0)) {
253 right.generateCode(currentScope, codeStream, false);
255 codeStream.iconst_0();
258 if ((right.constant != Constant.NotAConstant)
259 && (right.constant.typeID() == T_int)
260 && (right.constant.intValue() == 0)) {
261 left.generateCode(currentScope, codeStream, false);
263 codeStream.iconst_0();
265 left.generateCode(currentScope, codeStream, valueRequired);
266 right.generateCode(currentScope, codeStream, valueRequired);
274 if ((left.constant != Constant.NotAConstant)
275 && (left.constant.typeID() == T_long)
276 && (left.constant.longValue() == 0L)) {
277 right.generateCode(currentScope, codeStream, false);
279 codeStream.lconst_0();
282 if ((right.constant != Constant.NotAConstant)
283 && (right.constant.typeID() == T_long)
284 && (right.constant.longValue() == 0L)) {
285 left.generateCode(currentScope, codeStream, false);
287 codeStream.lconst_0();
289 left.generateCode(currentScope, codeStream, valueRequired);
290 right.generateCode(currentScope, codeStream, valueRequired);
296 case T_boolean : // logical and
297 generateOptimizedLogicalAnd(
301 (falseLabel = new Label(codeStream)),
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()) {
307 codeStream.iconst_1();
308 if ((bits & ValueForReturnMASK) != 0) {
309 codeStream.ireturn();
311 codeStream.iconst_0();
313 codeStream.goto_(endLabel = new Label(codeStream));
314 codeStream.decrStackSize(1);
316 codeStream.iconst_0();
326 switch (bits & ReturnTypeIDMASK) {
329 if ((left.constant != Constant.NotAConstant)
330 && (left.constant.typeID() == T_int)
331 && (left.constant.intValue() == 0)) {
332 right.generateCode(currentScope, codeStream, valueRequired);
335 if ((right.constant != Constant.NotAConstant)
336 && (right.constant.typeID() == T_int)
337 && (right.constant.intValue() == 0)) {
338 left.generateCode(currentScope, codeStream, valueRequired);
340 left.generateCode(currentScope, codeStream, valueRequired);
341 right.generateCode(currentScope, codeStream, valueRequired);
349 if ((left.constant != Constant.NotAConstant)
350 && (left.constant.typeID() == T_long)
351 && (left.constant.longValue() == 0L)) {
352 right.generateCode(currentScope, codeStream, valueRequired);
355 if ((right.constant != Constant.NotAConstant)
356 && (right.constant.typeID() == T_long)
357 && (right.constant.longValue() == 0L)) {
358 left.generateCode(currentScope, codeStream, valueRequired);
360 left.generateCode(currentScope, codeStream, valueRequired);
361 right.generateCode(currentScope, codeStream, valueRequired);
367 case T_boolean : // logical or
368 generateOptimizedLogicalOr(
372 (falseLabel = new Label(codeStream)),
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()) {
378 codeStream.iconst_1();
379 if ((bits & ValueForReturnMASK) != 0) {
380 codeStream.ireturn();
382 codeStream.iconst_0();
384 codeStream.goto_(endLabel = new Label(codeStream));
385 codeStream.decrStackSize(1);
387 codeStream.iconst_0();
397 switch (bits & ReturnTypeIDMASK) {
400 if ((left.constant != Constant.NotAConstant)
401 && (left.constant.typeID() == T_int)
402 && (left.constant.intValue() == 0)) {
403 right.generateCode(currentScope, codeStream, valueRequired);
406 if ((right.constant != Constant.NotAConstant)
407 && (right.constant.typeID() == T_int)
408 && (right.constant.intValue() == 0)) {
409 left.generateCode(currentScope, codeStream, valueRequired);
411 left.generateCode(currentScope, codeStream, valueRequired);
412 right.generateCode(currentScope, codeStream, valueRequired);
420 if ((left.constant != Constant.NotAConstant)
421 && (left.constant.typeID() == T_long)
422 && (left.constant.longValue() == 0L)) {
423 right.generateCode(currentScope, codeStream, valueRequired);
426 if ((right.constant != Constant.NotAConstant)
427 && (right.constant.typeID() == T_long)
428 && (right.constant.longValue() == 0L)) {
429 left.generateCode(currentScope, codeStream, valueRequired);
431 left.generateCode(currentScope, codeStream, valueRequired);
432 right.generateCode(currentScope, codeStream, valueRequired);
439 generateOptimizedLogicalXor(
443 (falseLabel = new Label(codeStream)),
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()) {
449 codeStream.iconst_1();
450 if ((bits & ValueForReturnMASK) != 0) {
451 codeStream.ireturn();
453 codeStream.iconst_0();
455 codeStream.goto_(endLabel = new Label(codeStream));
456 codeStream.decrStackSize(1);
458 codeStream.iconst_0();
468 switch (bits & ReturnTypeIDMASK) {
470 left.generateCode(currentScope, codeStream, valueRequired);
471 right.generateCode(currentScope, codeStream, valueRequired);
476 left.generateCode(currentScope, codeStream, valueRequired);
477 right.generateCode(currentScope, codeStream, valueRequired);
483 switch (bits & ReturnTypeIDMASK) {
485 left.generateCode(currentScope, codeStream, valueRequired);
486 right.generateCode(currentScope, codeStream, valueRequired);
491 left.generateCode(currentScope, codeStream, valueRequired);
492 right.generateCode(currentScope, codeStream, valueRequired);
497 case UNSIGNED_RIGHT_SHIFT :
498 switch (bits & ReturnTypeIDMASK) {
500 left.generateCode(currentScope, codeStream, valueRequired);
501 right.generateCode(currentScope, codeStream, valueRequired);
506 left.generateCode(currentScope, codeStream, valueRequired);
507 right.generateCode(currentScope, codeStream, valueRequired);
513 generateOptimizedGreaterThan(
517 (falseLabel = new Label(codeStream)),
520 codeStream.iconst_1();
521 if ((bits & ValueForReturnMASK) != 0) {
522 codeStream.ireturn();
524 codeStream.iconst_0();
526 codeStream.goto_(endLabel = new Label(codeStream));
527 codeStream.decrStackSize(1);
529 codeStream.iconst_0();
535 generateOptimizedGreaterThanOrEqual(
539 (falseLabel = new Label(codeStream)),
542 codeStream.iconst_1();
543 if ((bits & ValueForReturnMASK) != 0) {
544 codeStream.ireturn();
546 codeStream.iconst_0();
548 codeStream.goto_(endLabel = new Label(codeStream));
549 codeStream.decrStackSize(1);
551 codeStream.iconst_0();
557 generateOptimizedLessThan(
561 (falseLabel = new Label(codeStream)),
564 codeStream.iconst_1();
565 if ((bits & ValueForReturnMASK) != 0) {
566 codeStream.ireturn();
568 codeStream.iconst_0();
570 codeStream.goto_(endLabel = new Label(codeStream));
571 codeStream.decrStackSize(1);
573 codeStream.iconst_0();
579 generateOptimizedLessThanOrEqual(
583 (falseLabel = new Label(codeStream)),
586 codeStream.iconst_1();
587 if ((bits & ValueForReturnMASK) != 0) {
588 codeStream.ireturn();
590 codeStream.iconst_0();
592 codeStream.goto_(endLabel = new Label(codeStream));
593 codeStream.decrStackSize(1);
595 codeStream.iconst_0();
601 codeStream.generateImplicitConversion(implicitConversion);
603 codeStream.recordPositionsFrom(pc, this.sourceStart);
607 * Boolean operator code generation
608 * Optimized operations are: <, <=, >, >=, &, |, ^
610 public void generateOptimizedBoolean(
611 BlockScope currentScope,
612 CodeStream codeStream,
615 boolean valueRequired) {
617 if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
618 super.generateOptimizedBoolean(
626 switch ((bits & OperatorMASK) >> OperatorSHIFT) {
628 generateOptimizedLessThan(
636 generateOptimizedLessThanOrEqual(
644 generateOptimizedGreaterThan(
652 generateOptimizedGreaterThanOrEqual(
660 generateOptimizedLogicalAnd(
668 generateOptimizedLogicalOr(
676 generateOptimizedLogicalXor(
684 super.generateOptimizedBoolean(
693 * Boolean generation for >
695 public void generateOptimizedGreaterThan(
696 BlockScope currentScope,
697 CodeStream codeStream,
700 boolean valueRequired) {
702 int pc = codeStream.position;
703 int promotedTypeID = left.implicitConversion >> 4;
704 // both sides got promoted in the same way
705 if (promotedTypeID == T_int) {
707 if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
708 right.generateCode(currentScope, codeStream, valueRequired);
710 if (falseLabel == null) {
711 if (trueLabel != null) {
712 // implicitly falling through the FALSE case
713 codeStream.iflt(trueLabel);
716 if (trueLabel == null) {
717 // implicitly falling through the TRUE case
718 codeStream.ifge(falseLabel);
720 // no implicit fall through TRUE/FALSE --> should never occur
724 codeStream.recordPositionsFrom(pc, this.sourceStart);
728 if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
729 left.generateCode(currentScope, codeStream, valueRequired);
731 if (falseLabel == null) {
732 if (trueLabel != null) {
733 // implicitly falling through the FALSE case
734 codeStream.ifgt(trueLabel);
737 if (trueLabel == null) {
738 // implicitly falling through the TRUE case
739 codeStream.ifle(falseLabel);
741 // no implicit fall through TRUE/FALSE --> should never occur
745 codeStream.recordPositionsFrom(pc, this.sourceStart);
749 // default comparison
750 left.generateCode(currentScope, codeStream, valueRequired);
751 right.generateCode(currentScope, codeStream, valueRequired);
753 if (falseLabel == null) {
754 if (trueLabel != null) {
755 // implicit falling through the FALSE case
756 switch (promotedTypeID) {
758 codeStream.if_icmpgt(trueLabel);
762 codeStream.ifgt(trueLabel);
766 codeStream.ifgt(trueLabel);
770 codeStream.ifgt(trueLabel);
772 codeStream.recordPositionsFrom(pc, this.sourceStart);
776 if (trueLabel == null) {
777 // implicit falling through the TRUE case
778 switch (promotedTypeID) {
780 codeStream.if_icmple(falseLabel);
784 codeStream.ifle(falseLabel);
788 codeStream.ifle(falseLabel);
792 codeStream.ifle(falseLabel);
794 codeStream.recordPositionsFrom(pc, this.sourceStart);
797 // no implicit fall through TRUE/FALSE --> should never occur
804 * Boolean generation for >=
806 public void generateOptimizedGreaterThanOrEqual(
807 BlockScope currentScope,
808 CodeStream codeStream,
811 boolean valueRequired) {
813 int pc = codeStream.position;
814 int promotedTypeID = left.implicitConversion >> 4;
815 // both sides got promoted in the same way
816 if (promotedTypeID == T_int) {
818 if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
819 right.generateCode(currentScope, codeStream, valueRequired);
821 if (falseLabel == null) {
822 if (trueLabel != null) {
823 // implicitly falling through the FALSE case
824 codeStream.ifle(trueLabel);
827 if (trueLabel == null) {
828 // implicitly falling through the TRUE case
829 codeStream.ifgt(falseLabel);
831 // no implicit fall through TRUE/FALSE --> should never occur
835 codeStream.recordPositionsFrom(pc, this.sourceStart);
839 if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
840 left.generateCode(currentScope, codeStream, valueRequired);
842 if (falseLabel == null) {
843 if (trueLabel != null) {
844 // implicitly falling through the FALSE case
845 codeStream.ifge(trueLabel);
848 if (trueLabel == null) {
849 // implicitly falling through the TRUE case
850 codeStream.iflt(falseLabel);
852 // no implicit fall through TRUE/FALSE --> should never occur
856 codeStream.recordPositionsFrom(pc, this.sourceStart);
860 // default comparison
861 left.generateCode(currentScope, codeStream, valueRequired);
862 right.generateCode(currentScope, codeStream, valueRequired);
864 if (falseLabel == null) {
865 if (trueLabel != null) {
866 // implicit falling through the FALSE case
867 switch (promotedTypeID) {
869 codeStream.if_icmpge(trueLabel);
873 codeStream.ifge(trueLabel);
877 codeStream.ifge(trueLabel);
881 codeStream.ifge(trueLabel);
883 codeStream.recordPositionsFrom(pc, this.sourceStart);
887 if (trueLabel == null) {
888 // implicit falling through the TRUE case
889 switch (promotedTypeID) {
891 codeStream.if_icmplt(falseLabel);
895 codeStream.iflt(falseLabel);
899 codeStream.iflt(falseLabel);
903 codeStream.iflt(falseLabel);
905 codeStream.recordPositionsFrom(pc, this.sourceStart);
908 // no implicit fall through TRUE/FALSE --> should never occur
915 * Boolean generation for <
917 public void generateOptimizedLessThan(
918 BlockScope currentScope,
919 CodeStream codeStream,
922 boolean valueRequired) {
924 int pc = codeStream.position;
925 int promotedTypeID = left.implicitConversion >> 4;
926 // both sides got promoted in the same way
927 if (promotedTypeID == T_int) {
929 if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
930 right.generateCode(currentScope, codeStream, valueRequired);
932 if (falseLabel == null) {
933 if (trueLabel != null) {
934 // implicitly falling through the FALSE case
935 codeStream.ifgt(trueLabel);
938 if (trueLabel == null) {
939 // implicitly falling through the TRUE case
940 codeStream.ifle(falseLabel);
942 // no implicit fall through TRUE/FALSE --> should never occur
946 codeStream.recordPositionsFrom(pc, this.sourceStart);
950 if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
951 left.generateCode(currentScope, codeStream, valueRequired);
953 if (falseLabel == null) {
954 if (trueLabel != null) {
955 // implicitly falling through the FALSE case
956 codeStream.iflt(trueLabel);
959 if (trueLabel == null) {
960 // implicitly falling through the TRUE case
961 codeStream.ifge(falseLabel);
963 // no implicit fall through TRUE/FALSE --> should never occur
967 codeStream.recordPositionsFrom(pc, this.sourceStart);
971 // default comparison
972 left.generateCode(currentScope, codeStream, valueRequired);
973 right.generateCode(currentScope, codeStream, valueRequired);
975 if (falseLabel == null) {
976 if (trueLabel != null) {
977 // implicit falling through the FALSE case
978 switch (promotedTypeID) {
980 codeStream.if_icmplt(trueLabel);
984 codeStream.iflt(trueLabel);
988 codeStream.iflt(trueLabel);
992 codeStream.iflt(trueLabel);
994 codeStream.recordPositionsFrom(pc, this.sourceStart);
998 if (trueLabel == null) {
999 // implicit falling through the TRUE case
1000 switch (promotedTypeID) {
1002 codeStream.if_icmpge(falseLabel);
1006 codeStream.ifge(falseLabel);
1010 codeStream.ifge(falseLabel);
1014 codeStream.ifge(falseLabel);
1016 codeStream.recordPositionsFrom(pc, this.sourceStart);
1019 // no implicit fall through TRUE/FALSE --> should never occur
1026 * Boolean generation for <=
1028 public void generateOptimizedLessThanOrEqual(
1029 BlockScope currentScope,
1030 CodeStream codeStream,
1033 boolean valueRequired) {
1035 int pc = codeStream.position;
1036 int promotedTypeID = left.implicitConversion >> 4;
1037 // both sides got promoted in the same way
1038 if (promotedTypeID == T_int) {
1040 if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
1041 right.generateCode(currentScope, codeStream, valueRequired);
1042 if (valueRequired) {
1043 if (falseLabel == null) {
1044 if (trueLabel != null) {
1045 // implicitly falling through the FALSE case
1046 codeStream.ifge(trueLabel);
1049 if (trueLabel == null) {
1050 // implicitly falling through the TRUE case
1051 codeStream.iflt(falseLabel);
1053 // no implicit fall through TRUE/FALSE --> should never occur
1057 codeStream.recordPositionsFrom(pc, this.sourceStart);
1061 if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
1062 left.generateCode(currentScope, codeStream, valueRequired);
1063 if (valueRequired) {
1064 if (falseLabel == null) {
1065 if (trueLabel != null) {
1066 // implicitly falling through the FALSE case
1067 codeStream.ifle(trueLabel);
1070 if (trueLabel == null) {
1071 // implicitly falling through the TRUE case
1072 codeStream.ifgt(falseLabel);
1074 // no implicit fall through TRUE/FALSE --> should never occur
1078 codeStream.recordPositionsFrom(pc, this.sourceStart);
1082 // default comparison
1083 left.generateCode(currentScope, codeStream, valueRequired);
1084 right.generateCode(currentScope, codeStream, valueRequired);
1085 if (valueRequired) {
1086 if (falseLabel == null) {
1087 if (trueLabel != null) {
1088 // implicit falling through the FALSE case
1089 switch (promotedTypeID) {
1091 codeStream.if_icmple(trueLabel);
1095 codeStream.ifle(trueLabel);
1099 codeStream.ifle(trueLabel);
1103 codeStream.ifle(trueLabel);
1105 codeStream.recordPositionsFrom(pc, this.sourceStart);
1109 if (trueLabel == null) {
1110 // implicit falling through the TRUE case
1111 switch (promotedTypeID) {
1113 codeStream.if_icmpgt(falseLabel);
1117 codeStream.ifgt(falseLabel);
1121 codeStream.ifgt(falseLabel);
1125 codeStream.ifgt(falseLabel);
1127 codeStream.recordPositionsFrom(pc, this.sourceStart);
1130 // no implicit fall through TRUE/FALSE --> should never occur
1137 * Boolean generation for &
1139 public void generateOptimizedLogicalAnd(
1140 BlockScope currentScope,
1141 CodeStream codeStream,
1144 boolean valueRequired) {
1146 int pc = codeStream.position;
1148 if ((left.implicitConversion & 0xF) == T_boolean) {
1149 if ((condConst = left.conditionalConstant()) != NotAConstant) {
1150 if (condConst.booleanValue() == true) {
1151 // <something equivalent to true> & x
1152 left.generateOptimizedBoolean(
1158 if ((bits & OnlyValueRequiredMASK) != 0) {
1159 right.generateCode(currentScope, codeStream, valueRequired);
1161 right.generateOptimizedBoolean(
1169 // <something equivalent to false> & x
1170 left.generateOptimizedBoolean(
1176 right.generateOptimizedBoolean(
1182 if (valueRequired) {
1183 if ((bits & OnlyValueRequiredMASK) != 0) {
1184 codeStream.iconst_0();
1186 if (falseLabel != null) {
1187 // implicit falling through the TRUE case
1188 codeStream.goto_(falseLabel);
1193 codeStream.recordPositionsFrom(pc, this.sourceStart);
1196 if ((condConst = right.conditionalConstant()) != NotAConstant) {
1197 if (condConst.booleanValue() == true) {
1198 // x & <something equivalent to true>
1199 if ((bits & OnlyValueRequiredMASK) != 0) {
1200 left.generateCode(currentScope, codeStream, valueRequired);
1202 left.generateOptimizedBoolean(
1209 right.generateOptimizedBoolean(
1216 // x & <something equivalent to false>
1217 left.generateOptimizedBoolean(
1223 right.generateOptimizedBoolean(
1229 if (valueRequired) {
1230 if ((bits & OnlyValueRequiredMASK) != 0) {
1231 codeStream.iconst_0();
1233 if (falseLabel != null) {
1234 // implicit falling through the TRUE case
1235 codeStream.goto_(falseLabel);
1240 codeStream.recordPositionsFrom(pc, this.sourceStart);
1245 left.generateCode(currentScope, codeStream, valueRequired);
1246 right.generateCode(currentScope, codeStream, valueRequired);
1247 if (valueRequired) {
1249 if ((bits & OnlyValueRequiredMASK) == 0) {
1250 if (falseLabel == null) {
1251 if (trueLabel != null) {
1252 // implicit falling through the FALSE case
1253 codeStream.ifne(trueLabel);
1256 // implicit falling through the TRUE case
1257 if (trueLabel == null) {
1258 codeStream.ifeq(falseLabel);
1260 // no implicit fall through TRUE/FALSE --> should never occur
1265 codeStream.recordPositionsFrom(pc, this.sourceStart);
1269 * Boolean generation for |
1271 public void generateOptimizedLogicalOr(
1272 BlockScope currentScope,
1273 CodeStream codeStream,
1276 boolean valueRequired) {
1278 int pc = codeStream.position;
1280 if ((left.implicitConversion & 0xF) == T_boolean) {
1281 if ((condConst = left.conditionalConstant()) != NotAConstant) {
1282 if (condConst.booleanValue() == true) {
1283 // <something equivalent to true> | x
1284 left.generateOptimizedBoolean(
1290 right.generateOptimizedBoolean(
1296 if (valueRequired) {
1297 if ((bits & OnlyValueRequiredMASK) != 0) {
1298 codeStream.iconst_1();
1300 if (trueLabel != null) {
1301 codeStream.goto_(trueLabel);
1306 // <something equivalent to false> | x
1307 left.generateOptimizedBoolean(
1313 if ((bits & OnlyValueRequiredMASK) != 0) {
1314 right.generateCode(currentScope, codeStream, valueRequired);
1316 right.generateOptimizedBoolean(
1324 codeStream.recordPositionsFrom(pc, this.sourceStart);
1327 if ((condConst = right.conditionalConstant()) != NotAConstant) {
1328 if (condConst.booleanValue() == true) {
1329 // x | <something equivalent to true>
1330 left.generateOptimizedBoolean(
1336 right.generateOptimizedBoolean(
1342 if (valueRequired) {
1343 if ((bits & OnlyValueRequiredMASK) != 0) {
1344 codeStream.iconst_1();
1346 if (trueLabel != null) {
1347 codeStream.goto_(trueLabel);
1352 // x | <something equivalent to false>
1353 if ((bits & OnlyValueRequiredMASK) != 0) {
1354 left.generateCode(currentScope, codeStream, valueRequired);
1356 left.generateOptimizedBoolean(
1363 right.generateOptimizedBoolean(
1370 codeStream.recordPositionsFrom(pc, this.sourceStart);
1375 left.generateCode(currentScope, codeStream, valueRequired);
1376 right.generateCode(currentScope, codeStream, valueRequired);
1377 if (valueRequired) {
1379 if ((bits & OnlyValueRequiredMASK) == 0) {
1380 if (falseLabel == null) {
1381 if (trueLabel != null) {
1382 // implicit falling through the FALSE case
1383 codeStream.ifne(trueLabel);
1386 // implicit falling through the TRUE case
1387 if (trueLabel == null) {
1388 codeStream.ifeq(falseLabel);
1390 // no implicit fall through TRUE/FALSE --> should never occur
1395 codeStream.recordPositionsFrom(pc, this.sourceStart);
1399 * Boolean generation for ^
1401 public void generateOptimizedLogicalXor(
1402 BlockScope currentScope,
1403 CodeStream codeStream,
1406 boolean valueRequired) {
1408 int pc = codeStream.position;
1410 if ((left.implicitConversion & 0xF) == T_boolean) {
1411 if ((condConst = left.conditionalConstant()) != NotAConstant) {
1412 if (condConst.booleanValue() == true) {
1413 // <something equivalent to true> ^ x
1414 left.generateOptimizedBoolean(
1420 right.generateOptimizedBoolean(
1427 // <something equivalent to false> ^ x
1428 left.generateOptimizedBoolean(
1434 if ((bits & OnlyValueRequiredMASK) != 0) {
1435 right.generateCode(currentScope, codeStream, valueRequired);
1437 right.generateOptimizedBoolean(
1445 codeStream.recordPositionsFrom(pc, this.sourceStart);
1448 if ((condConst = right.conditionalConstant()) != NotAConstant) {
1449 if (condConst.booleanValue() == true) {
1450 // x ^ <something equivalent to true>
1451 left.generateOptimizedBoolean(
1457 right.generateOptimizedBoolean(
1464 // x ^ <something equivalent to false>
1465 if ((bits & OnlyValueRequiredMASK) != 0) {
1466 left.generateCode(currentScope, codeStream, valueRequired);
1468 left.generateOptimizedBoolean(
1475 right.generateOptimizedBoolean(
1482 codeStream.recordPositionsFrom(pc, this.sourceStart);
1487 left.generateCode(currentScope, codeStream, valueRequired);
1488 right.generateCode(currentScope, codeStream, valueRequired);
1489 if (valueRequired) {
1491 if ((bits & OnlyValueRequiredMASK) == 0) {
1492 if (falseLabel == null) {
1493 if (trueLabel != null) {
1494 // implicit falling through the FALSE case
1495 codeStream.ifne(trueLabel);
1498 // implicit falling through the TRUE case
1499 if (trueLabel == null) {
1500 codeStream.ifeq(falseLabel);
1502 // no implicit fall through TRUE/FALSE --> should never occur
1507 codeStream.recordPositionsFrom(pc, this.sourceStart);
1510 public void generateOptimizedStringBuffer(
1511 BlockScope blockScope,
1512 CodeStream codeStream,
1515 /* In the case trying to make a string concatenation, there is no need to create a new
1516 * string buffer, thus use a lower-level API for code generation involving only the
1517 * appending of arguments to the existing StringBuffer
1520 if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
1521 && ((bits & ReturnTypeIDMASK) == T_String)) {
1522 if (constant != NotAConstant) {
1523 codeStream.generateConstant(constant, implicitConversion);
1524 codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF);
1526 int pc = codeStream.position;
1527 left.generateOptimizedStringBuffer(
1530 left.implicitConversion & 0xF);
1531 codeStream.recordPositionsFrom(pc, left.sourceStart);
1532 pc = codeStream.position;
1533 right.generateOptimizedStringBuffer(
1536 right.implicitConversion & 0xF);
1537 codeStream.recordPositionsFrom(pc, right.sourceStart);
1540 super.generateOptimizedStringBuffer(blockScope, codeStream, typeID);
1544 public void generateOptimizedStringBufferCreation(
1545 BlockScope blockScope,
1546 CodeStream codeStream,
1549 /* In the case trying to make a string concatenation, there is no need to create a new
1550 * string buffer, thus use a lower-level API for code generation involving only the
1551 * appending of arguments to the existing StringBuffer
1554 if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
1555 && ((bits & ReturnTypeIDMASK) == T_String)) {
1556 if (constant != NotAConstant) {
1557 codeStream.newStringBuffer(); // new: java.lang.StringBuffer
1559 codeStream.ldc(constant.stringValue());
1560 codeStream.invokeStringBufferStringConstructor();
1561 // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
1563 int pc = codeStream.position;
1564 left.generateOptimizedStringBufferCreation(
1567 left.implicitConversion & 0xF);
1568 codeStream.recordPositionsFrom(pc, left.sourceStart);
1569 pc = codeStream.position;
1570 right.generateOptimizedStringBuffer(
1573 right.implicitConversion & 0xF);
1574 codeStream.recordPositionsFrom(pc, right.sourceStart);
1577 super.generateOptimizedStringBufferCreation(blockScope, codeStream, typeID);
1581 public boolean isCompactableOperation() {
1586 public void optimizedBooleanConstant(int leftId, int operator, int rightId) {
1590 if ((leftId != T_boolean) || (rightId != T_boolean))
1594 if ((cst = left.conditionalConstant()) != NotAConstant) {
1595 if (cst.booleanValue() == false) { // left is equivalent to false
1596 optimizedBooleanConstant = cst; // constant(false)
1598 } else { //left is equivalent to true
1599 if ((cst = right.conditionalConstant()) != NotAConstant) {
1600 optimizedBooleanConstant = cst;
1601 // the conditional result is equivalent to the right conditional value
1606 if ((cst = right.conditionalConstant()) != NotAConstant) {
1607 if (cst.booleanValue() == false) { // right is equivalent to false
1608 optimizedBooleanConstant = cst; // constant(false)
1613 if ((leftId != T_boolean) || (rightId != T_boolean))
1616 if ((cst = left.conditionalConstant()) != NotAConstant) {
1617 if (cst.booleanValue() == true) { // left is equivalent to true
1618 optimizedBooleanConstant = cst; // constant(true)
1620 } else { //left is equivalent to false
1621 if ((cst = right.conditionalConstant()) != NotAConstant) {
1622 optimizedBooleanConstant = cst;
1627 if ((cst = right.conditionalConstant()) != NotAConstant) {
1628 if (cst.booleanValue() == true) { // right is equivalent to true
1629 optimizedBooleanConstant = cst; // constant(true)
1635 public TypeBinding resolveType(BlockScope scope) {
1637 // use the id of the type to navigate into the table
1638 TypeBinding leftTb = left.resolveType(scope);
1639 TypeBinding rightTb = right.resolveType(scope);
1640 if (leftTb == null || rightTb == null) {
1641 constant = Constant.NotAConstant;
1644 int leftId = leftTb.id;
1645 int rightId = rightTb.id;
1647 || rightId > 15) { // must convert String + Object || Object + String
1648 if (leftId == T_String) {
1650 } else if (rightId == T_String) {
1653 constant = Constant.NotAConstant;
1654 scope.problemReporter().invalidOperator(this, leftTb, rightTb);
1658 if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
1659 if (leftId == T_String
1660 && rightTb.isArrayType()
1661 && ((ArrayBinding) rightTb).elementsType(scope) == CharBinding)
1662 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(
1666 && leftTb.isArrayType()
1667 && ((ArrayBinding) leftTb).elementsType(scope) == CharBinding)
1668 scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(
1672 // the code is an int
1673 // (cast) left Op (cast) rigth --> result
1674 // 0000 0000 0000 0000 0000
1675 // <<16 <<12 <<8 <<4 <<0
1677 // Don't test for result = 0. If it is zero, some more work is done.
1678 // On the one hand when it is not zero (correct code) we avoid doing the test
1680 ResolveTypeTables[(bits & OperatorMASK) >> OperatorSHIFT][(leftId << 4)
1682 left.implicitConversion = result >>> 12;
1683 right.implicitConversion = (result >>> 4) & 0x000FF;
1685 bits |= result & 0xF;
1686 switch (result & 0xF) { // record the current ReturnTypeID
1687 // only switch on possible result type.....
1689 this.typeBinding = BooleanBinding;
1692 this.typeBinding = ByteBinding;
1695 this.typeBinding = CharBinding;
1698 this.typeBinding = DoubleBinding;
1701 this.typeBinding = FloatBinding;
1704 this.typeBinding = IntBinding;
1707 this.typeBinding = LongBinding;
1710 this.typeBinding = scope.getJavaLangString();
1712 default : //error........
1713 constant = Constant.NotAConstant;
1714 scope.problemReporter().invalidOperator(this, leftTb, rightTb);
1718 // compute the constant when valid
1719 computeConstant(scope, leftId, rightId);
1720 return this.typeBinding;
1723 public String toStringExpressionNoParenthesis() {
1725 return left.toStringExpression() + " " + //$NON-NLS-1$
1726 operatorToString() + " " + //$NON-NLS-1$
1727 right.toStringExpression();
1730 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
1732 if (visitor.visit(this, scope)) {
1733 left.traverse(visitor, scope);
1734 right.traverse(visitor, scope);
1736 visitor.endVisit(this, scope);