[cfe-commits] r53235 - /cfe/trunk/lib/AST/ExprConstant.cpp

Anders Carlsson andersca at mac.com
Tue Jul 8 08:35:06 PDT 2008


Author: andersca
Date: Tue Jul  8 10:34:11 2008
New Revision: 53235

URL: http://llvm.org/viewvc/llvm-project?rev=53235&view=rev
Log:
More constant expression work.

Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=53235&r1=53234&r2=53235&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Jul  8 10:34:11 2008
@@ -60,24 +60,27 @@
     : 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 @@
     : 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 @@
   //===--------------------------------------------------------------------===//
   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 @@
   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 @@
   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





More information about the cfe-commits mailing list