rustc: Fill out remaining parts of C-unwind ABI

This commit intends to fill out some of the remaining pieces of the
C-unwind ABI. This has a number of other changes with it though to move
this design space forward a bit. Notably contained within here is:

* On `panic=unwind`, the `extern "C"` ABI is now considered as "may
  unwind". This fixes a longstanding soundness issue where if you
  `panic!()` in an `extern "C"` function defined in Rust that's actually
  UB because the LLVM representation for the function has the `nounwind`
  attribute, but then you unwind.

* Whether or not a function unwinds now mainly considers the ABI of the
  function instead of first checking the panic strategy. This fixes a
  miscompile of `extern "C-unwind"` with `panic=abort` because that ABI
  can still unwind.

* The aborting stub for non-unwinding ABIs with `panic=unwind` has been
  reimplemented. Previously this was done as a small tweak during MIR
  generation, but this has been moved to a separate and dedicated MIR
  pass. This new pass will, for appropriate functions and function
  calls, insert a `cleanup` landing pad for any function call that may
  unwind within a function that is itself not allowed to unwind. Note
  that this subtly changes some behavior from before where previously on
  an unwind which was caught-to-abort it would run active destructors in
  the function, and now it simply immediately aborts the process.

* The `#[unwind]` attribute has been removed and all users in tests and
  such are now using `C-unwind` and `#![feature(c_unwind)]`.

I think this is largely the last piece of the RFC to implement.
Unfortunately I believe this is still not stabilizable as-is because
activating the feature gate changes the behavior of the existing `extern
"C"` ABI in a way that has no replacement. My thinking for how to enable
this is that we add support for the `C-unwind` ABI on stable Rust first,
and then after it hits stable we change the behavior of the `C` ABI.
That way anyone straddling stable/beta/nightly can switch to `C-unwind`
safely.
This commit is contained in:
Alex Crichton
2021-06-08 11:23:58 -07:00
parent 2939249f29
commit 1c07096a45
46 changed files with 431 additions and 478 deletions

View File

@@ -13,6 +13,7 @@ use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_span::{Span, Symbol};
use std::borrow::Cow;
pub mod abort_unwinding_calls;
pub mod add_call_guards;
pub mod add_moves_for_packed_drops;
pub mod add_retag;
@@ -39,7 +40,6 @@ pub mod lower_intrinsics;
pub mod lower_slice_len;
pub mod match_branches;
pub mod multiple_return_terminators;
pub mod no_landing_pads;
pub mod nrvo;
pub mod promote_consts;
pub mod remove_noop_landing_pads;
@@ -451,7 +451,6 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[
// Remove all things only needed by analysis
&no_landing_pads::NoLandingPads,
&simplify_branches::SimplifyBranches::new("initial"),
&remove_noop_landing_pads::RemoveNoopLandingPads,
&cleanup_post_borrowck::CleanupNonCodegenStatements,
@@ -459,7 +458,6 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
// These next passes must be executed together
&add_call_guards::CriticalCallEdges,
&elaborate_drops::ElaborateDrops,
&no_landing_pads::NoLandingPads,
// AddMovesForPackedDrops needs to run after drop
// elaboration.
&add_moves_for_packed_drops::AddMovesForPackedDrops,
@@ -530,6 +528,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[
// This will remove extraneous landing pads which are no longer
// necessary as well as well as forcing any call in a non-unwinding
// function calling a possibly-unwinding function to abort the process.
&abort_unwinding_calls::AbortUnwindingCalls,
&add_call_guards::CriticalCallEdges,
// Dump the end result for testing and debugging purposes.
&dump_mir::Marker("PreCodegen"),