From c4c9045dabfc0f0d37dea1b3eb2992654d5b2db1 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Tue, 27 Oct 2009 22:09:17 +0000 Subject: [PATCH] __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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85324 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 64 +++++++++++++++++++++++++++++++++++++-- lib/CodeGen/CGBuiltin.cpp | 12 +++++--- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 8435e03417..dc53289165 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -151,6 +151,66 @@ static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType, return Result; } +namespace { +class VISIBILITY_HIDDEN HasSideEffect + : public StmtVisitor { + 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(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/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 29b46611e2..c26921969a 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/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. -- 2.40.0