@@ -1708,15 +1708,32 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
17081708 let mut cs_bx = Bx::build(self.cx, llbb);
17091709 let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
17101710
1711- // The "null" here is actually a RTTI type descriptor for the
1712- // C++ personality function, but `catch (...)` has no type so
1713- // it's null. The 64 here is actually a bitfield which
1714- // represents that this is a catch-all block.
17151711 bx = Bx::build(self.cx, cp_llbb);
17161712 let null =
17171713 bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space));
1718- let sixty_four = bx.const_i32(64);
1719- funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null]));
1714+
1715+ // The `null` in first argument here is actually a RTTI type
1716+ // descriptor for the C++ personality function, but `catch (...)`
1717+ // has no type so it's null.
1718+ let args = if base::wants_msvc_seh(self.cx.sess()) {
1719+ // This bitmask is a single `HT_IsStdDotDot` flag, which
1720+ // represents that this is a C++-style `catch (...)` block that
1721+ // only captures programmatic exceptions, not all SEH
1722+ // exceptions. The second `null` points to a non-existent
1723+ // `alloca` instruction, which an LLVM pass would inline into
1724+ // the initial SEH frame allocation.
1725+ let adjectives = bx.const_i32(0x40);
1726+ &[null, adjectives, null] as &[_]
1727+ } else {
1728+ // Specifying more arguments than necessary usually doesn't
1729+ // hurt, but the `WasmEHPrepare` LLVM pass does not recognize
1730+ // anything other than a single `null` as a `catch (...)` block,
1731+ // leading to problems down the line during instruction
1732+ // selection.
1733+ &[null] as &[_]
1734+ };
1735+
1736+ funclet = Some(bx.catch_pad(cs, args));
17201737 } else {
17211738 llbb = Bx::append_block(self.cx, self.llfn, "terminate");
17221739 bx = Bx::build(self.cx, llbb);
0 commit comments