]> granicus.if.org Git - clang/commitdiff
Merge r230255,231245,231280,231986:
authorJoerg Sonnenberger <joerg@bec.de>
Thu, 12 Mar 2015 11:14:45 +0000 (11:14 +0000)
committerJoerg Sonnenberger <joerg@bec.de>
Thu, 12 Mar 2015 11:14:45 +0000 (11:14 +0000)
Only lower __builtin_setjmp / __builtin_longjmp to
llvm.eh.sjlj.setjmp / llvm.eh.sjlj.longjmp, if the backend is known to
support them outside the Exception Handling context. The default
handling in LLVM codegen doesn't work and will create incorrect code.
The ARM backend on the other hand will assert if the intrinsics are
used.
--
Adjust the changes from r230255 to bail out if the backend can't lower
__builtin_setjmp/__builtin_longjmp and don't fall back to the libc
functions.
--
Fix test/CodeGen/builtins.c for platforms that don't lower sjlj

Opt in Win64 to supporting sjlj lowering. We have the backend lowering,
so I think this was just an oversight because WinX86_64TargetCodeGenInfo
doesn't inherit from X86_64TargetCodeGenInfo.
--
Under duress, move check for target support of __builtin_setjmp/
__builtin_longjmp to Sema as requested by John McCall.

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

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/TargetInfo.h
include/clang/Sema/Sema.h
lib/Basic/Targets.cpp
lib/CodeGen/TargetInfo.cpp
lib/Sema/SemaChecking.cpp
test/CodeGen/2003-08-06-BuiltinSetjmpLongjmp.c [deleted file]
test/CodeGen/builtins.c
test/Sema/builtin-longjmp.c [new file with mode: 0644]

index b173d82a31d4941940dfa9dda09f1bc8a2ed27b5..1a27e7cd3d2c09bd96eb1eb1600ec90ff841bc36 100644 (file)
@@ -6972,6 +6972,11 @@ def note_neon_vector_initializer_non_portable_q : Note<
   "vcombine_%0%1(vcreate_%0%1(), vcreate_%0%1()) to initialize from integer "
   "constants">;
 
+def err_builtin_longjmp_unsupported : Error<
+  "__builtin_longjmp is not supported for the current target">;
+def err_builtin_setjmp_unsupported : Error<
+  "__builtin_setjmp is not supported for the current target">;
+
 def err_builtin_longjmp_invalid_val : Error<
   "argument to __builtin_longjmp must be a constant 1">;
 def err_builtin_requires_language : Error<"'%0' is only available in %1">;
index 69a54044680d0db3488d690fda002e476195e6ab..7a6462c482278e73440ffc70ea0c7e19a710e36f 100644 (file)
@@ -852,6 +852,12 @@ public:
     }
   }
 
+  /// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
+  /// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
+  virtual bool hasSjLjLowering() const {
+    return false;
+  }
+
 protected:
   virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
     return PointerWidth;
index bba7c3683498b7cca349e2dcecb777e61cff5add..a364214c11de3add694c657f33c934f99e150a83 100644 (file)
@@ -8550,6 +8550,7 @@ private:
   bool SemaBuiltinAssume(CallExpr *TheCall);
   bool SemaBuiltinAssumeAligned(CallExpr *TheCall);
   bool SemaBuiltinLongjmp(CallExpr *TheCall);
+  bool SemaBuiltinSetjmp(CallExpr *TheCall);
   ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
   ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult,
                                      AtomicExpr::AtomicOp Op);
index bf60bbf3fd9f46e40671194d19fc60a78305f136..dc844bf221f75224e8520c1bbdabd99ecb78fb79 100644 (file)
@@ -919,6 +919,10 @@ public:
     if (RegNo == 1) return 4;
     return -1;
   }
+
+  bool hasSjLjLowering() const override {
+    return true;
+  }
 };
 
 const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
@@ -2181,6 +2185,10 @@ public:
   CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
     return MT == CCMT_Member ? CC_X86ThisCall : CC_C;
   }
+
+  bool hasSjLjLowering() const override {
+    return true;
+  }
 };
 
 bool X86TargetInfo::setFPMath(StringRef Name) {
index 39cc7e5d99c4559c15ad5fa7091a0cfb17299a76..c05b23a32e8682244058ed0fcc094741bb6f2f2b 100644 (file)
@@ -664,7 +664,6 @@ public:
                    ('T' << 24);
     return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
   }
-
 };
 
 }
@@ -4455,7 +4454,6 @@ public:
                                               llvm::AttributeSet::FunctionIndex,
                                               B));
   }
-
 };
 
 }
index fdc136ccbd232df893d5e30d9f3a65782f3f7638..8c3efdee9036d568ca8c74ebf25a59f400e44847 100644 (file)
@@ -297,6 +297,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
     if (SemaBuiltinLongjmp(TheCall))
       return ExprError();
     break;
