diff options
author | Anders Carlsson <andersca@mac.com> | 2008-07-08 15:34:11 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2008-07-08 15:34:11 +0000 |
commit | 650c92fdcc27a950a8a848ecab6a74e6f5e80788 (patch) | |
tree | 1656b40bb5e6250c60cf4fa2c36376c13e63a3dd /lib/AST/ExprConstant.cpp | |
parent | a25ae3d68d84d2b89907f998df6a396549589da5 (diff) |
More constant expression work.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53235 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 118 |
1 files changed, 112 insertions, 6 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index f2b32c6fa4..860ff1c165 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -60,24 +60,27 @@ class VISIBILITY_HIDDEN PointerExprEvaluator : Ctx(ctx) {} public: - static bool Evaluate(const Expr* E, APValue& Result, ASTContext &Ctx) { + static bool Evaluate(const Expr* E, APValue& Result, ASTContext &Ctx) { + if (!E->getType()->isPointerType()) + return false; Result = PointerExprEvaluator(Ctx).Visit(const_cast<Expr*>(E)); return Result.isLValue(); } APValue VisitStmt(Stmt *S) { // FIXME: Remove this when we support more expressions. - printf("Unhandled statement\n"); + printf("Unhandled pointer statement\n"); S->dump(); return APValue(); } APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + APValue VisitBinaryOperator(const BinaryOperator *E); + APValue VisitCastExpr(const CastExpr* E); + }; -} -namespace { class VISIBILITY_HIDDEN IntExprEvaluator : public StmtVisitor<IntExprEvaluator, APValue> { ASTContext &Ctx; @@ -86,7 +89,7 @@ class VISIBILITY_HIDDEN IntExprEvaluator : Ctx(ctx) {} public: - static bool Evaluate(const Expr* E, llvm::APSInt& Result, ASTContext &Ctx) { + static bool Evaluate(const Expr* E, llvm::APSInt& Result, ASTContext &Ctx) { APValue Value = IntExprEvaluator(Ctx).Visit(const_cast<Expr*>(E)); if (!Value.isSInt()) return false; @@ -100,7 +103,7 @@ public: //===--------------------------------------------------------------------===// APValue VisitStmt(Stmt *S) { // FIXME: Remove this when we support more expressions. - printf("Unhandled statement\n"); + printf("unhandled int expression"); S->dump(); return APValue(); } @@ -111,8 +114,76 @@ public: APValue VisitUnaryOperator(const UnaryOperator *E); APValue HandleCast(const Expr* SubExpr, QualType DestType); + APValue VisitCastExpr(const CastExpr* E) { + return HandleCast(E->getSubExpr(), E->getType()); + } + APValue VisitImplicitCastExpr(const ImplicitCastExpr* E) { + return HandleCast(E->getSubExpr(), E->getType()); + } + APValue VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E); + + APValue VisitIntegerLiteral(const IntegerLiteral *E) { + llvm::APSInt Result(Ctx.getTypeSize(E->getType())); + + Result = E->getValue(); + return APValue(Result); + } + }; +APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) +{ + if (E->getOpcode() != BinaryOperator::Add && + E->getOpcode() != BinaryOperator::Sub) + return APValue(); + + const Expr *PExp = E->getLHS(); + const Expr *IExp = E->getRHS(); + if (IExp->getType()->isPointerType()) + std::swap(PExp, IExp); + + APValue ResultLValue; + if (!PointerExprEvaluator::Evaluate(PExp, ResultLValue, Ctx)) + return APValue(); + llvm::APSInt AdditionalOffset(32); + if (!IntExprEvaluator::Evaluate(IExp, AdditionalOffset, Ctx)) + return APValue(); + + uint64_t Offset = ResultLValue.getLValueOffset(); + if (E->getOpcode() == BinaryOperator::Add) + Offset += AdditionalOffset.getZExtValue(); + else + Offset -= AdditionalOffset.getZExtValue(); + + return APValue(ResultLValue.getLValueBase(), Offset); +} + + +APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) +{ + const Expr* SubExpr = E->getSubExpr(); + + // Check for pointer->pointer cast + if (SubExpr->getType()->isPointerType()) { + APValue Result; + if (PointerExprEvaluator::Evaluate(SubExpr, Result, Ctx)) + return Result; + else + return APValue(); + } + + if (SubExpr->getType()->isArithmeticType()) { + llvm::APSInt Result(32); + if (IntExprEvaluator::Evaluate(SubExpr, Result, Ctx)) { + Result.extOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType()))); + return APValue(0, Result.getZExtValue()); + } + } + + assert(0 && "Unhandled cast"); + return APValue(); +} + APValue IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // The LHS of a constant expr is always evaluated and needed. llvm::APSInt Result(32); @@ -277,6 +348,41 @@ APValue IntExprEvaluator::HandleCast(const Expr* SubExpr, QualType DestType) { return APValue(Result); } +APValue IntExprEvaluator::VisitSizeOfAlignOfTypeExpr + (const SizeOfAlignOfTypeExpr *E) +{ + llvm::APSInt Result(32); + + // Return the result in the right width. + Result.zextOrTrunc(static_cast<uint32_t>(Ctx.getTypeSize(E->getType()))); + + // sizeof(void) and __alignof__(void) = 1 as a gcc extension. + if (E->getArgumentType()->isVoidType()) { + Result = 1; + Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); + return APValue(Result); + } + + // alignof always evaluates to a constant, sizeof does if arg is not VLA. + if (E->isSizeOf() && !E->getArgumentType()->isConstantSizeType()) + return APValue(); + + // Get information about the size or align. + if (E->getArgumentType()->isFunctionType()) { + // GCC extension: sizeof(function) = 1. + Result = E->isSizeOf() ? 1 : 4; + } else { + unsigned CharSize = Ctx.Target.getCharWidth(); + if (E->isSizeOf()) + Result = Ctx.getTypeSize(E->getArgumentType()) / CharSize; + else + Result = Ctx.getTypeAlign(E->getArgumentType()) / CharSize; + } + + Result.setIsUnsigned(E->getType()->isUnsignedIntegerType()); + return APValue(Result); +} + } bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const |