1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.impl.Constant;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19 // dedicated treatment for the ||
20 public class OR_OR_Expression extends BinaryExpression {
22 int rightInitStateIndex = -1;
24 int mergedInitStateIndex = -1;
26 public OR_OR_Expression(Expression left, Expression right, int operator) {
27 super(left, right, operator);
30 public FlowInfo analyseCode(BlockScope currentScope,
31 FlowContext flowContext, FlowInfo flowInfo) {
33 Constant cst = this.left.optimizedBooleanConstant();
34 boolean isLeftOptimizedTrue = cst != NotAConstant
35 && cst.booleanValue() == true;
36 boolean isLeftOptimizedFalse = cst != NotAConstant
37 && cst.booleanValue() == false;
39 if (isLeftOptimizedFalse) {
41 // need to be careful of scenario:
42 // (x || y) || !z, if passing the left info to the right, it would
43 // be swapped by the !
44 FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext,
45 flowInfo).unconditionalInits();
46 mergedInfo = right.analyseCode(currentScope, flowContext,
48 mergedInitStateIndex = currentScope.methodScope()
49 .recordInitializationStates(mergedInfo);
53 FlowInfo leftInfo = left.analyseCode(currentScope, flowContext,
56 // need to be careful of scenario:
57 // (x || y) || !z, if passing the left info to the right, it would be
59 FlowInfo rightInfo = leftInfo.initsWhenFalse().unconditionalInits()
61 rightInitStateIndex = currentScope.methodScope()
62 .recordInitializationStates(rightInfo);
64 int previousMode = rightInfo.reachMode();
65 if (isLeftOptimizedTrue) {
66 rightInfo.setReachMode(FlowInfo.UNREACHABLE);
68 rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
69 FlowInfo falseMergedInfo = rightInfo.initsWhenFalse().copy();
70 rightInfo.setReachMode(previousMode); // reset after falseMergedInfo
73 FlowInfo mergedInfo = FlowInfo
75 // merging two true initInfos for such a negative case:
76 // if ((t && (b = t)) || f) r = b; // b may not have
78 leftInfo.initsWhenTrue().copy().unconditionalInits()
80 rightInfo.initsWhenTrue().copy()
81 .unconditionalInits()),
83 mergedInitStateIndex = currentScope.methodScope()
84 .recordInitializationStates(mergedInfo);
89 * Code generation for a binary operation
92 * net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
94 * net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
95 * @param valueRequired
98 // public void generateCode(
99 // BlockScope currentScope,
100 // CodeStream codeStream,
101 // boolean valueRequired) {
102 // int pc = codeStream.position;
103 // Label falseLabel, endLabel;
104 // if (constant != Constant.NotAConstant) {
105 // if (valueRequired)
106 // codeStream.generateConstant(constant, implicitConversion);
107 // codeStream.recordPositionsFrom(pc, this.sourceStart);
110 // bits |= OnlyValueRequiredMASK;
111 // generateOptimizedBoolean(
115 // (falseLabel = new Label(codeStream)),
117 // /* improving code gen for such a case: boolean b = i < 0 || true;
118 // * since the label has never been used, we have the inlined value on the
120 // if (falseLabel.hasForwardReferences()) {
121 // if (valueRequired) {
122 // codeStream.iconst_1();
123 // if ((bits & ValueForReturnMASK) != 0) {
124 // codeStream.ireturn();
125 // falseLabel.place();
126 // codeStream.iconst_0();
128 // codeStream.goto_(endLabel = new Label(codeStream));
129 // codeStream.decrStackSize(1);
130 // falseLabel.place();
131 // codeStream.iconst_0();
135 // falseLabel.place();
138 // if (valueRequired) {
139 // codeStream.generateImplicitConversion(implicitConversion);
141 // codeStream.recordPositionsFrom(pc, this.sourceStart);
145 // * Boolean operator code generation
146 // * Optimized operations are: ||
148 // public void generateOptimizedBoolean(
149 // BlockScope currentScope,
150 // CodeStream codeStream,
153 // boolean valueRequired) {
154 // if (constant != Constant.NotAConstant) {
155 // super.generateOptimizedBoolean(currentScope, codeStream, trueLabel,
156 // falseLabel, valueRequired);
159 // Constant condConst;
160 // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
161 // if (condConst.booleanValue() == true) {
162 // // <something equivalent to true> || x
163 // left.generateOptimizedBoolean(
169 // if (valueRequired) {
170 // if ((bits & OnlyValueRequiredMASK) != 0) {
171 // codeStream.iconst_1();
173 // if (trueLabel != null) {
174 // codeStream.goto_(trueLabel);
178 // // reposition the endPC
179 // codeStream.updateLastRecordedEndPC(codeStream.position);
181 // // <something equivalent to false> || x
182 // left.generateOptimizedBoolean(
188 // if (rightInitStateIndex != -1) {
189 // codeStream.addDefinitelyAssignedVariables(currentScope,
190 // rightInitStateIndex);
192 // if ((bits & OnlyValueRequiredMASK) != 0) {
193 // right.generateCode(currentScope, codeStream, valueRequired);
195 // right.generateOptimizedBoolean(
203 // if (mergedInitStateIndex != -1) {
204 // codeStream.removeNotDefinitelyAssignedVariables(
206 // mergedInitStateIndex);
210 // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
211 // if (condConst.booleanValue() == true) {
212 // // x || <something equivalent to true>
213 // Label internalFalseLabel = new Label(codeStream);
214 // left.generateOptimizedBoolean(
218 // internalFalseLabel, // will be true in the end
220 // if (rightInitStateIndex != -1) {
221 // codeStream.addDefinitelyAssignedVariables(currentScope,
222 // rightInitStateIndex);
224 // internalFalseLabel.place();
225 // right.generateOptimizedBoolean(
231 // if (valueRequired) {
232 // if ((bits & OnlyValueRequiredMASK) != 0) {
233 // codeStream.iconst_1();
235 // if (trueLabel != null) {
236 // codeStream.goto_(trueLabel);
240 // // reposition the endPC
241 // codeStream.updateLastRecordedEndPC(codeStream.position);
243 // // x || <something equivalent to false>
244 // if ((bits & OnlyValueRequiredMASK) != 0) {
245 // left.generateCode(currentScope, codeStream, valueRequired);
247 // left.generateOptimizedBoolean(
254 // if (rightInitStateIndex != -1) {
255 // codeStream.addDefinitelyAssignedVariables(currentScope,
256 // rightInitStateIndex);
258 // right.generateOptimizedBoolean(
265 // if (mergedInitStateIndex != -1) {
266 // codeStream.removeNotDefinitelyAssignedVariables(
268 // mergedInitStateIndex);
273 // if (falseLabel == null) {
274 // if (trueLabel != null) {
275 // // implicit falling through the FALSE case
276 // left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null,
278 // right.generateOptimizedBoolean(
286 // // implicit falling through the TRUE case
287 // if (trueLabel == null) {
288 // Label internalTrueLabel = new Label(codeStream);
289 // left.generateOptimizedBoolean(
292 // internalTrueLabel,
295 // if (rightInitStateIndex != -1) {
296 // codeStream.addDefinitelyAssignedVariables(currentScope,
297 // rightInitStateIndex);
299 // right.generateOptimizedBoolean(
305 // internalTrueLabel.place();
307 // // no implicit fall through TRUE/FALSE --> should never occur
310 // if (mergedInitStateIndex != -1) {
311 // codeStream.removeNotDefinitelyAssignedVariables(
313 // mergedInitStateIndex);
316 public boolean isCompactableOperation() {
320 public void traverse(ASTVisitor visitor, BlockScope scope) {
321 if (visitor.visit(this, scope)) {
322 left.traverse(visitor, scope);
323 right.traverse(visitor, scope);
325 visitor.endVisit(this, scope);