+  case Builtin::BI__builtin_setjmp:
+    if (SemaBuiltinSetjmp(TheCall))
+      return ExprError();
+    break;
 
   case Builtin::BI__builtin_classify_type:
     if (checkArgCount(*this, TheCall, 1)) return true;
@@ -2367,8 +2371,13 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
 }
 
 /// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val).
-/// This checks that val is a constant 1.
+/// This checks that the target supports __builtin_longjmp and
+/// that val is a constant 1.
 bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
+  if (!Context.getTargetInfo().hasSjLjLowering())
+    return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_unsupported)
+             << SourceRange(TheCall->getLocStart(), TheCall->getLocEnd());
+
   Expr *Arg = TheCall->getArg(1);
   llvm::APSInt Result;
 
@@ -2383,6 +2392,16 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
   return false;
 }
 
+
+/// SemaBuiltinSetjmp - Handle __builtin_setjmp(void *env[5]).
+/// This checks that the target supports __builtin_setjmp.
+bool Sema::SemaBuiltinSetjmp(CallExpr *TheCall) {
+  if (!Context.getTargetInfo().hasSjLjLowering())
+    return Diag(TheCall->getLocStart(), diag::err_builtin_setjmp_unsupported)
+             << SourceRange(TheCall->getLocStart(), TheCall->getLocEnd());
+  return false;
+}
+
 namespace {
 enum StringLiteralCheckType {
   SLCT_NotALiteral,
diff --git a/test/CodeGen/2003-08-06-BuiltinSetjmpLongjmp.c b/test/CodeGen/2003-08-06-BuiltinSetjmpLongjmp.c
deleted file mode 100644 (file)
index 3aa5c00..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* RUN: %clang_cc1  %s -emit-llvm -o - | FileCheck %s
- *
- * __builtin_longjmp/setjmp should get transformed into intrinsics.
- */
-
-// CHECK-NOT: builtin_longjmp
-
-void jumpaway(int *ptr) {
-  __builtin_longjmp(ptr,1);
-}
-    
-int main(void) {
-  __builtin_setjmp(0);
-  jumpaway(0);
-}
index 1ab29a659b31a8de05425f4d3cca43d817f841f2..bf7874b088627bb3f4ff90a50edeb1f44521b992 100644 (file)
@@ -220,6 +220,8 @@ void test_float_builtin_ops(float F, double D, long double LD) {
   // CHECK: call x86_fp80 @llvm.fabs.f80(x86_fp80
 }
 
+// __builtin_longjmp isn't supported on all platforms, so only test it on X86.
+#ifdef __x86_64__
 // CHECK-LABEL: define void @test_builtin_longjmp
 void test_builtin_longjmp(void **buffer) {
   // CHECK: [[BITCAST:%.*]] = bitcast
@@ -227,6 +229,7 @@ void test_builtin_longjmp(void **buffer) {
   __builtin_longjmp(buffer, 1);
   // CHECK-NEXT: unreachable
 }
+#endif
 
 // CHECK-LABEL: define i64 @test_builtin_readcyclecounter
 long long test_builtin_readcyclecounter() {
diff --git a/test/Sema/builtin-longjmp.c b/test/Sema/builtin-longjmp.c
new file mode 100644 (file)
index 0000000..5ed393e
--- /dev/null
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm < %s| FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm < %s| FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-windows -emit-llvm < %s| FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-unknown-unknown -emit-llvm < %s| FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm < %s| FileCheck %s
+
+// RUN: %clang_cc1 -triple arm-unknown-unknown -emit-llvm-only -verify %s
+// RUN: %clang_cc1 -triple aarch64-unknown-unknown -emit-llvm-only -verify %s
+// RUN: %clang_cc1 -triple mips-unknown-unknown -emit-llvm-only -verify %s
+// RUN: %clang_cc1 -triple mips64-unknown-unknown -emit-llvm-only -verify %s
+
+// Check that __builtin_longjmp and __builtin_setjmp are lowered into
+// IR intrinsics on those architectures that can handle them.
+// Check that an error is created otherwise.
+
+typedef void *jmp_buf;
+jmp_buf buf;
+
+// CHECK:   define{{.*}} void @do_jump()
+// CHECK:   call{{.*}} void @llvm.eh.sjlj.longjmp
+
+// CHECK:   define{{.*}} void @do_setjmp()
+// CHECK:   call{{.*}} i32 @llvm.eh.sjlj.setjmp
+
+void do_jump(void) {
+  __builtin_longjmp(buf, 1); // expected-error {{__builtin_longjmp is not supported for the current target}}
+}
+
+void f(void);
+
+void do_setjmp(void) {
+  if (!__builtin_setjmp(buf)) // expected-error {{__builtin_setjmp is not supported for the current target}}
+    f();
+}