diff options
| author | Mike Stump <mrs@apple.com> | 2009-10-27 22:09:17 +0000 | 
|---|---|---|
| committer | Mike Stump <mrs@apple.com> | 2009-10-27 22:09:17 +0000 | 
| commit | 876387ba4ff804995cd3707af70925341c6b58b9 (patch) | |
| tree | 7c61a34d236f5226857fff03dfefe552d7637606 /clang/lib | |
| parent | a4374e66f0b92446c4fee3f3f61329a5ff832ba6 (diff) | |
| download | bcm5719-llvm-876387ba4ff804995cd3707af70925341c6b58b9.tar.gz bcm5719-llvm-876387ba4ff804995cd3707af70925341c6b58b9.zip  | |
__builtin_object_size refinements.  Ensure we handle expressions with
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.
llvm-svn: 85324
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 64 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 12 | 
2 files changed, 69 insertions, 7 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 8435e034173..dc53289165a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -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);    } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 29b46611e2e..c26921969a8 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -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.  | 

