Repository: rust-lang/rust
File: compiler/rustc_codegen_ssa/src/mir/block.rs (Rust)

Code before:
            //          foo();
            //      } catch (...) {
            //          bar();
            //      }
            //
            // which creates an IR snippet like
            //
            //      cs_terminate:
            //         %cs = catchswitch within none [%cp_terminate] unwind to caller
            //      cp_terminate:
            //         %cp = catchpad within %cs [null, i32 64, null]
            //         ...
            //
            // By contrast, on WebAssembly targets, we specifically _do_ want to
            // catch foreign exceptions. The situation with MSVC is a
            // regrettable hack which we don't want to extend to other targets
            // unless necessary. For WebAssembly, to generate catch(...) and
            // catch only C++ exception instead of generating a catch_all, we
            // need to call the intrinsics @llvm.wasm.get.exception and
            // @llvm.wasm.get.ehselector in the catch pad. Since we don't do
            // this, we generate a catch_all. We originally got this behavior
            // by accident but it luckily matches our intention.

            llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
            let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
            bx = Bx::build(self.cx, cp_llbb);

            let mut cs_bx = Bx::build(self.cx, llbb);

            // For wasm InCleanup blocks, our catch_switch is nested within the
            // outer catchpad, so we need to provide it as the parent value to
            // catch_switch.
            let mut outer_pad_value = None;
            if outer_catchpad_bb.is_some() {
                // Get the outer funclet's catchpad
                let outer_funclet = self.funclets[cache_bb]
                    .as_ref()
                    .expect("landing_pad_for didn't create funclet");
                outer_pad_value = Some(bx.funclet_pad_value(outer_funclet));
            }
            let cs = cs_bx.catch_switch(outer_pad_value, None, &[cp_llbb]);

            let null =
                bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space));

            // The `null` in first argument here is actually a RTTI type
            // descriptor for the C++ personality function, but `catch (...)`
            // has no type so it's null.
            let args = if base::wants_msvc_seh(self.cx.sess()) {
                // This bitmask is a single `HT_IsStdDotDot` flag, which
                // represents that this is a C++-style `catch (...)` block that

Review comment (refactor):
Can you move this after the last use of `cs_bx`? I would like to move towards having a single builder per function in the future. Interleaving the lifetimes of builders complicates that.

Code after:
            //          foo();
            //      } catch (...) {
            //          bar();
            //      }
            //
            // which creates an IR snippet like
            //
            //      cs_terminate:
            //         %cs = catchswitch within none [%cp_terminate] unwind to caller
            //      cp_terminate:
            //         %cp = catchpad within %cs [null, i32 64, null]
            //         ...
            //
            // By contrast, on WebAssembly targets, we specifically _do_ want to
            // catch foreign exceptions. The situation with MSVC is a
            // regrettable hack which we don't want to extend to other targets
            // unless necessary. For WebAssembly, to generate catch(...) and
            // catch only C++ exception instead of generating a catch_all, we
            // need to call the intrinsics @llvm.wasm.get.exception and
            // @llvm.wasm.get.ehselector in the catch pad. Since we don't do
            // this, we generate a catch_all. We originally got this behavior
            // by accident but it luckily matches our intention.

            llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");

            let mut cs_bx = Bx::build(self.cx, llbb);

            // For wasm InCleanup blocks, our catch_switch is nested within the
            // outer catchpad, so we need to provide it as the parent value to
            // catch_switch.
            let mut outer_cleanuppad = None;
            if outer_catchpad_bb.is_some() {
                // Get the outer funclet's catchpad
                let outer_funclet = self.funclets[cache_bb]
                    .as_ref()
                    .expect("landing_pad_for didn't create funclet");
                outer_cleanuppad = Some(cs_bx.get_funclet_cleanuppad(outer_funclet));
            }
            let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
            let cs = cs_bx.catch_switch(outer_cleanuppad, None, &[cp_llbb]);
            drop(cs_bx);

            bx = Bx::build(self.cx, cp_llbb);
            let null =
                bx.const_null(bx.type_ptr_ext(bx.cx().data_layout().instruction_address_space));

            // The `null` in first argument here is actually a RTTI type
            // descriptor for the C++ personality function, but `catch (...)`
            // has no type so it's null.
            let args = if base::wants_msvc_seh(self.cx.sess()) {
                // This bitmask is a single `HT_IsStdDotDot` flag, which