Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e0da778

Browse files
committedSep 27, 2024
Stash the new query alongside has_ffi_unwind_calls
1 parent 3f46a8e commit e0da778

File tree

12 files changed

+77
-37
lines changed

12 files changed

+77
-37
lines changed
 

‎compiler/rustc_interface/src/passes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
808808
});
809809
sess.time("MIR_effect_checking", || {
810810
for def_id in tcx.hir().body_owners() {
811-
tcx.ensure().has_ffi_unwind_calls(def_id);
811+
tcx.ensure().mir_flags(def_id);
812812

813813
// If we need to codegen, ensure that we emit all errors from
814814
// `mir_drops_elaborated_and_const_checked` now, to avoid discovering

‎compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ provide! { tcx, def_id, other, cdata,
352352
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
353353
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
354354
cross_crate_inlinable => { table_direct }
355-
is_nounwind => { table_direct }
355+
mir_flags => { table_direct }
356356

357357
dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) }
358358
is_private_dep => { cdata.private_dep }

‎compiler/rustc_metadata/src/rmeta/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
2424
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
2525
use rustc_middle::middle::lib_features::FeatureStability;
2626
use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
27+
use rustc_middle::mir::MirFlags;
2728
use rustc_middle::ty::fast_reject::SimplifiedType;
2829
use rustc_middle::ty::{
2930
self, DeducedParamAttrs, ParameterizedOverTcx, ReprOptions, Ty, TyCtxt, UnusedGenericParams,
@@ -404,7 +405,7 @@ define_tables! {
404405
// individually instead of `DefId`s.
405406
module_children_reexports: Table<DefIndex, LazyArray<ModChild>>,
406407
cross_crate_inlinable: Table<DefIndex, bool>,
407-
is_nounwind: Table<DefIndex, bool>,
408+
mir_flags: Table<DefIndex, MirFlags>,
408409

409410
- optional:
410411
attributes: Table<DefIndex, LazyArray<ast::Attribute>>,

‎compiler/rustc_metadata/src/rmeta/table.rs

+21
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ impl IsDefault for UnusedGenericParams {
5454
}
5555
}
5656

57+
impl IsDefault for MirFlags {
58+
fn is_default(&self) -> bool {
59+
*self == Self::default()
60+
}
61+
}
62+
5763
/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
5864
/// Used mainly for Lazy positions and lengths.
5965
/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`,
@@ -285,6 +291,21 @@ impl FixedSizeEncoding for AttrFlags {
285291
}
286292
}
287293

294+
impl FixedSizeEncoding for MirFlags {
295+
type ByteArray = [u8; 1];
296+
297+
#[inline]
298+
fn from_bytes(b: &[u8; 1]) -> Self {
299+
MirFlags::from_bits_truncate(b[0])
300+
}
301+
302+
#[inline]
303+
fn write_to_bytes(self, b: &mut [u8; 1]) {
304+
debug_assert!(!self.is_default());
305+
b[0] = self.bits();
306+
}
307+
}
308+
288309
impl FixedSizeEncoding for bool {
289310
type ByteArray = [u8; 1];
290311

‎compiler/rustc_middle/src/mir/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,15 @@ impl DefLocation {
17811781
}
17821782
}
17831783

1784+
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
1785+
pub struct MirFlags(u8);
1786+
bitflags::bitflags! {
1787+
impl MirFlags: u8 {
1788+
const IS_NOUNWIND = 1 << 0;
1789+
const HAS_FFI_UNWIND_CALLS = 1 << 1;
1790+
}
1791+
}
1792+
17841793
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
17851794
#[cfg(target_pointer_width = "64")]
17861795
mod size_asserts {

‎compiler/rustc_middle/src/query/erase.rs

+1
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ trivial! {
283283
rustc_middle::middle::resolve_bound_vars::ResolvedArg,
284284
rustc_middle::middle::stability::DeprecationEntry,
285285
rustc_middle::mir::ConstQualifs,
286+
rustc_middle::mir::MirFlags,
286287
rustc_middle::mir::interpret::AllocId,
287288
rustc_middle::mir::interpret::CtfeProvenance,
288289
rustc_middle::mir::interpret::ErrorHandled,

‎compiler/rustc_middle/src/query/mod.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use crate::middle::lib_features::LibFeatures;
5454
use crate::middle::privacy::EffectiveVisibilities;
5555
use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
5656
use crate::middle::stability::{self, DeprecationEntry};
57+
use crate::mir::MirFlags;
5758
use crate::mir::interpret::{
5859
EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
5960
EvalToValTreeResult, GlobalId, LitToConstError, LitToConstInput,
@@ -1495,12 +1496,9 @@ rustc_queries! {
14951496
desc { "checking if a crate is `#![profiler_runtime]`" }
14961497
separate_provide_extern
14971498
}
1498-
query has_ffi_unwind_calls(key: LocalDefId) -> bool {
1499-
desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key) }
1499+
query mir_flags(key: DefId) -> MirFlags {
1500+
desc { |tcx| "stashing some local properties of `{}` before the body is stolen", tcx.def_path_str(key) }
15001501
cache_on_disk_if { true }
1501-
}
1502-
query is_nounwind(key: DefId) -> bool {
1503-
desc { |tcx| "checking if `{}` contains unwinds", tcx.def_path_str(key) }
15041502
separate_provide_extern
15051503
}
15061504
query required_panic_strategy(_: CrateNum) -> Option<PanicStrategy> {

‎compiler/rustc_middle/src/ty/context.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ use crate::metadata::ModChild;
6666
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
6767
use crate::middle::{resolve_bound_vars, stability};
6868
use crate::mir::interpret::{self, Allocation, ConstAllocation};
69-
use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
69+
use crate::mir::{Body, Local, MirFlags, Place, PlaceElem, ProjectionKind, Promoted};
7070
use crate::query::plumbing::QuerySystem;
7171
use crate::query::{IntoQueryParam, LocalCrate, Providers, TyCtxtAt};
7272
use crate::thir::Thir;
@@ -3180,6 +3180,14 @@ impl<'tcx> TyCtxt<'tcx> {
31803180
}
31813181
}
31823182

3183+
pub fn is_nounwind(self, def_id: DefId) -> bool {
3184+
self.mir_flags(def_id).contains(MirFlags::IS_NOUNWIND)
3185+
}
3186+
3187+
pub fn has_ffi_unwind_calls(self, def_id: DefId) -> bool {
3188+
self.mir_flags(def_id).contains(MirFlags::HAS_FFI_UNWIND_CALLS)
3189+
}
3190+
31833191
/// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
31843192
pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
31853193
self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some()

‎compiler/rustc_middle/src/ty/parameterized.rs

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ trivially_parameterized_over_tcx! {
9696
rustc_hir::definitions::DefKey,
9797
rustc_index::bit_set::BitSet<u32>,
9898
rustc_index::bit_set::FiniteBitSet<u32>,
99+
rustc_middle::mir::MirFlags,
99100
rustc_session::cstore::ForeignModule,
100101
rustc_session::cstore::LinkagePreference,
101102
rustc_session::cstore::NativeLib,

‎compiler/rustc_mir_transform/src/ffi_unwind_calls.rs

+6-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_hir::def_id::{LOCAL_CRATE, LocalDefId};
1+
use rustc_hir::def_id::LOCAL_CRATE;
22
use rustc_middle::mir::*;
33
use rustc_middle::query::{LocalCrate, Providers};
44
use rustc_middle::ty::{self, TyCtxt, layout};
@@ -11,17 +11,10 @@ use tracing::debug;
1111
use crate::errors;
1212

1313
// Check if the body of this def_id can possibly leak a foreign unwind into Rust code.
14-
fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
15-
debug!("has_ffi_unwind_calls({local_def_id:?})");
14+
pub(crate) fn has_ffi_unwind_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
15+
let def_id = body.source.def_id();
1616

17-
// Only perform check on functions because constants cannot call FFI functions.
18-
let def_id = local_def_id.to_def_id();
19-
let kind = tcx.def_kind(def_id);
20-
if !kind.is_fn_like() {
21-
return false;
22-
}
23-
24-
let body = &*tcx.mir_built(local_def_id).borrow();
17+
debug!("has_ffi_unwind_calls({def_id:?})");
2518

2619
let body_ty = tcx.type_of(def_id).skip_binder();
2720
let body_abi = match body_ty.kind() {
@@ -108,7 +101,7 @@ fn required_panic_strategy(tcx: TyCtxt<'_>, _: LocalCrate) -> Option<PanicStrate
108101
}
109102

110103
for def_id in tcx.hir().body_owners() {
111-
if tcx.has_ffi_unwind_calls(def_id) {
104+
if tcx.has_ffi_unwind_calls(def_id.into()) {
112105
// Given that this crate is compiled in `-C panic=unwind`, the `AbortUnwindingCalls`
113106
// MIR pass will not be run on FFI-unwind call sites, therefore a foreign exception
114107
// can enter Rust through these sites.
@@ -139,5 +132,5 @@ fn required_panic_strategy(tcx: TyCtxt<'_>, _: LocalCrate) -> Option<PanicStrate
139132
}
140133

141134
pub(crate) fn provide(providers: &mut Providers) {
142-
*providers = Providers { has_ffi_unwind_calls, required_panic_strategy, ..*providers };
135+
*providers = Providers { required_panic_strategy, ..*providers };
143136
}

‎compiler/rustc_mir_transform/src/lib.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ use rustc_hir::def_id::LocalDefId;
2626
use rustc_index::IndexVec;
2727
use rustc_middle::mir::{
2828
AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, LocalDecl,
29-
MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, START_BLOCK,
30-
SourceInfo, Statement, StatementKind, TerminatorKind,
29+
MirFlags, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue,
30+
START_BLOCK, SourceInfo, Statement, StatementKind, TerminatorKind,
3131
};
3232
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
3333
use rustc_middle::util::Providers;
@@ -134,7 +134,7 @@ pub fn provide(providers: &mut Providers) {
134134
promoted_mir,
135135
deduced_param_attrs: deduce_param_attrs::deduced_param_attrs,
136136
coroutine_by_move_body_def_id: coroutine::coroutine_by_move_body_def_id,
137-
is_nounwind,
137+
mir_flags,
138138
..providers.queries
139139
};
140140
}
@@ -331,15 +331,14 @@ fn mir_promoted(
331331
_ => ConstQualifs::default(),
332332
};
333333

334-
// the `has_ffi_unwind_calls` query uses the raw mir, so make sure it is run.
335-
tcx.ensure_with_value().has_ffi_unwind_calls(def);
334+
tcx.ensure_with_value().mir_flags(def);
336335

337336
// the `by_move_body` query uses the raw mir, so make sure it is run.
338337
if tcx.needs_coroutine_by_move_body_def_id(def.to_def_id()) {
339338
tcx.ensure_with_value().coroutine_by_move_body_def_id(def);
340339
}
341340

342-
tcx.ensure_with_value().is_nounwind(def);
341+
tcx.ensure_with_value().mir_flags(def);
343342

344343
let mut body = tcx.mir_built(def).steal();
345344
if let Some(error_reported) = const_qualifs.tainted_by_errors {
@@ -363,22 +362,31 @@ fn mir_promoted(
363362
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
364363
}
365364

366-
fn is_nounwind<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> bool {
365+
fn mir_flags<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> MirFlags {
366+
let mut flags = MirFlags::default();
367367
if !tcx.is_mir_available(local_def_id) {
368-
return false;
368+
return flags;
369369
}
370370

371-
let def_id = local_def_id.to_def_id();
372-
let kind = tcx.def_kind(def_id);
371+
// Only perform check on functions because constants cannot call FFI functions.
372+
let kind = tcx.def_kind(local_def_id);
373373
if !kind.is_fn_like() {
374-
return false;
374+
return flags;
375375
}
376376

377377
let body = &*tcx.mir_built(local_def_id).borrow();
378-
if body.basic_blocks.iter().all(|block| block.terminator().unwind().is_none()) {
379-
return true;
378+
379+
if is_nounwind(body) {
380+
flags.insert(MirFlags::IS_NOUNWIND);
381+
}
382+
if ffi_unwind_calls::has_ffi_unwind_calls(tcx, body) {
383+
flags.insert(MirFlags::HAS_FFI_UNWIND_CALLS);
380384
}
381-
false
385+
flags
386+
}
387+
388+
fn is_nounwind<'tcx>(body: &Body<'tcx>) -> bool {
389+
body.basic_blocks.iter().all(|block| block.terminator().unwind().is_none())
382390
}
383391

384392
/// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)

‎tests/ui/coroutine/clone-rpit.next.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
1414
|
1515
LL | move |_: ()| {
1616
| ^^^^^^^^^^^^
17-
note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
17+
note: ...which requires stashing some local properties of `foo::{closure#0}` before the body is stolen...
1818
--> $DIR/clone-rpit.rs:15:5
1919
|
2020
LL | move |_: ()| {

0 commit comments

Comments
 (0)
Failed to load comments.