1extern crate indexmap;
2
3use indexmap::IndexMap;
4use rustc_hir::def_id::DefId;
5use rustc_middle::ty::TyCtxt;
6use rustc_public::{rustc_internal, CrateDef};
7use std::sync::OnceLock;
8
9static INIT: OnceLock<Intrinsics> = OnceLock::new();
10
11struct Intrinsics {
12 map: IndexMap<&'static str, DefId>,
13}
14
15pub fn init(tcx: TyCtxt) {
16 INIT.get_or_init(|| init_inner(tcx));
17}
18
19fn init_inner(tcx: TyCtxt) -> Intrinsics {
20 const CRATES: &[&str] = &["core", "std", "alloc"];
21
22 let mut map = IndexMap::with_capacity(INTRINSICS.len());
23 for krate in rustc_public::external_crates() {
24 if !CRATES.iter().any(|name| *name == krate.name) {
25 continue;
26 }
27 for fn_def in krate.fn_defs() {
28 let fn_name = fn_def.name();
29 if let Some(name) = INTRINSICS
30 .iter()
31 .find_map(|&name| (name == fn_name).then_some(name))
32 {
33 let def_id = rustc_internal::internal(tcx, fn_def.def_id());
35 if map.contains_key(name) {
36 panic!("DefId of {fn_name} has been inserted: {def_id:?}");
37 } else {
38 map.insert(name, def_id);
39 }
40 }
41 }
42 }
43
44 map.sort_unstable_by(|a, _, b, _| a.cmp(b));
45 assert_eq!(
46 INTRINSICS.len(),
47 map.len(),
48 "Intrinsic functions is incompletely retrieved.\n\
49 INTRINSICS = {INTRINSICS:#?}\nmap ={map:#?}"
50 );
51 Intrinsics { map }
53}
54
55macro_rules! intrinsics {
56 ($( $id:ident : $call:literal ,)+ ) => {
57 const INTRINSICS: &[&str] = &[$($call,)+];
58 $(
59 pub fn $id() -> DefId {
60 *INIT.get().expect("Intrinsics DefIds haven't been initialized.").map.get($call)
61 .unwrap_or_else(|| panic!("Failed to retrieve the DefId of {}.", $call))
62 }
63 )+
64 };
65}
66
67intrinsics! {
68 assume_init_drop: "std::mem::MaybeUninit::<T>::assume_init_drop",
69 call_mut: "std::ops::FnMut::call_mut",
70 clone: "std::clone::Clone::clone",
71 copy_from: "std::ptr::mut_ptr::<impl *mut T>::copy_from",
72 copy_from_nonoverlapping: "std::ptr::mut_ptr::<impl *mut T>::copy_from_nonoverlapping",
73 copy_to: "std::ptr::const_ptr::<impl *const T>::copy_to",
74 copy_to_nonoverlapping: "std::ptr::const_ptr::<impl *const T>::copy_to_nonoverlapping",
75 dealloc: "std::alloc::dealloc",
76 drop: "std::mem::drop",
77 drop_in_place: "std::ptr::drop_in_place",
78 manually_drop: "std::mem::ManuallyDrop::<T>::drop",
79}
80
81pub fn to_internal<T: CrateDef>(val: &T, tcx: TyCtxt) -> DefId {
83 rustc_internal::internal(tcx, val.def_id())
84}