]> granicus.if.org Git - clang/commitdiff
Back out r132209; it's breaking nightly tests.
authorEli Friedman <eli.friedman@gmail.com>
Fri, 27 May 2011 21:32:17 +0000 (21:32 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Fri, 27 May 2011 21:32:17 +0000 (21:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132219 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGException.cpp
lib/CodeGen/CodeGenFunction.h
test/CXX/except/except.spec/p9-dynamic.cpp
test/CodeGenCXX/arm.cpp
test/CodeGenCXX/destructors.cpp
test/CodeGenCXX/eh.cpp
test/CodeGenCXX/nrvo.cpp
test/CodeGenCXX/threadsafe-statics-exceptions.cpp
test/CodeGenObjC/blocks-2.m
test/CodeGenObjC/unwind-fn.m

index 91be321d315e276989290421b308e323a1c92544..6cb9599e257dd4895aac5f0253d88931be871bda 100644 (file)
@@ -112,18 +112,11 @@ static llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) {
   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
 }
 
-llvm::Constant *CodeGenFunction::getUnwindResumeFn() {
-  const llvm::FunctionType *FTy =
-    llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false);
-
-  if (CGM.getLangOptions().SjLjExceptions)
-    return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume");
-  return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume");
-}
-
 llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() {
+  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
   const llvm::FunctionType *FTy =
-    llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false);
+    llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Int8PtrTy,
+                            /*IsVarArgs=*/false);
 
   if (CGM.getLangOptions().SjLjExceptions)
     return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow");
@@ -570,59 +563,47 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
   return LP;
 }
 
-// This code contains a hack to work around a design flaw in
-// LLVM's EH IR which breaks semantics after inlining.  This same
-// hack is implemented in llvm-gcc.
-//
-// The LLVM EH abstraction is basically a thin veneer over the
-// traditional GCC zero-cost design: for each range of instructions
-// in the function, there is (at most) one "landing pad" with an
-// associated chain of EH actions.  A language-specific personality
-// function interprets this chain of actions and (1) decides whether
-// or not to resume execution at the landing pad and (2) if so,
-// provides an integer indicating why it's stopping.  In LLVM IR,
-// the association of a landing pad with a range of instructions is
-// achieved via an invoke instruction, the chain of actions becomes
-// the arguments to the @llvm.eh.selector call, and the selector
-// call returns the integer indicator.  Other than the required
-// presence of two intrinsic function calls in the landing pad,
-// the IR exactly describes the layout of the output code.
-//
-// A principal advantage of this design is that it is completely
-// language-agnostic; in theory, the LLVM optimizers can treat
-// landing pads neutrally, and targets need only know how to lower
-// the intrinsics to have a functioning exceptions system (assuming
-// that platform exceptions follow something approximately like the
-// GCC design).  Unfortunately, landing pads cannot be combined in a
-// language-agnostic way: given selectors A and B, there is no way
-// to make a single landing pad which faithfully represents the
-// semantics of propagating an exception first through A, then
-// through B, without knowing how the personality will interpret the
-// (lowered form of the) selectors.  This means that inlining has no
-// choice but to crudely chain invokes (i.e., to ignore invokes in
-// the inlined function, but to turn all unwindable calls into
-// invokes), which is only semantically valid if every unwind stops
-// at every landing pad.
-//
-// Therefore, the invoke-inline hack is to guarantee that every
-// landing pad has a catch-all.
-enum CleanupHackLevel_t {
-  /// A level of hack that requires that all landing pads have
-  /// catch-alls.
-  CHL_MandatoryCatchall,
-
-  /// A level of hack that requires that all landing pads handle
-  /// cleanups.
-  CHL_MandatoryCleanup,
-
-  /// No hacks at all;  ideal IR generation.
-  CHL_Ideal
-};
-const CleanupHackLevel_t CleanupHackLevel = CHL_MandatoryCleanup;
-
 llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
   assert(EHStack.requiresLandingPad());
 
