]> granicus.if.org Git - clang/commitdiff
__builtin_object_size refinements. Ensure we handle expressions with
authorMike Stump <mrs@apple.com>
Tue, 27 Oct 2009 22:09:17 +0000 (22:09 +0000)
committerMike Stump <mrs@apple.com>
Tue, 27 Oct 2009 22:09:17 +0000 (22:09 +0000)
side-effects up front, as when we switch to the llvm intrinsic call
for __builtin_object_size later, it will have two evaluations.

We also finish off the intrinsic version of the code so we can just
turn it on once llvm has the intrinsic.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85324 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
lib/CodeGen/CGBuiltin.cpp

index 8435e03417308dde245c1874a6b3ac2b88b2f5c0..dc53289165aae5416177fd7a835cf7fc63dad2d9 100644 (file)
@@ -151,6 +151,66 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType,
   return Result;
 }
 
+namespace {
+class VISIBILITY_HIDDEN HasSideEffect
+  : public StmtVisitor<HasSideEffect, bool> {
+  EvalInfo &Info;
+public:
+
+  HasSideEffect(EvalInfo &info) : Info(info) {}
+
+  // Unhandled nodes conservatively default to having side effects.
+  bool VisitStmt(Stmt *S) {
+    return true;
+  }
+
+  bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
+  bool VisitDeclRefExpr(DeclRefExpr *E) {
+    if (E->getType().isVolatileQualified())
+      return true;
+    return false;
+  }
+  // We don't want to evaluate BlockExprs multiple times, as they generate
+  // a ton of code.
+  bool VisitBlockExpr(BlockExpr *E) { return true; }
+  bool VisitPredefinedExpr(PredefinedExpr *E) { return false; }
+  bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E)
+    { return Visit(E->getInitializer()); }
+  bool VisitMemberExpr(MemberExpr *E) { return Visit(E->getBase()); }
+  bool VisitIntegerLiteral(IntegerLiteral *E) { return false; }
+  bool VisitFloatingLiteral(FloatingLiteral *E) { return false; }
+  bool VisitStringLiteral(StringLiteral *E) { return false; }
+  bool VisitCharacterLiteral(CharacterLiteral *E) { return false; }
+  bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { return false; }
+  bool VisitArraySubscriptExpr(ArraySubscriptExpr *E)
+    { return Visit(E->getLHS()) && Visit(E->getRHS()); }
+  bool VisitChooseExpr(ChooseExpr *E)
+    { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+  bool VisitCastExpr(CastExpr *E) { return Visit(E->getSubExpr()); }
+  bool VisitBinAssign(BinaryOperator *E) { return true; }
+  bool VisitCompoundAssign(BinaryOperator *E) { return true; }
+  bool VisitBinaryOperator(BinaryOperator *E) { return false; }
+  bool VisitUnaryPreInc(UnaryOperator *E) { return true; }
+  bool VisitUnaryPostInc(UnaryOperator *E) { return true; }
+  bool VisitUnaryPreDec(UnaryOperator *E) { return true; }
+  bool VisitUnaryPostDec(UnaryOperator *E) { return true; }
+  bool VisitUnaryDeref(UnaryOperator *E) {
+    if (E->getType().isVolatileQualified())
+      return true;
+    return false;
+  }
+  bool VisitUnaryOperator(UnaryOperator *E) { return Visit(E->getSubExpr()); }
+};
+
+bool HasSideEffects(const Expr* E, ASTContext &Ctx) {
+  Expr::EvalResult Result;
+  EvalInfo Info(Ctx, Result);
+
+  return HasSideEffect(Info).Visit(const_cast<Expr*>(E));
+}
+
+} // end anonymous namespace
+
 //===----------------------------------------------------------------------===//
 // LValue Evaluation
 //===----------------------------------------------------------------------===//
@@ -893,12 +953,12 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
           }
         }
 
-    if (Base.HasSideEffects) {
+    if (HasSideEffects(E->getArg(0), Info.Ctx)) {
       if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() < 2)
         return Success(-1, E);
       return Success(0, E);
     }
-    
+
     return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
   }
 
index 29b46611e2e71ea6b4b170cd5701e94f824b2837..c26921969a88601cf0894ed98c935127619a5e1e 100644 (file)
@@ -203,11 +203,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
 #if 0
     // We pass this builtin onto the optimizer so that it can
     // figure out the object size in more complex cases.
-    Value *F = CGM.getIntrinsic(Intrinsic::objectsize, 0, 0);
-    Builder.CreateCall2(F,
-                        EmitScalarExpr(E->getArg(0)));
-                        EmitScalarExpr(E->getArg(1)));
-    return RValue::get(Address);
+    const llvm::Type *ResType[] = {
+      ConvertType(E->getType())
+    };
+    Value *F = CGM.getIntrinsic(Intrinsic::objectsize, ResType, 1);
+    return RValue::get(Builder.CreateCall2(F,
+                                           EmitScalarExpr(E->getArg(0)),
+                                           EmitScalarExpr(E->getArg(1))));
 #else
     // FIXME: Implement. For now we just always fail and pretend we
     // don't know the object size.