X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/BinaryExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/BinaryExpression.java index f094885..4f8e580 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/BinaryExpression.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/BinaryExpression.java @@ -1,28 +1,31 @@ /******************************************************************************* - * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. + * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 + * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html + * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation - ******************************************************************************/ + *******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.ast; -import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor; -import net.sourceforge.phpdt.internal.compiler.impl.*; -import net.sourceforge.phpdt.internal.compiler.codegen.*; -import net.sourceforge.phpdt.internal.compiler.flow.*; -import net.sourceforge.phpdt.internal.compiler.lookup.*; +import net.sourceforge.phpdt.core.compiler.ITerminalSymbols.TokenName; +import net.sourceforge.phpdt.internal.compiler.ASTVisitor; +import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; +import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; +import net.sourceforge.phpdt.internal.compiler.impl.Constant; +import net.sourceforge.phpdt.internal.compiler.lookup.ArrayBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; public class BinaryExpression extends OperatorExpression { public Expression left, right; + public Constant optimizedBooleanConstant; public BinaryExpression(Expression left, Expression right, int operator) { - this.left = left; this.right = right; this.bits |= operator << OperatorSHIFT; // encode operator @@ -30,1608 +33,1631 @@ public class BinaryExpression extends OperatorExpression { this.sourceEnd = right.sourceEnd; } - public FlowInfo analyseCode( - BlockScope currentScope, - FlowContext flowContext, - FlowInfo flowInfo) { + public FlowInfo analyseCode(BlockScope currentScope, + FlowContext flowContext, FlowInfo flowInfo) { - return right - .analyseCode( + return right.analyseCode( currentScope, flowContext, - left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()) - .unconditionalInits(); + left.analyseCode(currentScope, flowContext, flowInfo) + .unconditionalInits()).unconditionalInits(); } public void computeConstant(BlockScope scope, int leftId, int rightId) { - //compute the constant when valid - if ((left.constant != Constant.NotAConstant) - && (right.constant != Constant.NotAConstant)) { + // compute the constant when valid + if ((this.left.constant != Constant.NotAConstant) + && (this.right.constant != Constant.NotAConstant)) { try { - constant = - Constant.computeConstantOperation( - left.constant, - leftId, - (bits & OperatorMASK) >> OperatorSHIFT, - right.constant, - rightId); + this.constant = Constant.computeConstantOperation( + this.left.constant, leftId, + (this.bits & OperatorMASK) >> OperatorSHIFT, + this.right.constant, rightId); } catch (ArithmeticException e) { - constant = Constant.NotAConstant; + this.constant = Constant.NotAConstant; // 1.2 no longer throws an exception at compile-time - //scope.problemReporter().compileTimeConstantThrowsArithmeticException(this); + // scope.problemReporter().compileTimeConstantThrowsArithmeticException(this); } } else { - constant = Constant.NotAConstant; - //add some work for the boolean operators & | - optimizedBooleanConstant( - leftId, - (bits & OperatorMASK) >> OperatorSHIFT, - rightId); + this.constant = Constant.NotAConstant; + // add some work for the boolean operators & | + // this.optimizedBooleanConstant( + // leftId, + // (this.bits & OperatorMASK) >> OperatorSHIFT, + // rightId); } } - public Constant conditionalConstant() { + public Constant optimizedBooleanConstant() { - return optimizedBooleanConstant == null ? constant : optimizedBooleanConstant; + return this.optimizedBooleanConstant == null ? this.constant + : this.optimizedBooleanConstant; } /** * Code generation for a binary operation */ - public void generateCode( - BlockScope currentScope, - CodeStream codeStream, - boolean valueRequired) { - - int pc = codeStream.position; - Label falseLabel, endLabel; - if (constant != Constant.NotAConstant) { - if (valueRequired) - codeStream.generateConstant(constant, implicitConversion); - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - bits |= OnlyValueRequiredMASK; - switch ((bits & OperatorMASK) >> OperatorSHIFT) { - case PLUS : - switch (bits & ReturnTypeIDMASK) { - case T_String : - codeStream.generateStringAppend(currentScope, left, right); - if (!valueRequired) - codeStream.pop(); - break; - case T_int : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.iadd(); - break; - case T_long : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.ladd(); - break; - case T_double : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.dadd(); - break; - case T_float : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.fadd(); - break; - } - break; - case MINUS : - switch (bits & ReturnTypeIDMASK) { - case T_int : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.isub(); - break; - case T_long : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.lsub(); - break; - case T_double : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.dsub(); - break; - case T_float : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.fsub(); - break; - } - break; - case MULTIPLY : - switch (bits & ReturnTypeIDMASK) { - case T_int : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.imul(); - break; - case T_long : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.lmul(); - break; - case T_double : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.dmul(); - break; - case T_float : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.fmul(); - break; - } - break; - case DIVIDE : - switch (bits & ReturnTypeIDMASK) { - case T_int : - left.generateCode(currentScope, codeStream, true); - right.generateCode(currentScope, codeStream, true); - codeStream.idiv(); - if (!valueRequired) - codeStream.pop(); - break; - case T_long : - left.generateCode(currentScope, codeStream, true); - right.generateCode(currentScope, codeStream, true); - codeStream.ldiv(); - if (!valueRequired) - codeStream.pop2(); - break; - case T_double : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.ddiv(); - break; - case T_float : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.fdiv(); - break; - } - break; - case REMAINDER : - switch (bits & ReturnTypeIDMASK) { - case T_int : - left.generateCode(currentScope, codeStream, true); - right.generateCode(currentScope, codeStream, true); - codeStream.irem(); - if (!valueRequired) - codeStream.pop(); - break; - case T_long : - left.generateCode(currentScope, codeStream, true); - right.generateCode(currentScope, codeStream, true); - codeStream.lrem(); - if (!valueRequired) - codeStream.pop2(); - break; - case T_double : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.drem(); - break; - case T_float : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.frem(); - break; - } - break; - case AND : - switch (bits & ReturnTypeIDMASK) { - case T_int : - // 0 & x - if ((left.constant != Constant.NotAConstant) - && (left.constant.typeID() == T_int) - && (left.constant.intValue() == 0)) { - right.generateCode(currentScope, codeStream, false); - if (valueRequired) - codeStream.iconst_0(); - } else { - // x & 0 - if ((right.constant != Constant.NotAConstant) - && (right.constant.typeID() == T_int) - && (right.constant.intValue() == 0)) { - left.generateCode(currentScope, codeStream, false); - if (valueRequired) - codeStream.iconst_0(); - } else { - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.iand(); - } - } - break; - case T_long : - // 0 & x - if ((left.constant != Constant.NotAConstant) - && (left.constant.typeID() == T_long) - && (left.constant.longValue() == 0L)) { - right.generateCode(currentScope, codeStream, false); - if (valueRequired) - codeStream.lconst_0(); - } else { - // x & 0 - if ((right.constant != Constant.NotAConstant) - && (right.constant.typeID() == T_long) - && (right.constant.longValue() == 0L)) { - left.generateCode(currentScope, codeStream, false); - if (valueRequired) - codeStream.lconst_0(); - } else { - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.land(); - } - } - break; - case T_boolean : // logical and - generateOptimizedLogicalAnd( - currentScope, - codeStream, - null, - (falseLabel = new Label(codeStream)), - valueRequired); - /* improving code gen for such a case: boolean b = i < 0 && false; - * since the label has never been used, we have the inlined value on the stack. */ - if (falseLabel.hasForwardReferences()) { - if (valueRequired) { - codeStream.iconst_1(); - if ((bits & ValueForReturnMASK) != 0) { - codeStream.ireturn(); - falseLabel.place(); - codeStream.iconst_0(); - } else { - codeStream.goto_(endLabel = new Label(codeStream)); - codeStream.decrStackSize(1); - falseLabel.place(); - codeStream.iconst_0(); - endLabel.place(); - } - } else { - falseLabel.place(); - } - } - } - break; - case OR : - switch (bits & ReturnTypeIDMASK) { - case T_int : - // 0 | x - if ((left.constant != Constant.NotAConstant) - && (left.constant.typeID() == T_int) - && (left.constant.intValue() == 0)) { - right.generateCode(currentScope, codeStream, valueRequired); - } else { - // x | 0 - if ((right.constant != Constant.NotAConstant) - && (right.constant.typeID() == T_int) - && (right.constant.intValue() == 0)) { - left.generateCode(currentScope, codeStream, valueRequired); - } else { - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.ior(); - } - } - break; - case T_long : - // 0 | x - if ((left.constant != Constant.NotAConstant) - && (left.constant.typeID() == T_long) - && (left.constant.longValue() == 0L)) { - right.generateCode(currentScope, codeStream, valueRequired); - } else { - // x | 0 - if ((right.constant != Constant.NotAConstant) - && (right.constant.typeID() == T_long) - && (right.constant.longValue() == 0L)) { - left.generateCode(currentScope, codeStream, valueRequired); - } else { - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.lor(); - } - } - break; - case T_boolean : // logical or - generateOptimizedLogicalOr( - currentScope, - codeStream, - null, - (falseLabel = new Label(codeStream)), - valueRequired); - /* improving code gen for such a case: boolean b = i < 0 || true; - * since the label has never been used, we have the inlined value on the stack. */ - if (falseLabel.hasForwardReferences()) { - if (valueRequired) { - codeStream.iconst_1(); - if ((bits & ValueForReturnMASK) != 0) { - codeStream.ireturn(); - falseLabel.place(); - codeStream.iconst_0(); - } else { - codeStream.goto_(endLabel = new Label(codeStream)); - codeStream.decrStackSize(1); - falseLabel.place(); - codeStream.iconst_0(); - endLabel.place(); - } - } else { - falseLabel.place(); - } - } - } - break; - case XOR : - switch (bits & ReturnTypeIDMASK) { - case T_int : - // 0 ^ x - if ((left.constant != Constant.NotAConstant) - && (left.constant.typeID() == T_int) - && (left.constant.intValue() == 0)) { - right.generateCode(currentScope, codeStream, valueRequired); - } else { - // x ^ 0 - if ((right.constant != Constant.NotAConstant) - && (right.constant.typeID() == T_int) - && (right.constant.intValue() == 0)) { - left.generateCode(currentScope, codeStream, valueRequired); - } else { - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.ixor(); - } - } - break; - case T_long : - // 0 ^ x - if ((left.constant != Constant.NotAConstant) - && (left.constant.typeID() == T_long) - && (left.constant.longValue() == 0L)) { - right.generateCode(currentScope, codeStream, valueRequired); - } else { - // x ^ 0 - if ((right.constant != Constant.NotAConstant) - && (right.constant.typeID() == T_long) - && (right.constant.longValue() == 0L)) { - left.generateCode(currentScope, codeStream, valueRequired); - } else { - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.lxor(); - } - } - break; - case T_boolean : - generateOptimizedLogicalXor( - currentScope, - codeStream, - null, - (falseLabel = new Label(codeStream)), - valueRequired); - /* improving code gen for such a case: boolean b = i < 0 ^ bool; - * since the label has never been used, we have the inlined value on the stack. */ - if (falseLabel.hasForwardReferences()) { - if (valueRequired) { - codeStream.iconst_1(); - if ((bits & ValueForReturnMASK) != 0) { - codeStream.ireturn(); - falseLabel.place(); - codeStream.iconst_0(); - } else { - codeStream.goto_(endLabel = new Label(codeStream)); - codeStream.decrStackSize(1); - falseLabel.place(); - codeStream.iconst_0(); - endLabel.place(); - } - } else { - falseLabel.place(); - } - } - } - break; - case LEFT_SHIFT : - switch (bits & ReturnTypeIDMASK) { - case T_int : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.ishl(); - break; - case T_long : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.lshl(); - } - break; - case RIGHT_SHIFT : - switch (bits & ReturnTypeIDMASK) { - case T_int : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.ishr(); - break; - case T_long : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.lshr(); - } - break; - case UNSIGNED_RIGHT_SHIFT : - switch (bits & ReturnTypeIDMASK) { - case T_int : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.iushr(); - break; - case T_long : - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) - codeStream.lushr(); - } - break; - case GREATER : - generateOptimizedGreaterThan( - currentScope, - codeStream, - null, - (falseLabel = new Label(codeStream)), - valueRequired); - if (valueRequired) { - codeStream.iconst_1(); - if ((bits & ValueForReturnMASK) != 0) { - codeStream.ireturn(); - falseLabel.place(); - codeStream.iconst_0(); - } else { - codeStream.goto_(endLabel = new Label(codeStream)); - codeStream.decrStackSize(1); - falseLabel.place(); - codeStream.iconst_0(); - endLabel.place(); - } - } - break; - case GREATER_EQUAL : - generateOptimizedGreaterThanOrEqual( - currentScope, - codeStream, - null, - (falseLabel = new Label(codeStream)), - valueRequired); - if (valueRequired) { - codeStream.iconst_1(); - if ((bits & ValueForReturnMASK) != 0) { - codeStream.ireturn(); - falseLabel.place(); - codeStream.iconst_0(); - } else { - codeStream.goto_(endLabel = new Label(codeStream)); - codeStream.decrStackSize(1); - falseLabel.place(); - codeStream.iconst_0(); - endLabel.place(); - } - } - break; - case LESS : - generateOptimizedLessThan( - currentScope, - codeStream, - null, - (falseLabel = new Label(codeStream)), - valueRequired); - if (valueRequired) { - codeStream.iconst_1(); - if ((bits & ValueForReturnMASK) != 0) { - codeStream.ireturn(); - falseLabel.place(); - codeStream.iconst_0(); - } else { - codeStream.goto_(endLabel = new Label(codeStream)); - codeStream.decrStackSize(1); - falseLabel.place(); - codeStream.iconst_0(); - endLabel.place(); - } - } - break; - case LESS_EQUAL : - generateOptimizedLessThanOrEqual( - currentScope, - codeStream, - null, - (falseLabel = new Label(codeStream)), - valueRequired); - if (valueRequired) { - codeStream.iconst_1(); - if ((bits & ValueForReturnMASK) != 0) { - codeStream.ireturn(); - falseLabel.place(); - codeStream.iconst_0(); - } else { - codeStream.goto_(endLabel = new Label(codeStream)); - codeStream.decrStackSize(1); - falseLabel.place(); - codeStream.iconst_0(); - endLabel.place(); - } - } - } - if (valueRequired) { - codeStream.generateImplicitConversion(implicitConversion); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - } - + // public void generateCode( + // BlockScope currentScope, + // CodeStream codeStream, + // boolean valueRequired) { + // + // int pc = codeStream.position; + // Label falseLabel, endLabel; + // if (constant != Constant.NotAConstant) { + // if (valueRequired) + // codeStream.generateConstant(constant, implicitConversion); + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // return; + // } + // bits |= OnlyValueRequiredMASK; + // switch ((bits & OperatorMASK) >> OperatorSHIFT) { + // case PLUS : + // switch (bits & ReturnTypeIDMASK) { + // case T_String : + // codeStream.generateStringAppend(currentScope, left, right); + // if (!valueRequired) + // codeStream.pop(); + // break; + // case T_int : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.iadd(); + // break; + // case T_long : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.ladd(); + // break; + // case T_double : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.dadd(); + // break; + // case T_float : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.fadd(); + // break; + // } + // break; + // case MINUS : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.isub(); + // break; + // case T_long : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.lsub(); + // break; + // case T_double : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.dsub(); + // break; + // case T_float : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.fsub(); + // break; + // } + // break; + // case MULTIPLY : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.imul(); + // break; + // case T_long : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.lmul(); + // break; + // case T_double : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.dmul(); + // break; + // case T_float : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.fmul(); + // break; + // } + // break; + // case DIVIDE : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // left.generateCode(currentScope, codeStream, true); + // right.generateCode(currentScope, codeStream, true); + // codeStream.idiv(); + // if (!valueRequired) + // codeStream.pop(); + // break; + // case T_long : + // left.generateCode(currentScope, codeStream, true); + // right.generateCode(currentScope, codeStream, true); + // codeStream.ldiv(); + // if (!valueRequired) + // codeStream.pop2(); + // break; + // case T_double : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.ddiv(); + // break; + // case T_float : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.fdiv(); + // break; + // } + // break; + // case REMAINDER : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // left.generateCode(currentScope, codeStream, true); + // right.generateCode(currentScope, codeStream, true); + // codeStream.irem(); + // if (!valueRequired) + // codeStream.pop(); + // break; + // case T_long : + // left.generateCode(currentScope, codeStream, true); + // right.generateCode(currentScope, codeStream, true); + // codeStream.lrem(); + // if (!valueRequired) + // codeStream.pop2(); + // break; + // case T_double : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.drem(); + // break; + // case T_float : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.frem(); + // break; + // } + // break; + // case AND : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // // 0 & x + // if ((left.constant != Constant.NotAConstant) + // && (left.constant.typeID() == T_int) + // && (left.constant.intValue() == 0)) { + // right.generateCode(currentScope, codeStream, false); + // if (valueRequired) + // codeStream.iconst_0(); + // } else { + // // x & 0 + // if ((right.constant != Constant.NotAConstant) + // && (right.constant.typeID() == T_int) + // && (right.constant.intValue() == 0)) { + // left.generateCode(currentScope, codeStream, false); + // if (valueRequired) + // codeStream.iconst_0(); + // } else { + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.iand(); + // } + // } + // break; + // case T_long : + // // 0 & x + // if ((left.constant != Constant.NotAConstant) + // && (left.constant.typeID() == T_long) + // && (left.constant.longValue() == 0L)) { + // right.generateCode(currentScope, codeStream, false); + // if (valueRequired) + // codeStream.lconst_0(); + // } else { + // // x & 0 + // if ((right.constant != Constant.NotAConstant) + // && (right.constant.typeID() == T_long) + // && (right.constant.longValue() == 0L)) { + // left.generateCode(currentScope, codeStream, false); + // if (valueRequired) + // codeStream.lconst_0(); + // } else { + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.land(); + // } + // } + // break; + // case T_boolean : // logical and + // generateOptimizedLogicalAnd( + // currentScope, + // codeStream, + // null, + // (falseLabel = new Label(codeStream)), + // valueRequired); + // /* improving code gen for such a case: boolean b = i < 0 && false; + // * since the label has never been used, we have the inlined value on the + // stack. */ + // if (falseLabel.hasForwardReferences()) { + // if (valueRequired) { + // codeStream.iconst_1(); + // if ((bits & ValueForReturnMASK) != 0) { + // codeStream.ireturn(); + // falseLabel.place(); + // codeStream.iconst_0(); + // } else { + // codeStream.goto_(endLabel = new Label(codeStream)); + // codeStream.decrStackSize(1); + // falseLabel.place(); + // codeStream.iconst_0(); + // endLabel.place(); + // } + // } else { + // falseLabel.place(); + // } + // } + // } + // break; + // case OR : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // // 0 | x + // if ((left.constant != Constant.NotAConstant) + // && (left.constant.typeID() == T_int) + // && (left.constant.intValue() == 0)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // } else { + // // x | 0 + // if ((right.constant != Constant.NotAConstant) + // && (right.constant.typeID() == T_int) + // && (right.constant.intValue() == 0)) { + // left.generateCode(currentScope, codeStream, valueRequired); + // } else { + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.ior(); + // } + // } + // break; + // case T_long : + // // 0 | x + // if ((left.constant != Constant.NotAConstant) + // && (left.constant.typeID() == T_long) + // && (left.constant.longValue() == 0L)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // } else { + // // x | 0 + // if ((right.constant != Constant.NotAConstant) + // && (right.constant.typeID() == T_long) + // && (right.constant.longValue() == 0L)) { + // left.generateCode(currentScope, codeStream, valueRequired); + // } else { + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.lor(); + // } + // } + // break; + // case T_boolean : // logical or + // generateOptimizedLogicalOr( + // currentScope, + // codeStream, + // null, + // (falseLabel = new Label(codeStream)), + // valueRequired); + // /* improving code gen for such a case: boolean b = i < 0 || true; + // * since the label has never been used, we have the inlined value on the + // stack. */ + // if (falseLabel.hasForwardReferences()) { + // if (valueRequired) { + // codeStream.iconst_1(); + // if ((bits & ValueForReturnMASK) != 0) { + // codeStream.ireturn(); + // falseLabel.place(); + // codeStream.iconst_0(); + // } else { + // codeStream.goto_(endLabel = new Label(codeStream)); + // codeStream.decrStackSize(1); + // falseLabel.place(); + // codeStream.iconst_0(); + // endLabel.place(); + // } + // } else { + // falseLabel.place(); + // } + // } + // } + // break; + // case XOR : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // // 0 ^ x + // if ((left.constant != Constant.NotAConstant) + // && (left.constant.typeID() == T_int) + // && (left.constant.intValue() == 0)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // } else { + // // x ^ 0 + // if ((right.constant != Constant.NotAConstant) + // && (right.constant.typeID() == T_int) + // && (right.constant.intValue() == 0)) { + // left.generateCode(currentScope, codeStream, valueRequired); + // } else { + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.ixor(); + // } + // } + // break; + // case T_long : + // // 0 ^ x + // if ((left.constant != Constant.NotAConstant) + // && (left.constant.typeID() == T_long) + // && (left.constant.longValue() == 0L)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // } else { + // // x ^ 0 + // if ((right.constant != Constant.NotAConstant) + // && (right.constant.typeID() == T_long) + // && (right.constant.longValue() == 0L)) { + // left.generateCode(currentScope, codeStream, valueRequired); + // } else { + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.lxor(); + // } + // } + // break; + // case T_boolean : + // generateOptimizedLogicalXor( + // currentScope, + // codeStream, + // null, + // (falseLabel = new Label(codeStream)), + // valueRequired); + // /* improving code gen for such a case: boolean b = i < 0 ^ bool; + // * since the label has never been used, we have the inlined value on the + // stack. */ + // if (falseLabel.hasForwardReferences()) { + // if (valueRequired) { + // codeStream.iconst_1(); + // if ((bits & ValueForReturnMASK) != 0) { + // codeStream.ireturn(); + // falseLabel.place(); + // codeStream.iconst_0(); + // } else { + // codeStream.goto_(endLabel = new Label(codeStream)); + // codeStream.decrStackSize(1); + // falseLabel.place(); + // codeStream.iconst_0(); + // endLabel.place(); + // } + // } else { + // falseLabel.place(); + // } + // } + // } + // break; + // case LEFT_SHIFT : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.ishl(); + // break; + // case T_long : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.lshl(); + // } + // break; + // case RIGHT_SHIFT : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.ishr(); + // break; + // case T_long : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.lshr(); + // } + // break; + // case UNSIGNED_RIGHT_SHIFT : + // switch (bits & ReturnTypeIDMASK) { + // case T_int : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.iushr(); + // break; + // case T_long : + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) + // codeStream.lushr(); + // } + // break; + // case GREATER : + // generateOptimizedGreaterThan( + // currentScope, + // codeStream, + // null, + // (falseLabel = new Label(codeStream)), + // valueRequired); + // if (valueRequired) { + // codeStream.iconst_1(); + // if ((bits & ValueForReturnMASK) != 0) { + // codeStream.ireturn(); + // falseLabel.place(); + // codeStream.iconst_0(); + // } else { + // codeStream.goto_(endLabel = new Label(codeStream)); + // codeStream.decrStackSize(1); + // falseLabel.place(); + // codeStream.iconst_0(); + // endLabel.place(); + // } + // } + // break; + // case GREATER_EQUAL : + // generateOptimizedGreaterThanOrEqual( + // currentScope, + // codeStream, + // null, + // (falseLabel = new Label(codeStream)), + // valueRequired); + // if (valueRequired) { + // codeStream.iconst_1(); + // if ((bits & ValueForReturnMASK) != 0) { + // codeStream.ireturn(); + // falseLabel.place(); + // codeStream.iconst_0(); + // } else { + // codeStream.goto_(endLabel = new Label(codeStream)); + // codeStream.decrStackSize(1); + // falseLabel.place(); + // codeStream.iconst_0(); + // endLabel.place(); + // } + // } + // break; + // case LESS : + // generateOptimizedLessThan( + // currentScope, + // codeStream, + // null, + // (falseLabel = new Label(codeStream)), + // valueRequired); + // if (valueRequired) { + // codeStream.iconst_1(); + // if ((bits & ValueForReturnMASK) != 0) { + // codeStream.ireturn(); + // falseLabel.place(); + // codeStream.iconst_0(); + // } else { + // codeStream.goto_(endLabel = new Label(codeStream)); + // codeStream.decrStackSize(1); + // falseLabel.place(); + // codeStream.iconst_0(); + // endLabel.place(); + // } + // } + // break; + // case LESS_EQUAL : + // generateOptimizedLessThanOrEqual( + // currentScope, + // codeStream, + // null, + // (falseLabel = new Label(codeStream)), + // valueRequired); + // if (valueRequired) { + // codeStream.iconst_1(); + // if ((bits & ValueForReturnMASK) != 0) { + // codeStream.ireturn(); + // falseLabel.place(); + // codeStream.iconst_0(); + // } else { + // codeStream.goto_(endLabel = new Label(codeStream)); + // codeStream.decrStackSize(1); + // falseLabel.place(); + // codeStream.iconst_0(); + // endLabel.place(); + // } + // } + // } + // if (valueRequired) { + // codeStream.generateImplicitConversion(implicitConversion); + // } + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // } /** - * Boolean operator code generation - * Optimized operations are: <, <=, >, >=, &, |, ^ + * Boolean operator code generation Optimized operations are: <, <=, >, >=, &, |, ^ */ - public void generateOptimizedBoolean( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { - - if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) { - super.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - return; - } - switch ((bits & OperatorMASK) >> OperatorSHIFT) { - case LESS : - generateOptimizedLessThan( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - return; - case LESS_EQUAL : - generateOptimizedLessThanOrEqual( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - return; - case GREATER : - generateOptimizedGreaterThan( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - return; - case GREATER_EQUAL : - generateOptimizedGreaterThanOrEqual( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - return; - case AND : - generateOptimizedLogicalAnd( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - return; - case OR : - generateOptimizedLogicalOr( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - return; - case XOR : - generateOptimizedLogicalXor( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - return; - } - super.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - } - - /** - * Boolean generation for > - */ - public void generateOptimizedGreaterThan( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { - - int pc = codeStream.position; - int promotedTypeID = left.implicitConversion >> 4; - // both sides got promoted in the same way - if (promotedTypeID == T_int) { - // 0 > x - if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) { - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicitly falling through the FALSE case - codeStream.iflt(trueLabel); - } - } else { - if (trueLabel == null) { - // implicitly falling through the TRUE case - codeStream.ifge(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - // x > 0 - if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) { - left.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicitly falling through the FALSE case - codeStream.ifgt(trueLabel); - } - } else { - if (trueLabel == null) { - // implicitly falling through the TRUE case - codeStream.ifle(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } - // default comparison - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicit falling through the FALSE case - switch (promotedTypeID) { - case T_int : - codeStream.if_icmpgt(trueLabel); - break; - case T_float : - codeStream.fcmpl(); - codeStream.ifgt(trueLabel); - break; - case T_long : - codeStream.lcmp(); - codeStream.ifgt(trueLabel); - break; - case T_double : - codeStream.dcmpl(); - codeStream.ifgt(trueLabel); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } else { - if (trueLabel == null) { - // implicit falling through the TRUE case - switch (promotedTypeID) { - case T_int : - codeStream.if_icmple(falseLabel); - break; - case T_float : - codeStream.fcmpl(); - codeStream.ifle(falseLabel); - break; - case T_long : - codeStream.lcmp(); - codeStream.ifle(falseLabel); - break; - case T_double : - codeStream.dcmpl(); - codeStream.ifle(falseLabel); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - } - + // public void generateOptimizedBoolean( + // BlockScope currentScope, + // CodeStream codeStream, + // Label trueLabel, + // Label falseLabel, + // boolean valueRequired) { + // + // if ((constant != Constant.NotAConstant) && (constant.typeID() == + // T_boolean)) { + // super.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // return; + // } + // switch ((bits & OperatorMASK) >> OperatorSHIFT) { + // case LESS : + // generateOptimizedLessThan( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // return; + // case LESS_EQUAL : + // generateOptimizedLessThanOrEqual( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // return; + // case GREATER : + // generateOptimizedGreaterThan( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // return; + // case GREATER_EQUAL : + // generateOptimizedGreaterThanOrEqual( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // return; + // case AND : + // generateOptimizedLogicalAnd( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // return; + // case OR : + // generateOptimizedLogicalOr( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // return; + // case XOR : + // generateOptimizedLogicalXor( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // return; + // } + // super.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // } + // + // /** + // * Boolean generation for > + // */ + // public void generateOptimizedGreaterThan( + // BlockScope currentScope, + // CodeStream codeStream, + // Label trueLabel, + // Label falseLabel, + // boolean valueRequired) { + // + // int promotedTypeID = left.implicitConversion >> 4; + // // both sides got promoted in the same way + // if (promotedTypeID == T_int) { + // // 0 > x + // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicitly falling through the FALSE case + // codeStream.iflt(trueLabel); + // } + // } else { + // if (trueLabel == null) { + // // implicitly falling through the TRUE case + // codeStream.ifge(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // // x > 0 + // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) + // { + // left.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicitly falling through the FALSE case + // codeStream.ifgt(trueLabel); + // } + // } else { + // if (trueLabel == null) { + // // implicitly falling through the TRUE case + // codeStream.ifle(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // } + // // default comparison + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // switch (promotedTypeID) { + // case T_int : + // codeStream.if_icmpgt(trueLabel); + // break; + // case T_float : + // codeStream.fcmpl(); + // codeStream.ifgt(trueLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.ifgt(trueLabel); + // break; + // case T_double : + // codeStream.dcmpl(); + // codeStream.ifgt(trueLabel); + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // } else { + // if (trueLabel == null) { + // // implicit falling through the TRUE case + // switch (promotedTypeID) { + // case T_int : + // codeStream.if_icmple(falseLabel); + // break; + // case T_float : + // codeStream.fcmpl(); + // codeStream.ifle(falseLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.ifle(falseLabel); + // break; + // case T_double : + // codeStream.dcmpl(); + // codeStream.ifle(falseLabel); + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // } /** * Boolean generation for >= */ - public void generateOptimizedGreaterThanOrEqual( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { + // public void generateOptimizedGreaterThanOrEqual( + // BlockScope currentScope, + // CodeStream codeStream, + // Label trueLabel, + // Label falseLabel, + // boolean valueRequired) { + // + // int promotedTypeID = left.implicitConversion >> 4; + // // both sides got promoted in the same way + // if (promotedTypeID == T_int) { + // // 0 >= x + // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicitly falling through the FALSE case + // codeStream.ifle(trueLabel); + // } + // } else { + // if (trueLabel == null) { + // // implicitly falling through the TRUE case + // codeStream.ifgt(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // // x >= 0 + // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) + // { + // left.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicitly falling through the FALSE case + // codeStream.ifge(trueLabel); + // } + // } else { + // if (trueLabel == null) { + // // implicitly falling through the TRUE case + // codeStream.iflt(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // } + // // default comparison + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // switch (promotedTypeID) { + // case T_int : + // codeStream.if_icmpge(trueLabel); + // break; + // case T_float : + // codeStream.fcmpl(); + // codeStream.ifge(trueLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.ifge(trueLabel); + // break; + // case T_double : + // codeStream.dcmpl(); + // codeStream.ifge(trueLabel); + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // } else { + // if (trueLabel == null) { + // // implicit falling through the TRUE case + // switch (promotedTypeID) { + // case T_int : + // codeStream.if_icmplt(falseLabel); + // break; + // case T_float : + // codeStream.fcmpl(); + // codeStream.iflt(falseLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.iflt(falseLabel); + // break; + // case T_double : + // codeStream.dcmpl(); + // codeStream.iflt(falseLabel); + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // } + // + // /** + // * Boolean generation for < + // */ + // public void generateOptimizedLessThan( + // BlockScope currentScope, + // CodeStream codeStream, + // Label trueLabel, + // Label falseLabel, + // boolean valueRequired) { + // + // int promotedTypeID = left.implicitConversion >> 4; + // // both sides got promoted in the same way + // if (promotedTypeID == T_int) { + // // 0 < x + // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicitly falling through the FALSE case + // codeStream.ifgt(trueLabel); + // } + // } else { + // if (trueLabel == null) { + // // implicitly falling through the TRUE case + // codeStream.ifle(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // // x < 0 + // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) + // { + // left.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicitly falling through the FALSE case + // codeStream.iflt(trueLabel); + // } + // } else { + // if (trueLabel == null) { + // // implicitly falling through the TRUE case + // codeStream.ifge(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // } + // // default comparison + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // switch (promotedTypeID) { + // case T_int : + // codeStream.if_icmplt(trueLabel); + // break; + // case T_float : + // codeStream.fcmpg(); + // codeStream.iflt(trueLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.iflt(trueLabel); + // break; + // case T_double : + // codeStream.dcmpg(); + // codeStream.iflt(trueLabel); + // } + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // } else { + // if (trueLabel == null) { + // // implicit falling through the TRUE case + // switch (promotedTypeID) { + // case T_int : + // codeStream.if_icmpge(falseLabel); + // break; + // case T_float : + // codeStream.fcmpg(); + // codeStream.ifge(falseLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.ifge(falseLabel); + // break; + // case T_double : + // codeStream.dcmpg(); + // codeStream.ifge(falseLabel); + // } + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // } + // + // /** + // * Boolean generation for <= + // */ + // public void generateOptimizedLessThanOrEqual( + // BlockScope currentScope, + // CodeStream codeStream, + // Label trueLabel, + // Label falseLabel, + // boolean valueRequired) { + // + // int promotedTypeID = left.implicitConversion >> 4; + // // both sides got promoted in the same way + // if (promotedTypeID == T_int) { + // // 0 <= x + // if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) { + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicitly falling through the FALSE case + // codeStream.ifge(trueLabel); + // } + // } else { + // if (trueLabel == null) { + // // implicitly falling through the TRUE case + // codeStream.iflt(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // // x <= 0 + // if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) + // { + // left.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicitly falling through the FALSE case + // codeStream.ifle(trueLabel); + // } + // } else { + // if (trueLabel == null) { + // // implicitly falling through the TRUE case + // codeStream.ifgt(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // } + // // default comparison + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // switch (promotedTypeID) { + // case T_int : + // codeStream.if_icmple(trueLabel); + // break; + // case T_float : + // codeStream.fcmpg(); + // codeStream.ifle(trueLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.ifle(trueLabel); + // break; + // case T_double : + // codeStream.dcmpg(); + // codeStream.ifle(trueLabel); + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } + // } else { + // if (trueLabel == null) { + // // implicit falling through the TRUE case + // switch (promotedTypeID) { + // case T_int : + // codeStream.if_icmpgt(falseLabel); + // break; + // case T_float : + // codeStream.fcmpg(); + // codeStream.ifgt(falseLabel); + // break; + // case T_long : + // codeStream.lcmp(); + // codeStream.ifgt(falseLabel); + // break; + // case T_double : + // codeStream.dcmpg(); + // codeStream.ifgt(falseLabel); + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // return; + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // } + // + // /** + // * Boolean generation for & + // */ + // public void generateOptimizedLogicalAnd( + // BlockScope currentScope, + // CodeStream codeStream, + // Label trueLabel, + // Label falseLabel, + // boolean valueRequired) { + // + // Constant condConst; + // if ((left.implicitConversion & 0xF) == T_boolean) { + // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) { + // if (condConst.booleanValue() == true) { + // // & x + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // if ((bits & OnlyValueRequiredMASK) != 0) { + // right.generateCode(currentScope, codeStream, valueRequired); + // } else { + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // } + // } else { + // // & x + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // if (valueRequired) { + // if ((bits & OnlyValueRequiredMASK) != 0) { + // codeStream.iconst_0(); + // } else { + // if (falseLabel != null) { + // // implicit falling through the TRUE case + // codeStream.goto_(falseLabel); + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // } + // return; + // } + // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) { + // if (condConst.booleanValue() == true) { + // // x & + // if ((bits & OnlyValueRequiredMASK) != 0) { + // left.generateCode(currentScope, codeStream, valueRequired); + // } else { + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // } + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // } else { + // // x & + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // if (valueRequired) { + // if ((bits & OnlyValueRequiredMASK) != 0) { + // codeStream.iconst_0(); + // } else { + // if (falseLabel != null) { + // // implicit falling through the TRUE case + // codeStream.goto_(falseLabel); + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // } + // return; + // } + // } + // // default case + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // codeStream.iand(); + // if ((bits & OnlyValueRequiredMASK) == 0) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // codeStream.ifne(trueLabel); + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // codeStream.ifeq(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // } + // + // /** + // * Boolean generation for | + // */ + // public void generateOptimizedLogicalOr( + // BlockScope currentScope, + // CodeStream codeStream, + // Label trueLabel, + // Label falseLabel, + // boolean valueRequired) { + // + // Constant condConst; + // if ((left.implicitConversion & 0xF) == T_boolean) { + // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) { + // if (condConst.booleanValue() == true) { + // // | x + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // if (valueRequired) { + // if ((bits & OnlyValueRequiredMASK) != 0) { + // codeStream.iconst_1(); + // } else { + // if (trueLabel != null) { + // codeStream.goto_(trueLabel); + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // } else { + // // | x + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // if ((bits & OnlyValueRequiredMASK) != 0) { + // right.generateCode(currentScope, codeStream, valueRequired); + // } else { + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // } + // } + // return; + // } + // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) { + // if (condConst.booleanValue() == true) { + // // x | + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // if (valueRequired) { + // if ((bits & OnlyValueRequiredMASK) != 0) { + // codeStream.iconst_1(); + // } else { + // if (trueLabel != null) { + // codeStream.goto_(trueLabel); + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // } else { + // // x | + // if ((bits & OnlyValueRequiredMASK) != 0) { + // left.generateCode(currentScope, codeStream, valueRequired); + // } else { + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // } + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // } + // return; + // } + // } + // // default case + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // codeStream.ior(); + // if ((bits & OnlyValueRequiredMASK) == 0) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // codeStream.ifne(trueLabel); + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // codeStream.ifeq(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // } + // + // /** + // * Boolean generation for ^ + // */ + // public void generateOptimizedLogicalXor( + // BlockScope currentScope, + // CodeStream codeStream, + // Label trueLabel, + // Label falseLabel, + // boolean valueRequired) { + // + // Constant condConst; + // if ((left.implicitConversion & 0xF) == T_boolean) { + // if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) { + // if (condConst.booleanValue() == true) { + // // ^ x + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // falseLabel, + // trueLabel, + // valueRequired); + // } else { + // // ^ x + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // if ((bits & OnlyValueRequiredMASK) != 0) { + // right.generateCode(currentScope, codeStream, valueRequired); + // } else { + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // } + // } + // return; + // } + // if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) { + // if (condConst.booleanValue() == true) { + // // x ^ + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // falseLabel, + // trueLabel, + // valueRequired); + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // } else { + // // x ^ + // if ((bits & OnlyValueRequiredMASK) != 0) { + // left.generateCode(currentScope, codeStream, valueRequired); + // } else { + // left.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // valueRequired); + // } + // right.generateOptimizedBoolean( + // currentScope, + // codeStream, + // trueLabel, + // falseLabel, + // false); + // } + // return; + // } + // } + // // default case + // left.generateCode(currentScope, codeStream, valueRequired); + // right.generateCode(currentScope, codeStream, valueRequired); + // if (valueRequired) { + // codeStream.ixor(); + // if ((bits & OnlyValueRequiredMASK) == 0) { + // if (falseLabel == null) { + // if (trueLabel != null) { + // // implicit falling through the FALSE case + // codeStream.ifne(trueLabel); + // } + // } else { + // // implicit falling through the TRUE case + // if (trueLabel == null) { + // codeStream.ifeq(falseLabel); + // } else { + // // no implicit fall through TRUE/FALSE --> should never occur + // } + // } + // } + // } + // // reposition the endPC + // codeStream.updateLastRecordedEndPC(codeStream.position); + // } + // + // public void generateOptimizedStringBuffer( + // BlockScope blockScope, + // CodeStream codeStream, + // int typeID) { + // + // /* In the case trying to make a string concatenation, there is no need to + // create a new + // * string buffer, thus use a lower-level API for code generation involving + // only the + // * appending of arguments to the existing StringBuffer + // */ + // + // if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) + // && ((bits & ReturnTypeIDMASK) == T_String)) { + // if (constant != NotAConstant) { + // codeStream.generateConstant(constant, implicitConversion); + // codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF); + // } else { + // int pc = codeStream.position; + // left.generateOptimizedStringBuffer( + // blockScope, + // codeStream, + // left.implicitConversion & 0xF); + // codeStream.recordPositionsFrom(pc, left.sourceStart); + // pc = codeStream.position; + // right.generateOptimizedStringBuffer( + // blockScope, + // codeStream, + // right.implicitConversion & 0xF); + // codeStream.recordPositionsFrom(pc, right.sourceStart); + // } + // } else { + // super.generateOptimizedStringBuffer(blockScope, codeStream, typeID); + // } + // } + // + // public void generateOptimizedStringBufferCreation( + // BlockScope blockScope, + // CodeStream codeStream, + // int typeID) { + // + // /* In the case trying to make a string concatenation, there is no need to + // create a new + // * string buffer, thus use a lower-level API for code generation involving + // only the + // * appending of arguments to the existing StringBuffer + // */ + // + // if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) + // && ((bits & ReturnTypeIDMASK) == T_String)) { + // if (constant != NotAConstant) { + // codeStream.newStringBuffer(); // new: java.lang.StringBuffer + // codeStream.dup(); + // codeStream.ldc(constant.stringValue()); + // codeStream.invokeStringBufferStringConstructor(); + // // invokespecial: java.lang.StringBuffer.(Ljava.lang.String;)V + // } else { + // int pc = codeStream.position; + // left.generateOptimizedStringBufferCreation( + // blockScope, + // codeStream, + // left.implicitConversion & 0xF); + // codeStream.recordPositionsFrom(pc, left.sourceStart); + // pc = codeStream.position; + // right.generateOptimizedStringBuffer( + // blockScope, + // codeStream, + // right.implicitConversion & 0xF); + // codeStream.recordPositionsFrom(pc, right.sourceStart); + // } + // } else { + // super.generateOptimizedStringBufferCreation(blockScope, codeStream, + // typeID); + // } + // } + // + // public boolean isCompactableOperation() { + // + // return true; + // } + // + // public void optimizedBooleanConstant(int leftId, int operator, int + // rightId) { + // + // switch (operator) { + // case AND : + // if ((leftId != T_boolean) || (rightId != T_boolean)) + // return; + // case AND_AND : + // Constant cst; + // if ((cst = left.optimizedBooleanConstant()) != NotAConstant) { + // if (cst.booleanValue() == false) { // left is equivalent to false + // optimizedBooleanConstant = cst; // constant(false) + // return; + // } else { //left is equivalent to true + // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) { + // optimizedBooleanConstant = cst; + // // the conditional result is equivalent to the right conditional value + // } + // return; + // } + // } + // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) { + // if (cst.booleanValue() == false) { // right is equivalent to false + // optimizedBooleanConstant = cst; // constant(false) + // } + // } + // return; + // case OR : + // if ((leftId != T_boolean) || (rightId != T_boolean)) + // return; + // case OR_OR : + // if ((cst = left.optimizedBooleanConstant()) != NotAConstant) { + // if (cst.booleanValue() == true) { // left is equivalent to true + // optimizedBooleanConstant = cst; // constant(true) + // return; + // } else { //left is equivalent to false + // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) { + // optimizedBooleanConstant = cst; + // } + // return; + // } + // } + // if ((cst = right.optimizedBooleanConstant()) != NotAConstant) { + // if (cst.booleanValue() == true) { // right is equivalent to true + // optimizedBooleanConstant = cst; // constant(true) + // } + // } + // } + // } + public StringBuffer printExpressionNoParenthesis(int indent, + StringBuffer output) { - int pc = codeStream.position; - int promotedTypeID = left.implicitConversion >> 4; - // both sides got promoted in the same way - if (promotedTypeID == T_int) { - // 0 >= x - if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) { - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicitly falling through the FALSE case - codeStream.ifle(trueLabel); - } - } else { - if (trueLabel == null) { - // implicitly falling through the TRUE case - codeStream.ifgt(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - // x >= 0 - if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) { - left.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicitly falling through the FALSE case - codeStream.ifge(trueLabel); - } - } else { - if (trueLabel == null) { - // implicitly falling through the TRUE case - codeStream.iflt(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } - // default comparison - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicit falling through the FALSE case - switch (promotedTypeID) { - case T_int : - codeStream.if_icmpge(trueLabel); - break; - case T_float : - codeStream.fcmpl(); - codeStream.ifge(trueLabel); - break; - case T_long : - codeStream.lcmp(); - codeStream.ifge(trueLabel); - break; - case T_double : - codeStream.dcmpl(); - codeStream.ifge(trueLabel); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } else { - if (trueLabel == null) { - // implicit falling through the TRUE case - switch (promotedTypeID) { - case T_int : - codeStream.if_icmplt(falseLabel); - break; - case T_float : - codeStream.fcmpl(); - codeStream.iflt(falseLabel); - break; - case T_long : - codeStream.lcmp(); - codeStream.iflt(falseLabel); - break; - case T_double : - codeStream.dcmpl(); - codeStream.iflt(falseLabel); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } + left.printExpression(indent, output).append(' ').append( + operatorToString()).append(' '); + return right.printExpression(0, output); } - /** - * Boolean generation for < - */ - public void generateOptimizedLessThan( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { - - int pc = codeStream.position; - int promotedTypeID = left.implicitConversion >> 4; - // both sides got promoted in the same way - if (promotedTypeID == T_int) { - // 0 < x - if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) { - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicitly falling through the FALSE case - codeStream.ifgt(trueLabel); - } - } else { - if (trueLabel == null) { - // implicitly falling through the TRUE case - codeStream.ifle(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - // x < 0 - if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) { - left.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicitly falling through the FALSE case - codeStream.iflt(trueLabel); - } - } else { - if (trueLabel == null) { - // implicitly falling through the TRUE case - codeStream.ifge(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } - // default comparison - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicit falling through the FALSE case - switch (promotedTypeID) { - case T_int : - codeStream.if_icmplt(trueLabel); - break; - case T_float : - codeStream.fcmpg(); - codeStream.iflt(trueLabel); - break; - case T_long : - codeStream.lcmp(); - codeStream.iflt(trueLabel); - break; - case T_double : - codeStream.dcmpg(); - codeStream.iflt(trueLabel); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } else { - if (trueLabel == null) { - // implicit falling through the TRUE case - switch (promotedTypeID) { - case T_int : - codeStream.if_icmpge(falseLabel); - break; - case T_float : - codeStream.fcmpg(); - codeStream.ifge(falseLabel); - break; - case T_long : - codeStream.lcmp(); - codeStream.ifge(falseLabel); - break; - case T_double : - codeStream.dcmpg(); - codeStream.ifge(falseLabel); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - } - - /** - * Boolean generation for <= - */ - public void generateOptimizedLessThanOrEqual( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { - - int pc = codeStream.position; - int promotedTypeID = left.implicitConversion >> 4; - // both sides got promoted in the same way - if (promotedTypeID == T_int) { - // 0 <= x - if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) { - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicitly falling through the FALSE case - codeStream.ifge(trueLabel); - } - } else { - if (trueLabel == null) { - // implicitly falling through the TRUE case - codeStream.iflt(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - // x <= 0 - if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) { - left.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicitly falling through the FALSE case - codeStream.ifle(trueLabel); - } - } else { - if (trueLabel == null) { - // implicitly falling through the TRUE case - codeStream.ifgt(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } - // default comparison - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicit falling through the FALSE case - switch (promotedTypeID) { - case T_int : - codeStream.if_icmple(trueLabel); - break; - case T_float : - codeStream.fcmpg(); - codeStream.ifle(trueLabel); - break; - case T_long : - codeStream.lcmp(); - codeStream.ifle(trueLabel); - break; - case T_double : - codeStream.dcmpg(); - codeStream.ifle(trueLabel); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } else { - if (trueLabel == null) { - // implicit falling through the TRUE case - switch (promotedTypeID) { - case T_int : - codeStream.if_icmpgt(falseLabel); - break; - case T_float : - codeStream.fcmpg(); - codeStream.ifgt(falseLabel); - break; - case T_long : - codeStream.lcmp(); - codeStream.ifgt(falseLabel); - break; - case T_double : - codeStream.dcmpg(); - codeStream.ifgt(falseLabel); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - } - - /** - * Boolean generation for & - */ - public void generateOptimizedLogicalAnd( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { - - int pc = codeStream.position; - Constant condConst; - if ((left.implicitConversion & 0xF) == T_boolean) { - if ((condConst = left.conditionalConstant()) != NotAConstant) { - if (condConst.booleanValue() == true) { - // & x - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - if ((bits & OnlyValueRequiredMASK) != 0) { - right.generateCode(currentScope, codeStream, valueRequired); - } else { - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - } - } else { - // & x - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - if (valueRequired) { - if ((bits & OnlyValueRequiredMASK) != 0) { - codeStream.iconst_0(); - } else { - if (falseLabel != null) { - // implicit falling through the TRUE case - codeStream.goto_(falseLabel); - } - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - if ((condConst = right.conditionalConstant()) != NotAConstant) { - if (condConst.booleanValue() == true) { - // x & - if ((bits & OnlyValueRequiredMASK) != 0) { - left.generateCode(currentScope, codeStream, valueRequired); - } else { - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - } - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - } else { - // x & - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - if (valueRequired) { - if ((bits & OnlyValueRequiredMASK) != 0) { - codeStream.iconst_0(); - } else { - if (falseLabel != null) { - // implicit falling through the TRUE case - codeStream.goto_(falseLabel); - } - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } - // default case - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - codeStream.iand(); - if ((bits & OnlyValueRequiredMASK) == 0) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicit falling through the FALSE case - codeStream.ifne(trueLabel); - } - } else { - // implicit falling through the TRUE case - if (trueLabel == null) { - codeStream.ifeq(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - } - - /** - * Boolean generation for | - */ - public void generateOptimizedLogicalOr( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { - - int pc = codeStream.position; - Constant condConst; - if ((left.implicitConversion & 0xF) == T_boolean) { - if ((condConst = left.conditionalConstant()) != NotAConstant) { - if (condConst.booleanValue() == true) { - // | x - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - if (valueRequired) { - if ((bits & OnlyValueRequiredMASK) != 0) { - codeStream.iconst_1(); - } else { - if (trueLabel != null) { - codeStream.goto_(trueLabel); - } - } - } - } else { - // | x - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - if ((bits & OnlyValueRequiredMASK) != 0) { - right.generateCode(currentScope, codeStream, valueRequired); - } else { - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - if ((condConst = right.conditionalConstant()) != NotAConstant) { - if (condConst.booleanValue() == true) { - // x | - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - if (valueRequired) { - if ((bits & OnlyValueRequiredMASK) != 0) { - codeStream.iconst_1(); - } else { - if (trueLabel != null) { - codeStream.goto_(trueLabel); - } - } - } - } else { - // x | - if ((bits & OnlyValueRequiredMASK) != 0) { - left.generateCode(currentScope, codeStream, valueRequired); - } else { - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - } - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } - // default case - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - codeStream.ior(); - if ((bits & OnlyValueRequiredMASK) == 0) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicit falling through the FALSE case - codeStream.ifne(trueLabel); - } - } else { - // implicit falling through the TRUE case - if (trueLabel == null) { - codeStream.ifeq(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - } - - /** - * Boolean generation for ^ - */ - public void generateOptimizedLogicalXor( - BlockScope currentScope, - CodeStream codeStream, - Label trueLabel, - Label falseLabel, - boolean valueRequired) { - - int pc = codeStream.position; - Constant condConst; - if ((left.implicitConversion & 0xF) == T_boolean) { - if ((condConst = left.conditionalConstant()) != NotAConstant) { - if (condConst.booleanValue() == true) { - // ^ x - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - right.generateOptimizedBoolean( - currentScope, - codeStream, - falseLabel, - trueLabel, - valueRequired); - } else { - // ^ x - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - if ((bits & OnlyValueRequiredMASK) != 0) { - right.generateCode(currentScope, codeStream, valueRequired); - } else { - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - if ((condConst = right.conditionalConstant()) != NotAConstant) { - if (condConst.booleanValue() == true) { - // x ^ - left.generateOptimizedBoolean( - currentScope, - codeStream, - falseLabel, - trueLabel, - valueRequired); - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - } else { - // x ^ - if ((bits & OnlyValueRequiredMASK) != 0) { - left.generateCode(currentScope, codeStream, valueRequired); - } else { - left.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - valueRequired); - } - right.generateOptimizedBoolean( - currentScope, - codeStream, - trueLabel, - falseLabel, - false); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - return; - } - } - // default case - left.generateCode(currentScope, codeStream, valueRequired); - right.generateCode(currentScope, codeStream, valueRequired); - if (valueRequired) { - codeStream.ixor(); - if ((bits & OnlyValueRequiredMASK) == 0) { - if (falseLabel == null) { - if (trueLabel != null) { - // implicit falling through the FALSE case - codeStream.ifne(trueLabel); - } - } else { - // implicit falling through the TRUE case - if (trueLabel == null) { - codeStream.ifeq(falseLabel); - } else { - // no implicit fall through TRUE/FALSE --> should never occur - } - } - } - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - } - - public void generateOptimizedStringBuffer( - BlockScope blockScope, - CodeStream codeStream, - int typeID) { - - /* In the case trying to make a string concatenation, there is no need to create a new - * string buffer, thus use a lower-level API for code generation involving only the - * appending of arguments to the existing StringBuffer - */ - - if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) - && ((bits & ReturnTypeIDMASK) == T_String)) { - if (constant != NotAConstant) { - codeStream.generateConstant(constant, implicitConversion); - codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF); - } else { - int pc = codeStream.position; - left.generateOptimizedStringBuffer( - blockScope, - codeStream, - left.implicitConversion & 0xF); - codeStream.recordPositionsFrom(pc, left.sourceStart); - pc = codeStream.position; - right.generateOptimizedStringBuffer( - blockScope, - codeStream, - right.implicitConversion & 0xF); - codeStream.recordPositionsFrom(pc, right.sourceStart); - } - } else { - super.generateOptimizedStringBuffer(blockScope, codeStream, typeID); - } - } - - public void generateOptimizedStringBufferCreation( - BlockScope blockScope, - CodeStream codeStream, - int typeID) { - - /* In the case trying to make a string concatenation, there is no need to create a new - * string buffer, thus use a lower-level API for code generation involving only the - * appending of arguments to the existing StringBuffer - */ - - if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) - && ((bits & ReturnTypeIDMASK) == T_String)) { - if (constant != NotAConstant) { - codeStream.newStringBuffer(); // new: java.lang.StringBuffer - codeStream.dup(); - codeStream.ldc(constant.stringValue()); - codeStream.invokeStringBufferStringConstructor(); - // invokespecial: java.lang.StringBuffer.(Ljava.lang.String;)V - } else { - int pc = codeStream.position; - left.generateOptimizedStringBufferCreation( - blockScope, - codeStream, - left.implicitConversion & 0xF); - codeStream.recordPositionsFrom(pc, left.sourceStart); - pc = codeStream.position; - right.generateOptimizedStringBuffer( - blockScope, - codeStream, - right.implicitConversion & 0xF); - codeStream.recordPositionsFrom(pc, right.sourceStart); - } - } else { - super.generateOptimizedStringBufferCreation(blockScope, codeStream, typeID); - } - } - - public boolean isCompactableOperation() { - - return true; - } - - public void optimizedBooleanConstant(int leftId, int operator, int rightId) { - - switch (operator) { - case AND : - if ((leftId != T_boolean) || (rightId != T_boolean)) - return; - case AND_AND : - Constant cst; - if ((cst = left.conditionalConstant()) != NotAConstant) { - if (cst.booleanValue() == false) { // left is equivalent to false - optimizedBooleanConstant = cst; // constant(false) - return; - } else { //left is equivalent to true - if ((cst = right.conditionalConstant()) != NotAConstant) { - optimizedBooleanConstant = cst; - // the conditional result is equivalent to the right conditional value - } - return; - } - } - if ((cst = right.conditionalConstant()) != NotAConstant) { - if (cst.booleanValue() == false) { // right is equivalent to false - optimizedBooleanConstant = cst; // constant(false) - } - } - return; - case OR : - if ((leftId != T_boolean) || (rightId != T_boolean)) - return; - case OR_OR : - if ((cst = left.conditionalConstant()) != NotAConstant) { - if (cst.booleanValue() == true) { // left is equivalent to true - optimizedBooleanConstant = cst; // constant(true) - return; - } else { //left is equivalent to false - if ((cst = right.conditionalConstant()) != NotAConstant) { - optimizedBooleanConstant = cst; - } - return; - } - } - if ((cst = right.conditionalConstant()) != NotAConstant) { - if (cst.booleanValue() == true) { // right is equivalent to true - optimizedBooleanConstant = cst; // constant(true) - } - } - } - } - public TypeBinding resolveType(BlockScope scope) { // use the id of the type to navigate into the table @@ -1643,8 +1669,8 @@ public class BinaryExpression extends OperatorExpression { } int leftId = leftTb.id; int rightId = rightTb.id; - if (leftId > 15 - || rightId > 15) { // must convert String + Object || Object + String + if (leftId > 15 || rightId > 15) { // must convert String + Object || + // Object + String if (leftId == T_String) { rightId = T_Object; } else if (rightId == T_String) { @@ -1657,82 +1683,85 @@ public class BinaryExpression extends OperatorExpression { } if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) { if (leftId == T_String - && rightTb.isArrayType() - && ((ArrayBinding) rightTb).elementsType(scope) == CharBinding) - scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression( - right); - else if ( - rightId == T_String + && rightTb.isArrayType() + && ((ArrayBinding) rightTb).elementsType(scope) == CharBinding) + scope + .problemReporter() + .signalNoImplicitStringConversionForCharArrayExpression( + right); + else if (rightId == T_String && leftTb.isArrayType() && ((ArrayBinding) leftTb).elementsType(scope) == CharBinding) - scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression( - left); + scope + .problemReporter() + .signalNoImplicitStringConversionForCharArrayExpression( + left); } // the code is an int - // (cast) left Op (cast) rigth --> result - // 0000 0000 0000 0000 0000 - // <<16 <<12 <<8 <<4 <<0 + // (cast) left Op (cast) rigth --> result + // 0000 0000 0000 0000 0000 + // <<16 <<12 <<8 <<4 <<0 // Don't test for result = 0. If it is zero, some more work is done. - // On the one hand when it is not zero (correct code) we avoid doing the test - int result = - ResolveTypeTables[(bits & OperatorMASK) >> OperatorSHIFT][(leftId << 4) + // On the one hand when it is not zero (correct code) we avoid doing the + // test + int result = ResolveTypeTables[(bits & OperatorMASK) >> OperatorSHIFT][(leftId << 4) + rightId]; left.implicitConversion = result >>> 12; right.implicitConversion = (result >>> 4) & 0x000FF; bits |= result & 0xF; switch (result & 0xF) { // record the current ReturnTypeID - // only switch on possible result type..... - case T_boolean : - this.typeBinding = BooleanBinding; - break; - case T_byte : - this.typeBinding = ByteBinding; - break; - case T_char : - this.typeBinding = CharBinding; - break; - case T_double : - this.typeBinding = DoubleBinding; - break; - case T_float : - this.typeBinding = FloatBinding; - break; - case T_int : - this.typeBinding = IntBinding; - break; - case T_long : - this.typeBinding = LongBinding; - break; - case T_String : - this.typeBinding = scope.getJavaLangString(); - break; - default : //error........ - constant = Constant.NotAConstant; - scope.problemReporter().invalidOperator(this, leftTb, rightTb); - return null; + // only switch on possible result type..... + case T_boolean: + this.resolvedType = BooleanBinding; + break; + case T_byte: + this.resolvedType = ByteBinding; + break; + case T_char: + this.resolvedType = CharBinding; + break; + case T_double: + this.resolvedType = DoubleBinding; + break; + case T_float: + this.resolvedType = FloatBinding; + break; + case T_int: + this.resolvedType = IntBinding; + break; + case T_long: + this.resolvedType = LongBinding; + break; + case T_String: + this.resolvedType = scope.getJavaLangString(); + break; + default: // error........ + constant = Constant.NotAConstant; + scope.problemReporter().invalidOperator(this, leftTb, rightTb); + return null; } // compute the constant when valid computeConstant(scope, leftId, rightId); - return this.typeBinding; + return this.resolvedType; } - + public String toStringExpressionNoParenthesis() { return left.toStringExpression() + " " + //$NON-NLS-1$ - operatorToString() + " " + //$NON-NLS-1$ - right.toStringExpression(); + operatorToString() + " " + //$NON-NLS-1$ + right.toStringExpression(); } - public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) { - + public void traverse(ASTVisitor visitor, BlockScope scope) { + if (visitor.visit(this, scope)) { left.traverse(visitor, scope); right.traverse(visitor, scope); } visitor.endVisit(this, scope); } -} \ No newline at end of file +}