From: Chris Lattner Date: Fri, 11 Jul 2008 19:10:17 +0000 (+0000) Subject: make the new evaluator avoid conversions APValue<->APSInt in some cases. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b542afe02d317411d53b3541946f9f2a8f509a11;p=clang make the new evaluator avoid conversions APValue<->APSInt in some cases. Add some accessors to APValue. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53465 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index b89248b9fe..7007b665bc 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -92,30 +92,54 @@ public: bool isComplexFloat() const { return Kind == ComplexFloat; } bool isLValue() const { return Kind == LValue; } - const APSInt &getSInt() const { + APSInt &getSInt() { assert(isSInt() && "Invalid accessor"); - return *(const APSInt*)(const void*)Data; + return *(APSInt*)(void*)Data; } - const APFloat &getFloat() const { + const APSInt &getSInt() const { + return const_cast(this)->getSInt(); + } + + APFloat &getFloat() { assert(isFloat() && "Invalid accessor"); - return *(const APFloat*)(const void*)Data; + return *(APFloat*)(void*)Data; + } + const APFloat &getFloat() const { + return const_cast(this)->getFloat(); + } + + APSInt &getComplexSIntReal() { + assert(isComplexSInt() && "Invalid accessor"); + return ((ComplexAPSInt*)(void*)Data)->Real; } const APSInt &getComplexSIntReal() const { + return const_cast(this)->getComplexSIntReal(); + } + + APSInt &getComplexSIntImag() { assert(isComplexSInt() && "Invalid accessor"); - return ((const ComplexAPSInt*)(const void*)Data)->Real; + return ((ComplexAPSInt*)(void*)Data)->Imag; } const APSInt &getComplexSIntImag() const { - assert(isComplexSInt() && "Invalid accessor"); - return ((const ComplexAPSInt*)(const void*)Data)->Imag; + return const_cast(this)->getComplexSIntImag(); + } + + APFloat &getComplexFloatReal() { + assert(isComplexFloat() && "Invalid accessor"); + return ((ComplexAPFloat*)(void*)Data)->Real; } const APFloat &getComplexFloatReal() const { + return const_cast(this)->getComplexFloatReal(); + } + + APFloat &getComplexFloatImag() { assert(isComplexFloat() && "Invalid accessor"); - return ((const ComplexAPFloat*)(const void*)Data)->Real; + return ((ComplexAPFloat*)(void*)Data)->Imag; } const APFloat &getComplexFloatImag() const { - assert(isComplexFloat() && "Invalid accessor"); - return ((const ComplexAPFloat*)(const void*)Data)->Imag; + return const_cast(this)->getComplexFloatImag(); } + Expr* getLValueBase() const { assert(isLValue() && "Invalid accessor"); return ((const LV*)(const void*)Data)->Base; diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 6be72681e3..5826fab131 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1,4 +1,4 @@ -//===--- Expr.cpp - Expression Constant Evaluator -------------------------===// +//===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===// // // The LLVM Compiler Infrastructure // @@ -116,8 +116,7 @@ APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } -APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) -{ +APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { const Expr* SubExpr = E->getSubExpr(); // Check for pointer->pointer cast @@ -144,95 +143,86 @@ APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) //===----------------------------------------------------------------------===// // Integer Evaluation //===----------------------------------------------------------------------===// - namespace { class VISIBILITY_HIDDEN IntExprEvaluator - : public StmtVisitor { + : public StmtVisitor { ASTContext &Ctx; - + APSInt &Result; public: - IntExprEvaluator(ASTContext &ctx) : Ctx(ctx) {} + IntExprEvaluator(ASTContext &ctx, APSInt &result) : Ctx(ctx), Result(result){} //===--------------------------------------------------------------------===// // Visitor Methods //===--------------------------------------------------------------------===// - APValue VisitStmt(Stmt *S) { + bool VisitStmt(Stmt *S) { // FIXME: Remove this when we support more expressions. printf("unhandled int expression"); S->dump(); - return APValue(); + return false; } - APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } - APValue VisitBinaryOperator(const BinaryOperator *E); - APValue VisitUnaryOperator(const UnaryOperator *E); + bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitUnaryOperator(const UnaryOperator *E); - APValue HandleCast(const Expr* SubExpr, QualType DestType); - APValue VisitCastExpr(const CastExpr* E) { + bool HandleCast(const Expr* SubExpr, QualType DestType); + bool VisitCastExpr(const CastExpr* E) { return HandleCast(E->getSubExpr(), E->getType()); } - APValue VisitImplicitCastExpr(const ImplicitCastExpr* E) { + bool VisitImplicitCastExpr(const ImplicitCastExpr* E) { return HandleCast(E->getSubExpr(), E->getType()); } - APValue VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E); + bool VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E); - APValue VisitIntegerLiteral(const IntegerLiteral *E) { - llvm::APSInt Result(Ctx.getTypeSize(E->getType())); - + bool VisitIntegerLiteral(const IntegerLiteral *E) { Result = E->getValue(); - return APValue(Result); + return true; } }; } // end anonymous namespace static bool EvaluateInteger(const Expr* E, APSInt &Result, ASTContext &Ctx) { - APValue Value = IntExprEvaluator(Ctx).Visit(const_cast(E)); - if (!Value.isSInt()) - return false; - - Result = Value.getSInt(); - return true; + return IntExprEvaluator(Ctx, Result).Visit(const_cast(E)); } -APValue IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { +bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // The LHS of a constant expr is always evaluated and needed. - llvm::APSInt Result(32); - if (!EvaluateInteger(E->getLHS(), Result, Ctx)) - return APValue(); + if (!Visit(E->getLHS())) + return false; llvm::APSInt RHS(32); if (!EvaluateInteger(E->getRHS(), RHS, Ctx)) - return APValue(); + return false; switch (E->getOpcode()) { default: - return APValue(); + return false; case BinaryOperator::Mul: Result *= RHS; break; case BinaryOperator::Div: if (RHS == 0) - return APValue(); - Result /= RHS; - break; + return false; + Result /= RHS; + break; case BinaryOperator::Rem: if (RHS == 0) - return APValue(); + return false; 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)); + Result <<= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1); break; case BinaryOperator::Shr: - Result >>= - static_cast(RHS.getLimitedValue(Result.getBitWidth()-1)); + Result >>= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1); break; + + // FIXME: Need to set the result width? case BinaryOperator::LT: Result = Result < RHS; break; case BinaryOperator::GT: Result = Result > RHS; break; case BinaryOperator::LE: Result = Result <= RHS; break; @@ -251,17 +241,14 @@ APValue IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // 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(); + return false; } Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - - return APValue(Result); + return true; } -APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { - llvm::APSInt Result(32); - +bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { if (E->isOffsetOfOp()) Result = E->evaluateOffsetOf(Ctx); else if (E->isSizeOfAlignOfOp()) { @@ -275,7 +262,7 @@ APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { // 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(); + return false; } // Get information about the size or align. @@ -294,16 +281,16 @@ APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { // Get the operand value. If this is sizeof/alignof, do not evalute the // operand. This affects C99 6.6p3. if (!EvaluateInteger(E->getSubExpr(), Result, Ctx)) - return APValue(); + return false; switch (E->getOpcode()) { // Address, indirect, pre/post inc/dec, etc are not valid constant exprs. // See C99 6.6p3. default: - return APValue(); + return false; case UnaryOperator::Extension: assert(0 && "Handle UnaryOperator::Extension"); - return APValue(); + return false; case UnaryOperator::LNot: { bool Val = Result == 0; uint32_t typeSize = Ctx.getTypeSize(E->getType()); @@ -323,10 +310,10 @@ APValue IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { } Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - return APValue(Result); + return true; } -APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) { +bool IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) { llvm::APSInt Result(32); uint32_t DestWidth = static_cast(Ctx.getTypeSize(DestType)); @@ -334,7 +321,7 @@ APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) { // Handle simple integer->integer casts. if (SubExpr->getType()->isIntegerType()) { if (!EvaluateInteger(SubExpr, Result, Ctx)) - return APValue(); + return false; // Figure out if this is a truncate, extend or noop cast. // If the input is signed, do a sign extend, noop, or truncate. @@ -348,9 +335,9 @@ APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) { } else if (SubExpr->getType()->isPointerType()) { APValue LV; if (!EvaluatePointer(SubExpr, LV, Ctx)) - return APValue(); + return false; if (LV.getLValueBase()) - return APValue(); + return false; Result.extOrTrunc(DestWidth); Result = LV.getLValueOffset(); @@ -359,13 +346,11 @@ APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) { } Result.setIsUnsigned(DestType->isUnsignedIntegerType()); - return APValue(Result); + return true; } -APValue IntExprEvaluator:: - VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) { - llvm::APSInt Result(32); - +bool IntExprEvaluator:: +VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) { // Return the result in the right width. Result.zextOrTrunc(static_cast(Ctx.getTypeSize(E->getType()))); @@ -373,12 +358,12 @@ APValue IntExprEvaluator:: if (E->getArgumentType()->isVoidType()) { Result = 1; Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - return APValue(Result); + return true; } // alignof always evaluates to a constant, sizeof does if arg is not VLA. if (E->isSizeOf() && !E->getArgumentType()->isConstantSizeType()) - return APValue(); + return false; // Get information about the size or align. if (E->getArgumentType()->isFunctionType()) { @@ -393,19 +378,18 @@ APValue IntExprEvaluator:: } Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); - return APValue(Result); + return true; } //===----------------------------------------------------------------------===// // Top level TryEvaluate. //===----------------------------------------------------------------------===// -bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const { - llvm::APSInt sInt(1); - +bool Expr::tryEvaluate(APValue &Result, ASTContext &Ctx) const { #if USE_NEW_EVALUATOR if (getType()->isIntegerType()) { - if (IntExprEvaluator::Evaluate(this, sInt, Ctx)) { + llvm::APSInt sInt(32); + if (EvaluateInteger(this, sInt, Ctx)) { Result = APValue(sInt); return true; }