sgraenitz created this revision.
sgraenitz added reviewers: theraven, rnk.
Herald added a project: All.
sgraenitz requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Pushing the `CatchRetScope` early causes cleanups for catch parameters to be 
emitted in the basic block of the catch handler instead of the `catchret.dest` 
block. This is important because the latter is not part of the catchpad and 
this caused code truncations due to ARC PreISel intrinsics in WinEHPrepare.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D137939

Files:
  clang/lib/CodeGen/CGObjCRuntime.cpp
  clang/test/CodeGenObjCXX/arc-exceptions-seh.mm

Index: clang/test/CodeGenObjCXX/arc-exceptions-seh.mm
===================================================================
--- clang/test/CodeGenObjCXX/arc-exceptions-seh.mm
+++ clang/test/CodeGenObjCXX/arc-exceptions-seh.mm
@@ -7,23 +7,42 @@
 // funclet tokens for llvm.objc.retain and llvm.objc.storeStrong and that they
 // refer to their catchpad's SSA value.
 
-@class Ety;
-void opaque(void);
-void test_catch_with_objc_intrinsic(void) {
+void do_something();
+void may_throw(id);
+
+void try_catch_with_objc_intrinsic() {
+  id ex;
   @try {
-    opaque();
-  } @catch (Ety *ex) {
-    // Destroy ex when leaving catchpad. This emits calls to intrinsic functions
-    // llvm.objc.retain and llvm.objc.storeStrong
+    may_throw(ex);
+  } @catch (id ex_caught) {
+    do_something();
+    may_throw(ex_caught);
   }
 }
 
-// CHECK-LABEL: define{{.*}} void {{.*}}test_catch_with_objc_intrinsic
-//                ...
-// CHECK:       catch.dispatch:
-// CHECK-NEXT:    [[CATCHSWITCH:%[0-9]+]] = catchswitch within none
-//                ...
-// CHECK:       catch:
-// CHECK-NEXT:    [[CATCHPAD:%[0-9]+]] = catchpad within [[CATCHSWITCH]]
-// CHECK:         {{%[0-9]+}} = call {{.*}} @llvm.objc.retain{{.*}} [ "funclet"(token [[CATCHPAD]]) ]
-// CHECK:         call {{.*}} @llvm.objc.storeStrong{{.*}} [ "funclet"(token [[CATCHPAD]]) ]
+// CHECK-LABEL:   try_catch_with_objc_intrinsic
+//
+// CHECK:         catch.dispatch:
+// CHECK-NEXT:      [[CATCHSWITCH:%[0-9]+]] = catchswitch within none [label %catch]
+//
+// All calls within a catchpad must have funclet tokens that refer to the
+// enclosing catchpad:
+// CHECK:         catch:
+// CHECK-NEXT:      [[CATCHPAD:%[0-9]+]] = catchpad within [[CATCHSWITCH]]
+// CHECK:           call
+// CHECK:           @llvm.objc.retain
+// CHECK:           [ "funclet"(token [[CATCHPAD]]) ]
+// CHECK:           call
+// CHECK:           do_something
+// CHECK:           [ "funclet"(token [[CATCHPAD]]) ]
+// CHECK:           call
+// CHECK:           may_throw
+// CHECK:           [ "funclet"(token [[CATCHPAD]]) ]
+// CHECK:           call
+// CHECK:           @llvm.objc.storeStrong
+// CHECK:           [ "funclet"(token [[CATCHPAD]]) ]
+// CHECK:           catchret from [[CATCHPAD]] to label %catchret.dest
+//
+// This block exists and it's empty:
+// CHECK:         catchret.dest:
+// CHECK-NEXT:      br label %eh.cont
Index: clang/lib/CodeGen/CGObjCRuntime.cpp
===================================================================
--- clang/lib/CodeGen/CGObjCRuntime.cpp
+++ clang/lib/CodeGen/CGObjCRuntime.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/StmtObjC.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGen/CodeGenABITypes.h"
+#include "llvm/IR/Instruction.h"
 #include "llvm/Support/SaveAndRestore.h"
 
 using namespace clang;
@@ -227,13 +228,18 @@
     CatchHandler &Handler = Handlers[I];
 
     CGF.EmitBlock(Handler.Block);
-    llvm::CatchPadInst *CPI = nullptr;
-    SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad(CGF.CurrentFuncletPad);
-    if (useFunclets)
-      if ((CPI = dyn_cast_or_null<llvm::CatchPadInst>(Handler.Block->getFirstNonPHI()))) {
+
+    CodeGenFunction::LexicalScope Cleanups(CGF, Handler.Body->getSourceRange());
+    SaveAndRestore<llvm::Instruction *> RevertAfterScope(CGF.CurrentFuncletPad);
+    if (useFunclets) {
+      llvm::Instruction *CPICandidate = Handler.Block->getFirstNonPHI();
+      if (auto *CPI = dyn_cast_or_null<llvm::CatchPadInst>(CPICandidate)) {
         CGF.CurrentFuncletPad = CPI;
         CPI->setOperand(2, CGF.getExceptionSlot().getPointer());
+        CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
       }
+    }
+
     llvm::Value *RawExn = CGF.getExceptionFromSlot();
 
     // Enter the catch.
@@ -241,8 +247,6 @@
     if (beginCatchFn)
       Exn = CGF.EmitNounwindRuntimeCall(beginCatchFn, RawExn, "exn.adjusted");
 
-    CodeGenFunction::LexicalScope cleanups(CGF, Handler.Body->getSourceRange());
-
     if (endCatchFn) {
       // Add a cleanup to leave the catch.
       bool EndCatchMightThrow = (Handler.Variable == nullptr);
@@ -260,15 +264,13 @@
       CGF.EmitAutoVarDecl(*CatchParam);
       EmitInitOfCatchParam(CGF, CastExn, CatchParam);
     }
-    if (CPI)
-        CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI);
 
     CGF.ObjCEHValueStack.push_back(Exn);
     CGF.EmitStmt(Handler.Body);
     CGF.ObjCEHValueStack.pop_back();
 
     // Leave any cleanups associated with the catch.
-    cleanups.ForceCleanup();
+    Cleanups.ForceCleanup();
 
     CGF.EmitBranchThroughCleanup(Cont);
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to