[PATCH] D79474: [Windows EH] Fix the order of Nested try-catches in $tryMap$ table

Ten Tzen via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 6 01:02:40 PDT 2020


tentzen created this revision.
tentzen added reviewers: rnk, eli.friedman, JosephTremoulet, asmith.
Herald added subscribers: llvm-commits, hiraditya.
Herald added a project: LLVM.

This bug is exposed by Test7 of ehthrow.cxx in MSVC EH suite where
a rethrow occurs in a try-catch inside a catch (i.e., a nested Catch
handlers). See the test code in
https://github.com/microsoft/compiler-tests/blob/master/eh/ehthrow.cxx#L346

When an object is rethrown in a Catch handler, the copy-ctor of this
object must be executed after the destructions of live objects, but
BEFORE the dtors of live objects in parent handlers.

Today Windows runtime (__CxxFrameHandler3 & 4) expects nested Catch handers
are stored in pre-order (outer first, inner next) in $tryMap$ table, so
that given a State, its Catch's beginning State can be properly
retrieved. The Catch beginning state (which is also the ending State) is
the State where rethrown object's copy-ctor must take place.

LLVM currently stores nested catch handlers in post-ordering because
it's the natural way to compute the highest State in Catch.
The fix is to simply store TryCatch handler in pre-order, but update
Catch's highest State after child Catches are all processed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D79474

Files:
  llvm/lib/CodeGen/WinEHPrepare.cpp
  llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll


Index: llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll
===================================================================
--- llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll
+++ llvm/test/CodeGen/X86/win-catchpad-nested-cxx.ll
@@ -63,16 +63,16 @@
 ; CHECK-NEXT: .long   1
 
 ; CHECK: $tryMap$try_in_catch:
-; CHECK-NEXT: .long   2
-; CHECK-NEXT: .long   2
-; CHECK-NEXT: .long   3
-; CHECK-NEXT: .long   1
-; CHECK-NEXT: .long   ($handlerMap$0$try_in_catch)
 ; CHECK-NEXT: .long   0
 ; CHECK-NEXT: .long   0
 ; CHECK-NEXT: .long   3
 ; CHECK-NEXT: .long   1
 ; CHECK-NEXT: .long   ($handlerMap$1$try_in_catch)
+; CHECK-NEXT: .long   2
+; CHECK-NEXT: .long   2
+; CHECK-NEXT: .long   3
+; CHECK-NEXT: .long   1
+; CHECK-NEXT: .long   ($handlerMap$0$try_in_catch)
 
 ; CHECK: $handlerMap$0$try_in_catch:
 ; CHECK-NEXT:   .long   64
Index: llvm/lib/CodeGen/WinEHPrepare.cpp
===================================================================
--- llvm/lib/CodeGen/WinEHPrepare.cpp
+++ llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -263,6 +263,13 @@
 
     // catchpads are separate funclets in C++ EH due to the way rethrow works.
     int TryHigh = CatchLow - 1;
+
+    // MSVC FrameHandler3/4 expect Catch Handlers in $tryMap$ are
+    //  stored in pre-order (outer first, inner next), not post-order
+    //  Add to map here.  Fix the CatchHIgh after children are processed
+    addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchLow, Handlers);
+    unsigned TBMEIdx = FuncInfo.TryBlockMap.size() - 1;
+
     for (const auto *CatchPad : Handlers) {
       FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow;
       for (const User *U : CatchPad->users()) {
@@ -283,7 +290,9 @@
       }
     }
     int CatchHigh = FuncInfo.getLastStateNumber();
-    addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
+    // Now child Catches are processed, update CatchHigh
+    FuncInfo.TryBlockMap[TBMEIdx].CatchHigh = CatchHigh;
+
     LLVM_DEBUG(dbgs() << "TryLow[" << BB->getName() << "]: " << TryLow << '\n');
     LLVM_DEBUG(dbgs() << "TryHigh[" << BB->getName() << "]: " << TryHigh
                       << '\n');


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D79474.262304.patch
Type: text/x-patch
Size: 2121 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200506/65a2e276/attachment.bin>


More information about the llvm-commits mailing list