+  // This function contains a hack to work around a design flaw in
+  // LLVM's EH IR which breaks semantics after inlining.  This same
+  // hack is implemented in llvm-gcc.
+  //
+  // The LLVM EH abstraction is basically a thin veneer over the
+  // traditional GCC zero-cost design: for each range of instructions
+  // in the function, there is (at most) one "landing pad" with an
+  // associated chain of EH actions.  A language-specific personality
+  // function interprets this chain of actions and (1) decides whether
+  // or not to resume execution at the landing pad and (2) if so,
+  // provides an integer indicating why it's stopping.  In LLVM IR,
+  // the association of a landing pad with a range of instructions is
+  // achieved via an invoke instruction, the chain of actions becomes
+  // the arguments to the @llvm.eh.selector call, and the selector
+  // call returns the integer indicator.  Other than the required
+  // presence of two intrinsic function calls in the landing pad,
+  // the IR exactly describes the layout of the output code.
+  //
+  // A principal advantage of this design is that it is completely
+  // language-agnostic; in theory, the LLVM optimizers can treat
+  // landing pads neutrally, and targets need only know how to lower
+  // the intrinsics to have a functioning exceptions system (assuming
+  // that platform exceptions follow something approximately like the
+  // GCC design).  Unfortunately, landing pads cannot be combined in a
+  // language-agnostic way: given selectors A and B, there is no way
+  // to make a single landing pad which faithfully represents the
+  // semantics of propagating an exception first through A, then
+  // through B, without knowing how the personality will interpret the
+  // (lowered form of the) selectors.  This means that inlining has no
+  // choice but to crudely chain invokes (i.e., to ignore invokes in
+  // the inlined function, but to turn all unwindable calls into
+  // invokes), which is only semantically valid if every unwind stops
+  // at every landing pad.
+  //
+  // Therefore, the invoke-inline hack is to guarantee that every
+  // landing pad has a catch-all.
+  const bool UseInvokeInlineHack = true;
+
   for (EHScopeStack::iterator ir = EHStack.begin(); ; ) {
     assert(ir != EHStack.end() &&
            "stack requiring landing pad is nothing but non-EH scopes?");
@@ -755,23 +736,16 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
     EHSelector.append(EHFilters.begin(), EHFilters.end());
 
     // Also check whether we need a cleanup.
-    if (CleanupHackLevel == CHL_MandatoryCatchall || HasEHCleanup)
-      EHSelector.push_back(CleanupHackLevel == CHL_MandatoryCatchall
+    if (UseInvokeInlineHack || HasEHCleanup)
+      EHSelector.push_back(UseInvokeInlineHack
                            ? getCatchAllValue(*this)
                            : getCleanupValue(*this));
 
   // Otherwise, signal that we at least have cleanups.
-  } else if (CleanupHackLevel == CHL_MandatoryCatchall || HasEHCleanup) {
-    EHSelector.push_back(CleanupHackLevel == CHL_MandatoryCatchall
+  } else if (UseInvokeInlineHack || HasEHCleanup) {
+    EHSelector.push_back(UseInvokeInlineHack
                          ? getCatchAllValue(*this)
                          : getCleanupValue(*this));
-
-  // At the MandatoryCleanup hack level, we don't need to actually
-  // spuriously tell the unwinder that we have cleanups, but we do
-  // need to always be prepared to handle cleanups.
-  } else if (CleanupHackLevel == CHL_MandatoryCleanup) {
-    // Just don't decrement LastToEmitInLoop.
-
   } else {
     assert(LastToEmitInLoop > 2);
     LastToEmitInLoop--;
@@ -859,7 +833,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
 
     // If there was a cleanup, we'll need to actually check whether we
     // landed here because the filter triggered.
-    if (CleanupHackLevel != CHL_Ideal || HasEHCleanup) {
+    if (UseInvokeInlineHack || HasEHCleanup) {
       llvm::BasicBlock *RethrowBB = createBasicBlock("cleanup");
       llvm::BasicBlock *UnexpectedBB = createBasicBlock("ehspec.unexpected");
 
@@ -869,11 +843,10 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
       Builder.CreateCondBr(FailsFilter, UnexpectedBB, RethrowBB);
 
       // The rethrow block is where we land if this was a cleanup.
+      // TODO: can this be _Unwind_Resume if the InvokeInlineHack is off?
       EmitBlock(RethrowBB);
-      llvm::Constant *RethrowFn =
-        CleanupHackLevel == CHL_MandatoryCatchall ? getUnwindResumeOrRethrowFn()
-                                                  : getUnwindResumeFn();
-      Builder.CreateCall(RethrowFn, Builder.CreateLoad(getExceptionSlot()))
+      Builder.CreateCall(getUnwindResumeOrRethrowFn(),
+                         Builder.CreateLoad(getExceptionSlot()))
         ->setDoesNotReturn();
       Builder.CreateUnreachable();
 
@@ -890,7 +863,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
     Builder.CreateUnreachable();
 
   // ...or a normal catch handler...
-  } else if (CleanupHackLevel == CHL_Ideal && !HasEHCleanup) {
+  } else if (!UseInvokeInlineHack && !HasEHCleanup) {
     llvm::Value *Type = EHSelector.back();
     EmitBranchThroughEHCleanup(EHHandlers[Type]);
 
@@ -1471,9 +1444,7 @@ CodeGenFunction::UnwindDest CodeGenFunction::getRethrowDest() {
   if (!RethrowName.empty())
     RethrowFn = getCatchallRethrowFn(*this, RethrowName);
   else
-    RethrowFn = (CleanupHackLevel == CHL_MandatoryCatchall
-                   ? getUnwindResumeOrRethrowFn()
-                   : getUnwindResumeFn());
+    RethrowFn = getUnwindResumeOrRethrowFn();
 
   Builder.CreateCall(RethrowFn, Builder.CreateLoad(getExceptionSlot()))
     ->setDoesNotReturn();
index 8613f05e924d506df0160d7486a065ed5fc1c23d..9aa7903ab79ca4328a95d0e6be776e3385d08d9c 100644 (file)
@@ -1705,7 +1705,6 @@ public:
   void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S);
   void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
 
-  llvm::Constant *getUnwindResumeFn();
   llvm::Constant *getUnwindResumeOrRethrowFn();
   void EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
   void ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock = false);
index 3f496f25c9ba26ead87df11b3ddd1fcfaf0ffb46..490d2fa21f99962440d6a100b3c38dfcf9af4690 100644 (file)
@@ -7,5 +7,5 @@ void target() throw(int)
   // CHECK: invoke void @_Z8externalv()
   external();
 }
-// CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} i8* bitcast (i8** @_ZTIi to i8*)) nounwind
+// CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} i8* bitcast (i8** @_ZTIi to i8*), i8* null) nounwind
 // CHECK: call void @__cxa_call_unexpected
index a3333171c18c347ef4c751a6e4aa85b92ee567a8..f56b1552ce6dc0c65f07dcc091b85cfd171bd010 100644 (file)
@@ -310,7 +310,7 @@ namespace test7 {
 
     // CHECK:      call i8* @llvm.eh.exception()
     // CHECK:      call void @__cxa_guard_abort(i32* @_ZGVZN5test74testEvE1x)
-    // CHECK:      call void @_Unwind_Resume(
+    // CHECK:      call void @_Unwind_Resume_or_Rethrow
   }
 }
 
@@ -349,7 +349,7 @@ namespace test8 {
 
     // CHECK:      call i8* @llvm.eh.exception()
     // CHECK:      call void @__cxa_guard_abort(i32* @_ZGVZN5test84testEvE1x)
-    // CHECK:      call void @_Unwind_Resume(
+    // CHECK:      call void @_Unwind_Resume_or_Rethrow
   }
 }
 
index bc32d7d743ac12e99cdf73204891016d16faefee..353b61061ad1c53ea90e6afcab6abbc955ebf0b1 100644 (file)
@@ -334,7 +334,7 @@ namespace test7 {
   // CHECK: ret void
   // CHECK: call i8* @llvm.eh.exception(
   // CHECK: call void @_ZdlPv({{.*}}) nounwind
-  // CHECK: call void @_Unwind_Resume(
+  // CHECK: call void @_Unwind_Resume_or_Rethrow
 
   // Checked at top of file:
   // @_ZN5test312_GLOBAL__N_11DD1Ev = alias internal {{.*}} @_ZN5test312_GLOBAL__N_11DD2Ev
@@ -364,7 +364,7 @@ namespace test7 {
   // CHECK: ret void
   // CHECK: call i8* @llvm.eh.exception()
   // CHECK: call void @_ZdlPv({{.*}}) nounwind
-  // CHECK: call void @_Unwind_Resume(
+  // CHECK: call void @_Unwind_Resume_or_Rethrow(
 
   // CHECK: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
   // CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
index 250d47edd2c69105d8562c74489810a3132cecfb..88c32724b84b62760546fcfd324d7a3b3eb8b023 100644 (file)
@@ -190,7 +190,7 @@ namespace test9 {
 
   // landing pad from first call to invoke
   // CHECK:      call i8* @llvm.eh.exception
-  // CHECK:      call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*))
+  // CHECK:      call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* {{.*}}, i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* bitcast (i8** @_ZTIi to i8*), i8* null)
 }
 
 // __cxa_end_catch can throw for some kinds of caught exceptions.
index 3104f937f1bf4f31a533a0abf26630c0e4a972ab..ad6fa4f744569dff8758b8cfd41d6c7932c962fa 100644 (file)
@@ -95,7 +95,7 @@ X test2(bool B) {
 
   // %invoke.cont17: rethrow block for %eh.cleanup.
   // This really should be elsewhere in the function.
-  // CHECK-EH:      call void @_Unwind_Resume(
+  // CHECK-EH:      call void @_Unwind_Resume_or_Rethrow
   // CHECK-EH-NEXT: unreachable
 
   // %terminate.lpad: terminate landing pad.
index 06ebe0a71b6e314746a17b59cccd68b6249301d9..0bd810eeca56960d238cf16bdd4512a1cf1cc831 100644 (file)
@@ -24,6 +24,6 @@ void f() {
   // CHECK: call i8* @llvm.eh.exception()
   // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector
   // CHECK: call void @__cxa_guard_abort(i64* @_ZGVZ1fvE1x)
-  // CHECK: call void @_Unwind_Resume(
+  // CHECK: call void @_Unwind_Resume_or_Rethrow
   // CHECK: unreachable
 }
index 1f1c272fbf51129079ee7662b831e5ef502c6dd4..38b863560998d0b249d849ec7e174ef3c1b26928 100644 (file)
@@ -33,5 +33,5 @@ void test1() {
   // CHECK:      call i8* @llvm.eh.exception()
   // CHECK:      [[T1:%.*]] = bitcast [[N_T]]* [[N]] to i8*
   // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8)
-  // CHECK:      call void @_Unwind_Resume(
+  // CHECK:      call void @_Unwind_Resume_or_Rethrow(
 }
index 8d13c989696a7c8dad831d52209a7df4ea0e8e85..5e4a7a5863b7089fce4f6c1eaab49598d7daa54e 100644 (file)
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -fobjc-nonfragile-abi -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck --check-prefix=DEFAULT_EH %s
 // RUN: %clang_cc1 -fsjlj-exceptions -fobjc-nonfragile-abi -fexceptions -fobjc-exceptions -emit-llvm -o - %s | FileCheck --check-prefix=SJLJ_EH %s
 
-// DEFAULT_EH: declare void @_Unwind_Resume(i8*)
-// SJLJ_EH: declare void @_Unwind_SjLj_Resume(i8*)
+// DEFAULT_EH: declare void @_Unwind_Resume_or_Rethrow(i8*)
+// SJLJ_EH: declare void @_Unwind_SjLj_Resume_or_Rethrow(i8*)
 
 void f1(), f2();
 void f0() {