From a25ae3d68d84d2b89907f998df6a396549589da5 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Tue, 8 Jul 2008 14:35:21 +0000 Subject: [PATCH] Move out some methods. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53234 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 308 +++++++++++++++++++-------------------- 1 file changed, 149 insertions(+), 159 deletions(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 5307a56fab..f2b32c6fa4 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -107,186 +107,176 @@ public: APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - APValue VisitBinaryOperator(const BinaryOperator *E) { - // The LHS of a constant expr is always evaluated and needed. - llvm::APSInt Result(32); - if (!Evaluate(E->getLHS(), Result, Ctx)) - return APValue(); + APValue VisitBinaryOperator(const BinaryOperator *E); + APValue VisitUnaryOperator(const UnaryOperator *E); - llvm::APSInt RHS(32); - if (!Evaluate(E->getRHS(), RHS, Ctx)) + APValue HandleCast(const Expr* SubExpr, QualType DestType); +}; + +APValue IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { + // The LHS of a constant expr is always evaluated and needed. + llvm::APSInt Result(32); + if (!Evaluate(E->getLHS(), Result, Ctx)) + return APValue(); + + llvm::APSInt RHS(32); + if (!Evaluate(E->getRHS(), RHS, Ctx)) + return APValue(); + + switch (E->getOpcode()) { + default: + return APValue(); + case BinaryOperator::Mul: + Result *= RHS; + break; + case BinaryOperator::Div: + if (RHS == 0) + return APValue(); + Result /= RHS; + break; + case BinaryOperator::Rem: + if (RHS == 0) return APValue(); + Result %= RHS; + break; + case BinaryOperator::Add: Result += RHS; break; + case BinaryOperator::Sub: Result -= RHS; break; + case BinaryOperator::Shl: + Result <<= + static_cast(RHS.getLimitedValue(Result.getBitWidth()-1)); + break; + case BinaryOperator::Shr: + Result >>= + static_cast(RHS.getLimitedValue(Result.getBitWidth()-1)); + break; + case BinaryOperator::LT: Result = Result < RHS; break; + case BinaryOperator::GT: Result = Result > RHS; break; + case BinaryOperator::LE: Result = Result <= RHS; break; + case BinaryOperator::GE: Result = Result >= RHS; break; + case BinaryOperator::EQ: Result = Result == RHS; break; + case BinaryOperator::NE: Result = Result != RHS; break; + case BinaryOperator::And: Result &= RHS; break; + case BinaryOperator::Xor: Result ^= RHS; break; + case BinaryOperator::Or: Result |= RHS; break; + case BinaryOperator::Comma: + // C99 6.6p3: "shall not contain assignment, ..., or comma operators, + // *except* when they are contained within a subexpression that is not + // evaluated". Note that Assignment can never happen due to constraints + // on the LHS subexpr, so we don't need to check it here. + // FIXME: Need to come up with an efficient way to deal with the C99 + // rules on evaluation while still evaluating this. Maybe a + // "evaluated comma" out parameter? + return APValue(); + } + + Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); + + return APValue(Result); +} + +APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { + llvm::APSInt Result(32); + + if (E->isOffsetOfOp()) + Result = E->evaluateOffsetOf(Ctx); + else if (E->isSizeOfAlignOfOp()) { + // Return the result in the right width. + Result.zextOrTrunc(static_cast(Ctx.getTypeSize(E->getType()))); + + // sizeof(void) and __alignof__(void) = 1 as a gcc extension. + if (E->getSubExpr()->getType()->isVoidType()) + Result = 1; + + // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. + if (!E->getSubExpr()->getType()->isConstantSizeType()) { + // FIXME: Should we attempt to evaluate this? + return APValue(); + } + + // Get information about the size or align. + if (E->getSubExpr()->getType()->isFunctionType()) { + // GCC extension: sizeof(function) = 1. + // FIXME: AlignOf shouldn't be unconditionally 4! + Result = E->getOpcode() == UnaryOperator::AlignOf ? 4 : 1; + } else { + unsigned CharSize = Ctx.Target.getCharWidth(); + if (E->getOpcode() == UnaryOperator::AlignOf) + Result = Ctx.getTypeAlign(E->getSubExpr()->getType()) / CharSize; + else + Result = Ctx.getTypeSize(E->getSubExpr()->getType()) / CharSize; + } + } else { + // Get the operand value. If this is sizeof/alignof, do not evalute the + // operand. This affects C99 6.6p3. + if (!Evaluate(E->getSubExpr(), Result, Ctx)) + return APValue(); + switch (E->getOpcode()) { + // Address, indirect, pre/post inc/dec, etc are not valid constant exprs. + // See C99 6.6p3. default: return APValue(); - case BinaryOperator::Mul: - Result *= RHS; + case UnaryOperator::Extension: + assert(0 && "Handle UnaryOperator::Extension"); + return APValue(); + case UnaryOperator::LNot: { + bool Val = Result == 0; + uint32_t typeSize = Ctx.getTypeSize(E->getType()); + Result.zextOrTrunc(typeSize); + Result = Val; break; - case BinaryOperator::Div: - if (RHS == 0) - return APValue(); - Result /= RHS; - break; - case BinaryOperator::Rem: - if (RHS == 0) - return APValue(); - Result %= RHS; + } + case UnaryOperator::Plus: break; - case BinaryOperator::Add: Result += RHS; break; - case BinaryOperator::Sub: Result -= RHS; break; - case BinaryOperator::Shl: - Result <<= - static_cast(RHS.getLimitedValue(Result.getBitWidth()-1)); + case UnaryOperator::Minus: + Result = -Result; break; - case BinaryOperator::Shr: - Result >>= - static_cast(RHS.getLimitedValue(Result.getBitWidth()-1)); + case UnaryOperator::Not: + Result = ~Result; break; - case BinaryOperator::LT: Result = Result < RHS; break; - case BinaryOperator::GT: Result = Result > RHS; break; - case BinaryOperator::LE: Result = Result <= RHS; break; - case BinaryOperator::GE: Result = Result >= RHS; break; - case BinaryOperator::EQ: Result = Result == RHS; break; - case BinaryOperator::NE: Result = Result != RHS; break; - case BinaryOperator::And: Result &= RHS; break; - case BinaryOperator::Xor: Result ^= RHS; break; - case BinaryOperator::Or: Result |= RHS; break; - - case BinaryOperator::Comma: - // C99 6.6p3: "shall not contain assignment, ..., or comma operators, - // *except* when they are contained within a subexpression that is not - // evaluated". Note that Assignment can never happen due to constraints - // on the LHS subexpr, so we don't need to check it here. - // FIXME: Need to come up with an efficient way to deal with the C99 - // rules on evaluation while still evaluating this. Maybe a - // "evaluated comma" out parameter? - return APValue(); } - - Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - - return APValue(Result); } - APValue VisitUnaryOperator(const UnaryOperator *E) { - llvm::APSInt Result(32); - - if (E->isOffsetOfOp()) - Result = E->evaluateOffsetOf(Ctx); - else if (E->isSizeOfAlignOfOp()) { - // Return the result in the right width. - Result.zextOrTrunc(static_cast(Ctx.getTypeSize(E->getType()))); - - // sizeof(void) and __alignof__(void) = 1 as a gcc extension. - if (E->getSubExpr()->getType()->isVoidType()) - Result = 1; - - // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2. - if (!E->getSubExpr()->getType()->isConstantSizeType()) { - // FIXME: Should we attempt to evaluate this? - return APValue(); - } - - // Get information about the size or align. - if (E->getSubExpr()->getType()->isFunctionType()) { - // GCC extension: sizeof(function) = 1. - // FIXME: AlignOf shouldn't be unconditionally 4! - Result = E->getOpcode() == UnaryOperator::AlignOf ? 4 : 1; - } else { - unsigned CharSize = Ctx.Target.getCharWidth(); - if (E->getOpcode() == UnaryOperator::AlignOf) - Result = Ctx.getTypeAlign(E->getSubExpr()->getType()) / CharSize; - else - Result = Ctx.getTypeSize(E->getSubExpr()->getType()) / CharSize; - } - } else { - // Get the operand value. If this is sizeof/alignof, do not evalute the - // operand. This affects C99 6.6p3. - if (!Evaluate(E->getSubExpr(), Result, Ctx)) - return APValue(); + Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); + return APValue(Result); +} + +APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) { + llvm::APSInt Result(32); - switch (E->getOpcode()) { - // Address, indirect, pre/post inc/dec, etc are not valid constant exprs. - // See C99 6.6p3. - default: - return APValue(); - case UnaryOperator::Extension: - assert(0 && "Handle UnaryOperator::Extension"); - return APValue(); - case UnaryOperator::LNot: { - bool Val = Result == 0; - uint32_t typeSize = Ctx.getTypeSize(E->getType()); - Result.zextOrTrunc(typeSize); - Result = Val; - break; - } - case UnaryOperator::Plus: - break; - case UnaryOperator::Minus: - Result = -Result; - break; - case UnaryOperator::Not: - Result = ~Result; - break; - } - } + uint32_t DestWidth = static_cast(Ctx.getTypeSize(DestType)); - Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - return APValue(Result); - } + // Handle simple integer->integer casts. + if (SubExpr->getType()->isIntegerType()) { + if (!Evaluate(SubExpr, Result, Ctx)) + return APValue(); - APValue HandleCast(const Expr* SubExpr, QualType DestType) { - llvm::APSInt Result(32); - - uint32_t DestWidth = static_cast(Ctx.getTypeSize(DestType)); - - // Handle simple integer->integer casts. - if (SubExpr->getType()->isIntegerType()) { - if (!Evaluate(SubExpr, Result, Ctx)) - return APValue(); - - // Figure out if this is a truncate, extend or noop cast. - // If the input is signed, do a sign extend, noop, or truncate. - if (DestType->isBooleanType()) { - // Conversion to bool compares against zero. - Result = Result != 0; - Result.zextOrTrunc(DestWidth); - } - else - Result.extOrTrunc(DestWidth); - } else if (SubExpr->getType()->isPointerType()) { - APValue LV; - if (!PointerExprEvaluator::Evaluate(SubExpr, LV, Ctx)) - return APValue(); - if (LV.getLValueBase()) - return APValue(); - - Result = llvm::APSInt(DestWidth, LV.getLValueOffset()); - } else { - assert(0 && "Unhandled cast!"); + // Figure out if this is a truncate, extend or noop cast. + // If the input is signed, do a sign extend, noop, or truncate. + if (DestType->isBooleanType()) { + // Conversion to bool compares against zero. + Result = Result != 0; + Result.zextOrTrunc(DestWidth); } + else + Result.extOrTrunc(DestWidth); + } else if (SubExpr->getType()->isPointerType()) { + APValue LV; + if (!PointerExprEvaluator::Evaluate(SubExpr, LV, Ctx)) + return APValue(); + if (LV.getLValueBase()) + return APValue(); - Result.setIsUnsigned(DestType->isUnsignedIntegerType()); - return APValue(Result); - } - - APValue VisitImplicitCastExpr(const ImplicitCastExpr *E) { - return HandleCast(E->getSubExpr(), E->getType()); - } - - APValue VisitCastExpr(const CastExpr *E) { - return HandleCast(E->getSubExpr(), E->getType()); + Result = llvm::APSInt(DestWidth, LV.getLValueOffset()); + } else { + assert(0 && "Unhandled cast!"); } - APValue VisitIntegerLiteral(const IntegerLiteral *E) { - llvm::APSInt Result(Ctx.getTypeSize(E->getType())); - - Result = E->getValue(); - return APValue(Result); - } + Result.setIsUnsigned(DestType->isUnsignedIntegerType()); + return APValue(Result); +} -}; } bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const -- 2.40.0