Skip to content

Commit 74c0931

Browse files
committed
Implement intrinsics with fallback bodies
1 parent d53f4ab commit 74c0931

File tree

11 files changed

+70
-62
lines changed

11 files changed

+70
-62
lines changed

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
787787

788788
// Handle intrinsics old codegen wants Expr's for, ourselves.
789789
let intrinsic = match def {
790-
Some(ty::InstanceDef::Intrinsic(def_id)) => Some(bx.tcx().item_name(def_id)),
790+
Some(ty::InstanceDef::Intrinsic(def_id)) => Some(bx.tcx().intrinsic(def_id).unwrap()),
791791
_ => None,
792792
};
793793

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
791791
rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing,
792792
"the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe"
793793
),
794+
rustc_attr!(
795+
rustc_intrinsic, Normal, template!(List: "value"), ErrorFollowing,
796+
"the `#[rustc_intrinsic]` attribute is used to declare intrinsics with function bodies",
797+
),
794798

795799
// ==========================================================================
796800
// Internal attributes, Testing:

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,8 +1744,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
17441744
self.root.tables.attr_flags.get(self, index)
17451745
}
17461746

1747-
fn get_intrinsic(self, index: DefIndex) -> bool {
1748-
self.root.tables.intrinsic.get(self, index)
1747+
fn get_intrinsic(self, index: DefIndex) -> Option<Symbol> {
1748+
self.root.tables.intrinsic.get(self, index).map(|d| d.decode(self))
17491749
}
17501750

17511751
fn get_doc_link_resolutions(self, index: DefIndex) -> DocLinkResMap {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ provide! { tcx, def_id, other, cdata,
346346
cdata.get_stability_implications(tcx).iter().copied().collect()
347347
}
348348
stripped_cfg_items => { cdata.get_stripped_cfg_items(cdata.cnum, tcx) }
349-
intrinsic => { cdata.get_intrinsic(def_id.index).then(|| tcx.item_name(def_id)) }
349+
intrinsic => { cdata.get_intrinsic(def_id.index) }
350350
defined_lang_items => { cdata.get_lang_items(tcx) }
351351
diagnostic_items => { cdata.get_diagnostic_items() }
352352
missing_lang_items => { cdata.get_missing_lang_items(tcx) }

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1417,7 +1417,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14171417
if let DefKind::Fn | DefKind::AssocFn = def_kind {
14181418
self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id));
14191419
record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id));
1420-
self.tables.intrinsic.set(def_id.index, tcx.intrinsic(def_id).is_some());
1420+
if let Some(name) = tcx.intrinsic(def_id) {
1421+
record!(self.tables.intrinsic[def_id] <- name);
1422+
}
14211423
}
14221424
if let DefKind::TyParam = def_kind {
14231425
let default = self.tcx.object_lifetime_default(def_id);

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ macro_rules! define_tables {
375375

376376
define_tables! {
377377
- defaulted:
378-
intrinsic: Table<DefIndex, bool>,
378+
intrinsic: Table<DefIndex, Option<LazyValue<Symbol>>>,
379379
is_macro_rules: Table<DefIndex, bool>,
380380
is_type_alias_impl_trait: Table<DefIndex, bool>,
381381
type_alias_is_lazy: Table<DefIndex, bool>,

compiler/rustc_middle/src/ty/util.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,13 @@ pub fn intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Symbol> {
15431543
if matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
15441544
{
15451545
Some(tcx.item_name(def_id.into()))
1546+
} else if let Some(name) = tcx.get_attr(def_id, sym::rustc_intrinsic) {
1547+
Some(
1548+
name.get_normal_item().meta(rustc_span::DUMMY_SP).unwrap().meta_item_list().unwrap()[0]
1549+
.ident()
1550+
.unwrap()
1551+
.name,
1552+
)
15461553
} else {
15471554
None
15481555
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,6 +1411,7 @@ symbols! {
14111411
rustc_if_this_changed,
14121412
rustc_inherit_overflow_checks,
14131413
rustc_insignificant_dtor,
1414+
rustc_intrinsic,
14141415
rustc_layout,
14151416
rustc_layout_scalar_valid_range_end,
14161417
rustc_layout_scalar_valid_range_start,

library/core/src/intrinsics.rs

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,63 +2518,59 @@ extern "rust-intrinsic" {
25182518
G: FnOnce<ARG, Output = RET>,
25192519
F: FnOnce<ARG, Output = RET>;
25202520

2521-
/// Returns whether the argument's value is statically known at
2522-
/// compile-time.
2523-
///
2524-
/// This is useful when there is a way of writing the code that will
2525-
/// be *faster* when some variables have known values, but *slower*
2526-
/// in the general case: an `if is_val_statically_known(var)` can be used
2527-
/// to select between these two variants. The `if` will be optimized away
2528-
/// and only the desired branch remains.
2529-
///
2530-
/// Formally speaking, this function non-deterministically returns `true`
2531-
/// or `false`, and the caller has to ensure sound behavior for both cases.
2532-
/// In other words, the following code has *Undefined Behavior*:
2533-
///
2534-
/// ```no_run
2535-
/// #![feature(is_val_statically_known)]
2536-
/// #![feature(core_intrinsics)]
2537-
/// # #![allow(internal_features)]
2538-
/// use std::hint::unreachable_unchecked;
2539-
/// use std::intrinsics::is_val_statically_known;
2540-
///
2541-
/// unsafe {
2542-
/// if !is_val_statically_known(0) { unreachable_unchecked(); }
2543-
/// }
2544-
/// ```
2545-
///
2546-
/// This also means that the following code's behavior is unspecified; it
2547-
/// may panic, or it may not:
2548-
///
2549-
/// ```no_run
2550-
/// #![feature(is_val_statically_known)]
2551-
/// #![feature(core_intrinsics)]
2552-
/// # #![allow(internal_features)]
2553-
/// use std::intrinsics::is_val_statically_known;
2554-
///
2555-
/// unsafe {
2556-
/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0));
2557-
/// }
2558-
/// ```
2559-
///
2560-
/// Unsafe code may not rely on `is_val_statically_known` returning any
2561-
/// particular value, ever. However, the compiler will generally make it
2562-
/// return `true` only if the value of the argument is actually known.
2563-
///
2564-
/// When calling this in a `const fn`, both paths must be semantically
2565-
/// equivalent, that is, the result of the `true` branch and the `false`
2566-
/// branch must return the same value and have the same side-effects *no
2567-
/// matter what*.
2568-
#[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")]
2569-
#[rustc_nounwind]
2570-
#[cfg(not(bootstrap))]
2571-
pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
25722521
}
25732522

2574-
// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable`
2575-
// and thus compiling stage0 core doesn't work.
2523+
/// Returns whether the argument's value is statically known at
2524+
/// compile-time.
2525+
///
2526+
/// This is useful when there is a way of writing the code that will
2527+
/// be *faster* when some variables have known values, but *slower*
2528+
/// in the general case: an `if is_val_statically_known(var)` can be used
2529+
/// to select between these two variants. The `if` will be optimized away
2530+
/// and only the desired branch remains.
2531+
///
2532+
/// Formally speaking, this function non-deterministically returns `true`
2533+
/// or `false`, and the caller has to ensure sound behavior for both cases.
2534+
/// In other words, the following code has *Undefined Behavior*:
2535+
///
2536+
/// ```no_run
2537+
/// #![feature(is_val_statically_known)]
2538+
/// #![feature(core_intrinsics)]
2539+
/// # #![allow(internal_features)]
2540+
/// use std::hint::unreachable_unchecked;
2541+
/// use std::intrinsics::is_val_statically_known;
2542+
///
2543+
/// unsafe {
2544+
/// if !is_val_statically_known(0) { unreachable_unchecked(); }
2545+
/// }
2546+
/// ```
2547+
///
2548+
/// This also means that the following code's behavior is unspecified; it
2549+
/// may panic, or it may not:
2550+
///
2551+
/// ```no_run
2552+
/// #![feature(is_val_statically_known)]
2553+
/// #![feature(core_intrinsics)]
2554+
/// # #![allow(internal_features)]
2555+
/// use std::intrinsics::is_val_statically_known;
2556+
///
2557+
/// unsafe {
2558+
/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0));
2559+
/// }
2560+
/// ```
2561+
///
2562+
/// Unsafe code may not rely on `is_val_statically_known` returning any
2563+
/// particular value, ever. However, the compiler will generally make it
2564+
/// return `true` only if the value of the argument is actually known.
2565+
///
2566+
/// When calling this in a `const fn`, both paths must be semantically
2567+
/// equivalent, that is, the result of the `true` branch and the `false`
2568+
/// branch must return the same value and have the same side-effects *no
2569+
/// matter what*.
2570+
#[rustc_nounwind]
2571+
#[unstable(feature = "core_intrinsics", issue = "none")]
25762572
#[rustc_const_stable(feature = "is_val_statically_known", since = "0.0.0")]
2577-
#[cfg(bootstrap)]
2573+
#[cfg_attr(not(bootstrap), rustc_intrinsic(is_val_statically_known))]
25782574
pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
25792575
false
25802576
}

library/core/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,6 @@
200200
//
201201
// Language features:
202202
// tidy-alphabetical-start
203-
#![cfg_attr(not(bootstrap), feature(is_val_statically_known))]
204203
#![feature(abi_unadjusted)]
205204
#![feature(adt_const_params)]
206205
#![feature(allow_internal_unsafe)]

tests/ui/consts/is_val_statically_known.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// run-pass
22

33
#![feature(core_intrinsics)]
4-
#![feature(is_val_statically_known)]
54

65
use std::intrinsics::is_val_statically_known;
76

0 commit comments

Comments
 (0)