From d545ad130180ba15c894cd137a457fcd30c75c73 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 23 Sep 2009 06:06:36 +0000 Subject: [PATCH] implement support for __builtin_eh_return_data_regno on x86-32 and x86-64. This implements PR5034 and rdar://6836445. llvm-svn: 82614 --- clang/clang.xcodeproj/project.pbxproj | 4 ---- clang/include/clang/Basic/Builtins.def | 1 + clang/include/clang/Basic/TargetInfo.h | 9 ++++++++- clang/lib/AST/ExprConstant.cpp | 6 ++++++ clang/lib/Basic/Targets.cpp | 12 ++++++++++++ clang/lib/Sema/Sema.h | 1 + clang/lib/Sema/SemaChecking.cpp | 22 +++++++++++++++++++--- clang/test/Sema/builtins.c | 10 ++++++++++ 8 files changed, 57 insertions(+), 8 deletions(-) diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 8a5bdbfe4649..cf8bec008550 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -209,7 +209,6 @@ DEB076CF0F3A222200F5A2BE /* DeclTemplate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB076CE0F3A222200F5A2BE /* DeclTemplate.cpp */; }; DEB077990F44F97800F5A2BE /* TokenConcatenation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB077980F44F97800F5A2BE /* TokenConcatenation.cpp */; }; DEB07AC80F4A427E00F5A2BE /* SemaAttr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */; }; - DEC63B1C0C7B940600DBF169 /* CFG.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC63B1B0C7B940600DBF169 /* CFG.h */; }; DEC8D9910A9433CD00353FCA /* Decl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9900A9433CD00353FCA /* Decl.h */; }; DEC8D9A40A94346E00353FCA /* AST.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9A30A94346E00353FCA /* AST.h */; }; DECAB0D00DB3C84200E13CCB /* RewriteRope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECAB0CF0DB3C84200E13CCB /* RewriteRope.cpp */; }; @@ -327,7 +326,6 @@ DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */, DE6954640C5121BD00A5826B /* Token.h in CopyFiles */, DEF2E95F0C5FBD74000C4259 /* InternalsManual.html in CopyFiles */, - DEC63B1C0C7B940600DBF169 /* CFG.h in CopyFiles */, DEF7D9F70C9C8B1A0001F598 /* Rewriter.h in CopyFiles */, 84AF36A10CB17A3B00C820A5 /* DeclObjC.h in CopyFiles */, DE3986F00CB8D4B300223765 /* IdentifierTable.h in CopyFiles */, @@ -679,7 +677,6 @@ DEB077980F44F97800F5A2BE /* TokenConcatenation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TokenConcatenation.cpp; sourceTree = ""; }; DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaAttr.cpp; path = lib/Sema/SemaAttr.cpp; sourceTree = ""; tabWidth = 2; }; DEB089EE0F12F1D900522C07 /* TypeTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeTraits.h; sourceTree = ""; }; - DEC63B1B0C7B940600DBF169 /* CFG.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CFG.h; path = clang/AST/CFG.h; sourceTree = ""; tabWidth = 2; }; DEC8D9900A9433CD00353FCA /* Decl.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Decl.h; path = clang/AST/Decl.h; sourceTree = ""; tabWidth = 2; }; DEC8D9A30A94346E00353FCA /* AST.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = AST.h; path = clang/AST/AST.h; sourceTree = ""; tabWidth = 2; }; DECAB0CF0DB3C84200E13CCB /* RewriteRope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteRope.cpp; path = lib/Rewrite/RewriteRope.cpp; sourceTree = ""; }; @@ -1303,7 +1300,6 @@ 90FB99DE0F98FB1D008F9415 /* DeclContextInternals.h */, 90FB99DF0F98FB1D008F9415 /* DeclVisitor.h */, 90FB99E00F98FB1D008F9415 /* ExternalASTSource.h */, - DEC63B1B0C7B940600DBF169 /* CFG.h */, DEC8D9900A9433CD00353FCA /* Decl.h */, 3538FDB60ED24A2C005EC283 /* DeclarationName.h */, 035611470DA6A45C00D2EF2A /* DeclBase.h */, diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index da0906b77b3e..502bbd24d9cb 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -247,6 +247,7 @@ BUILTIN(__builtin_flt_rounds, "i", "nc") BUILTIN(__builtin_setjmp, "iv**", "") BUILTIN(__builtin_longjmp, "vv**i", "") BUILTIN(__builtin_unwind_init, "v", "") +BUILTIN(__builtin_eh_return_data_regno, "ii", "nc") // GCC Object size checking builtins BUILTIN(__builtin_object_size, "zv*i", "n") diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 1f61e3fccc2c..8ce85cf6bb9a 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -384,10 +384,17 @@ public: return RegParmMax; } - // isTLSSupported - Whether the target supports thread-local storage + /// isTLSSupported - Whether the target supports thread-local storage. bool isTLSSupported() const { return TLSSupported; } + + /// getEHDataRegisterNumber - Return the register number that + /// __builtin_eh_return_regno would return with the specified argument. + virtual int getEHDataRegisterNumber(unsigned RegNo) const { + return -1; + } + protected: virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 9c34547db1ad..5123aaa7ca79 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -870,6 +870,12 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { // __builtin_constant_p always has one operand: it returns true if that // operand can be folded, false otherwise. return Success(E->getArg(0)->isEvaluatable(Info.Ctx), E); + + case Builtin::BI__builtin_eh_return_data_regno: { + int Operand = E->getArg(0)->EvaluateAsInt(Info.Ctx).getZExtValue(); + Operand = Info.Ctx.Target.getEHDataRegisterNumber(Operand); + return Success(Operand, E); + } } } diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index f620581cb494..8c31dcb7c666 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -900,6 +900,12 @@ public: virtual const char *getVAListDeclaration() const { return "typedef char* __builtin_va_list;"; } + + int getEHDataRegisterNumber(unsigned RegNo) const { + if (RegNo == 0) return 0; + if (RegNo == 1) return 2; + return -1; + } }; } // end anonymous namespace @@ -990,6 +996,12 @@ public: "} __va_list_tag;" "typedef __va_list_tag __builtin_va_list[1];"; } + + int getEHDataRegisterNumber(unsigned RegNo) const { + if (RegNo == 0) return 0; + if (RegNo == 1) return 1; + return -1; + } }; } // end anonymous namespace diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 193d99288129..875da1a1d92e 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -3700,6 +3700,7 @@ private: bool SemaBuiltinObjectSize(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); bool SemaBuiltinAtomicOverloaded(CallExpr *TheCall); + bool SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall); bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 1e26c3507bbf..18a997998a59 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -138,6 +138,10 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinStackAddress(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_eh_return_data_regno: + if (SemaBuiltinEHReturnDataRegNo(TheCall)) + return ExprError(); + break; case Builtin::BI__builtin_shufflevector: return SemaBuiltinShuffleVector(TheCall); // TheCall will be freed by the smart pointer here, but that's fine, since @@ -698,7 +702,7 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { llvm::APSInt Result; if (!BT || BT->getKind() != BuiltinType::Int) return Diag(TheCall->getLocStart(), diag::err_prefetch_invalid_argument) - << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + << Arg->getSourceRange(); if (Arg->isValueDependent()) continue; @@ -713,17 +717,29 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { if (i == 1) { if (Result.getSExtValue() < 0 || Result.getSExtValue() > 1) return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << "0" << "1" << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + << "0" << "1" << Arg->getSourceRange(); } else { if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) - << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + << "0" << "3" << Arg->getSourceRange(); } } return false; } +/// SemaBuiltinEHReturnDataRegNo - Handle __builtin_eh_return_data_regno, the +/// operand must be an integer constant. +bool Sema::SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall) { + llvm::APSInt Result; + if (!TheCall->getArg(0)->isIntegerConstantExpr(Result, Context)) + return Diag(TheCall->getLocStart(), diag::err_expr_not_ice) + << TheCall->getArg(0)->getSourceRange(); + + return false; +} + + /// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, /// int type). This simply type checks that type is one of the defined /// constants (0-3). diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c index c3daa667d8a4..04a56bd5ed10 100644 --- a/clang/test/Sema/builtins.c +++ b/clang/test/Sema/builtins.c @@ -52,3 +52,13 @@ void test10(void) { // No warning about falling off the end of a noreturn function. } + +void test11(int X) { + switch (X) { + case __builtin_eh_return_data_regno(0): // constant foldable. + break; + } + + __builtin_eh_return_data_regno(X); // expected-error {{not an integer constant expression}} +} +