Skip to content

Commit afc1033

Browse files
authored
Unrolled build for rust-lang#126361
Rollup merge of rust-lang#126361 - celinval:issue-0079-intrinsic, r=oli-obk Unify intrinsics body handling in StableMIR rust-lang#120675 introduced a new mechanism to declare intrinsics which will potentially replace the rust-intrinsic ABI. The new mechanism introduces a placeholder body and mark the intrinsic with `#[rustc_intrinsic_must_be_overridden]`. In practice, this means that a backend should not generate code for the placeholder, and shim the intrinsic. The new annotation is an internal compiler implementation, and it doesn't need to be exposed to StableMIR users. In this PR, we unify the interface for intrinsics marked with `rustc_intrinsic_must_be_overridden` and intrinsics that do not have a body. Fixes rust-lang/project-stable-mir#79 r? ``@oli-obk`` cc: ``@momvart``
2 parents 687a68d + c8c6598 commit afc1033

File tree

5 files changed

+42
-25
lines changed

5 files changed

+42
-25
lines changed

compiler/rustc_smir/src/rustc_smir/context.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
6464
}
6565

6666
fn has_body(&self, def: DefId) -> bool {
67-
let tables = self.0.borrow();
68-
let def_id = tables[def];
69-
tables.tcx.is_mir_available(def_id)
67+
let mut tables = self.0.borrow_mut();
68+
let tcx = tables.tcx;
69+
let def_id = def.internal(&mut *tables, tcx);
70+
tables.item_has_body(def_id)
7071
}
7172

7273
fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignModuleDef> {
@@ -323,13 +324,6 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
323324
tcx.intrinsic(def_id).unwrap().name.to_string()
324325
}
325326

326-
fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool {
327-
let mut tables = self.0.borrow_mut();
328-
let tcx = tables.tcx;
329-
let def_id = def.0.internal(&mut *tables, tcx);
330-
tcx.intrinsic_raw(def_id).unwrap().must_be_overridden
331-
}
332-
333327
fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
334328
let mut tables = self.0.borrow_mut();
335329
let tcx = tables.tcx;
@@ -516,7 +510,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
516510
let mut tables = self.0.borrow_mut();
517511
let instance = tables.instances[def];
518512
tables
519-
.has_body(instance)
513+
.instance_has_body(instance)
520514
.then(|| BodyBuilder::new(tables.tcx, instance).build(&mut *tables))
521515
}
522516

compiler/rustc_smir/src/rustc_smir/mod.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,33 @@ impl<'tcx> Tables<'tcx> {
5151
self.mir_consts.create_or_fetch(constant)
5252
}
5353

54-
pub(crate) fn has_body(&self, instance: Instance<'tcx>) -> bool {
54+
/// Return whether the instance as a body available.
55+
///
56+
/// Items and intrinsics may have a body available from its definition.
57+
/// Shims body may be generated depending on their type.
58+
pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool {
5559
let def_id = instance.def_id();
56-
self.tcx.is_mir_available(def_id)
60+
self.item_has_body(def_id)
5761
|| !matches!(
5862
instance.def,
5963
ty::InstanceDef::Virtual(..)
6064
| ty::InstanceDef::Intrinsic(..)
6165
| ty::InstanceDef::Item(..)
6266
)
6367
}
68+
69+
/// Return whether the item has a body defined by the user.
70+
///
71+
/// Note that intrinsics may have a placeholder body that shouldn't be used in practice.
72+
/// In StableMIR, we handle this case as if the body is not available.
73+
pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
74+
let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) {
75+
intrinsic.must_be_overridden
76+
} else {
77+
false
78+
};
79+
!must_override && self.tcx.is_mir_available(def_id)
80+
}
6481
}
6582

6683
/// Build a stable mir crate from a given crate number.

compiler/stable_mir/src/compiler_interface.rs

-4
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,6 @@ pub trait Context {
9494
/// Retrieve the plain function name of an intrinsic.
9595
fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol;
9696

97-
/// Returns whether the intrinsic has no meaningful body and all backends
98-
/// need to shim all calls to it.
99-
fn intrinsic_must_be_overridden(&self, def: IntrinsicDef) -> bool;
100-
10197
/// Retrieve the closure signature for the given generic arguments.
10298
fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig;
10399

compiler/stable_mir/src/ty.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,11 @@ impl FnDef {
668668
with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0)))
669669
}
670670

671+
// Check if the function body is available.
672+
pub fn has_body(&self) -> bool {
673+
with(|ctx| ctx.has_body(self.0))
674+
}
675+
671676
/// Get the information of the intrinsic if this function is a definition of one.
672677
pub fn as_intrinsic(&self) -> Option<IntrinsicDef> {
673678
with(|cx| cx.intrinsic(self.def_id()))
@@ -700,7 +705,7 @@ impl IntrinsicDef {
700705
/// Returns whether the intrinsic has no meaningful body and all backends
701706
/// need to shim all calls to it.
702707
pub fn must_be_overridden(&self) -> bool {
703-
with(|cx| cx.intrinsic_must_be_overridden(*self))
708+
with(|cx| !cx.has_body(self.0))
704709
}
705710
}
706711

tests/ui-fulldeps/stable-mir/check_intrinsics.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,19 @@ fn test_intrinsics() -> ControlFlow<()> {
5555
///
5656
/// If by any chance this test breaks because you changed how an intrinsic is implemented, please
5757
/// update the test to invoke a different intrinsic.
58+
///
59+
/// In StableMIR, we only expose intrinsic body if they are not marked with
60+
/// `rustc_intrinsic_must_be_overridden`.
5861
fn check_instance(instance: &Instance) {
5962
assert_eq!(instance.kind, InstanceKind::Intrinsic);
6063
let name = instance.intrinsic_name().unwrap();
6164
if instance.has_body() {
6265
let Some(body) = instance.body() else { unreachable!("Expected a body") };
6366
assert!(!body.blocks.is_empty());
64-
assert_matches!(name.as_str(), "likely" | "vtable_size");
67+
assert_eq!(&name, "likely");
6568
} else {
6669
assert!(instance.body().is_none());
67-
assert_eq!(&name, "size_of_val");
70+
assert_matches!(name.as_str(), "size_of_val" | "vtable_size");
6871
}
6972
}
7073

@@ -75,11 +78,13 @@ fn check_def(fn_def: FnDef) {
7578

7679
let name = intrinsic.fn_name();
7780
match name.as_str() {
78-
"likely" | "size_of_val" => {
81+
"likely" => {
7982
assert!(!intrinsic.must_be_overridden());
83+
assert!(fn_def.has_body());
8084
}
81-
"vtable_size" => {
85+
"vtable_size" | "size_of_val" => {
8286
assert!(intrinsic.must_be_overridden());
87+
assert!(!fn_def.has_body());
8388
}
8489
_ => unreachable!("Unexpected intrinsic: {}", name),
8590
}
@@ -96,9 +101,9 @@ impl<'a> MirVisitor for CallsVisitor<'a> {
96101
TerminatorKind::Call { func, .. } => {
97102
let TyKind::RigidTy(RigidTy::FnDef(def, args)) =
98103
func.ty(self.locals).unwrap().kind()
99-
else {
100-
return;
101-
};
104+
else {
105+
return;
106+
};
102107
self.calls.push((def, args.clone()));
103108
}
104109
_ => {}

0 commit comments

Comments
 (0)