Skip to content

Commit f024f19

Browse files
committed
Add declaration-only lang items for core runtime symbols
1 parent 800c67b commit f024f19

6 files changed

Lines changed: 102 additions & 13 deletions

File tree

compiler/rustc_hir/src/lang_items.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,14 @@ language_item_table! {
447447

448448
// Used to fallback `{float}` to `f32` when `f32: From<{float}>`
449449
From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1);
450+
451+
// Runtime symbols
452+
MemCpy, sym::memcpy_fn, memcpy_fn, Target::Fn, GenericRequirement::None;
453+
MemMove, sym::memmove_fn, memmove_fn, Target::Fn, GenericRequirement::None;
454+
MemSet, sym::memset_fn, memset_fn, Target::Fn, GenericRequirement::None;
455+
MemCmp, sym::memcmp_fn, memcmp_fn, Target::Fn, GenericRequirement::None;
456+
Bcmp, sym::bcmp_fn, bcmp_fn, Target::Fn, GenericRequirement::None;
457+
StrLen, sym::strlen_fn, strlen_fn, Target::Fn, GenericRequirement::None;
450458
}
451459

452460
/// The requirement imposed on the generics of a lang item

compiler/rustc_hir/src/weak_lang_items.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,29 @@ macro_rules! weak_lang_items {
2323
}
2424
}
2525

26+
macro_rules! decl_lang_items {
27+
($($item:ident,)*) => {
28+
pub static DECL_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*];
29+
30+
impl LangItem {
31+
pub fn is_decl(self) -> bool {
32+
matches!(self, $(LangItem::$item)|*)
33+
}
34+
}
35+
}
36+
}
37+
2638
weak_lang_items! {
2739
PanicImpl, rust_begin_unwind;
2840
EhPersonality, rust_eh_personality;
2941
EhCatchTypeinfo, rust_eh_catch_typeinfo;
3042
}
43+
44+
decl_lang_items! {
45+
MemCpy,
46+
MemMove,
47+
MemSet,
48+
MemCmp,
49+
Bcmp,
50+
StrLen,
51+
}

compiler/rustc_passes/src/lang_items.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ pub(crate) enum Duplicate {
2929
CrateDepends,
3030
}
3131

32+
enum CollectWeak {
33+
Allowed,
34+
Ignore,
35+
}
36+
3237
struct LanguageItemCollector<'ast, 'tcx> {
3338
items: LanguageItems,
3439
tcx: TyCtxt<'tcx>,
@@ -60,19 +65,23 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> {
6065
attrs: &'ast [ast::Attribute],
6166
item_span: Span,
6267
generics: Option<&'ast ast::Generics>,
68+
collect_weak: CollectWeak,
6369
) {
6470
if let Some((name, attr_span)) = extract_ast(attrs) {
6571
match LangItem::from_name(name) {
6672
// Known lang item with attribute on correct target.
6773
Some(lang_item) if actual_target == lang_item.target() => {
68-
self.collect_item_extended(
69-
lang_item,
70-
def_id,
71-
item_span,
72-
attr_span,
73-
generics,
74-
actual_target,
75-
);
74+
// Weak lang items are handled separately
75+
if !lang_item.is_weak() || matches!(collect_weak, CollectWeak::Allowed) {
76+
self.collect_item_extended(
77+
lang_item,
78+
def_id,
79+
item_span,
80+
attr_span,
81+
generics,
82+
actual_target,
83+
);
84+
}
7685
}
7786
// Known lang item with attribute on incorrect target.
7887
Some(lang_item) => {
@@ -299,20 +308,33 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
299308
&i.attrs,
300309
i.span,
301310
i.opt_generics(),
311+
CollectWeak::Allowed,
302312
);
303313

304314
let parent_item = self.parent_item.replace(i);
305315
visit::walk_item(self, i);
306316
self.parent_item = parent_item;
307317
}
308318

319+
fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) {
320+
self.check_for_lang(
321+
Target::Fn,
322+
self.resolver.node_id_to_def_id[&i.id],
323+
&i.attrs,
324+
i.span,
325+
None,
326+
CollectWeak::Ignore,
327+
);
328+
}
329+
309330
fn visit_variant(&mut self, variant: &'ast ast::Variant) {
310331
self.check_for_lang(
311332
Target::Variant,
312333
self.resolver.node_id_to_def_id[&variant.id],
313334
&variant.attrs,
314335
variant.span,
315336
None,
337+
CollectWeak::Allowed,
316338
);
317339
}
318340

@@ -352,6 +374,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> {
352374
&i.attrs,
353375
i.span,
354376
generics,
377+
CollectWeak::Allowed,
355378
);
356379

357380
visit::walk_assoc_item(self, i, ctxt);

compiler/rustc_passes/src/weak_lang_items.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,15 @@ struct WeakLangItemVisitor<'a, 'tcx> {
4848
impl<'ast> visit::Visitor<'ast> for WeakLangItemVisitor<'_, '_> {
4949
fn visit_foreign_item(&mut self, i: &'ast ast::ForeignItem) {
5050
if let Some((lang_item, _)) = extract_ast(&i.attrs) {
51-
if let Some(item) = LangItem::from_name(lang_item)
52-
&& item.is_weak()
53-
{
54-
if self.items.get(item).is_none() {
55-
self.items.missing.push(item);
51+
if let Some(item) = LangItem::from_name(lang_item) {
52+
if item.is_weak() {
53+
if self.items.get(item).is_none() {
54+
self.items.missing.push(item);
55+
}
56+
} else if item.is_decl() {
57+
// delc lang items are handled directly in lang_items.rs
58+
} else {
59+
self.tcx.dcx().emit_err(UnknownExternLangItem { span: i.span, lang_item });
5660
}
5761
} else {
5862
self.tcx.dcx().emit_err(UnknownExternLangItem { span: i.span, lang_item });

compiler/rustc_span/src/symbol.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ symbols! {
508508
backchain,
509509
backend_repr,
510510
bang,
511+
bcmp_fn,
511512
begin_panic,
512513
bench,
513514
bevy_ecs,
@@ -1248,7 +1249,11 @@ symbols! {
12481249
mem_variant_count,
12491250
mem_zeroed,
12501251
member_constraints,
1252+
memcmp_fn,
1253+
memcpy_fn,
1254+
memmove_fn,
12511255
memory,
1256+
memset_fn,
12521257
memtag,
12531258
message,
12541259
meta,
@@ -1983,6 +1988,7 @@ symbols! {
19831988
strict_provenance_lints,
19841989
string_deref_patterns,
19851990
stringify,
1991+
strlen_fn,
19861992
struct_field_attributes,
19871993
struct_inherit,
19881994
struct_variant,

library/core/src/ffi/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,30 @@ impl fmt::Debug for c_void {
9191
)]
9292
#[link(name = "/defaultlib:libcmt", modifiers = "+verbatim", cfg(target_feature = "crt-static"))]
9393
unsafe extern "C" {}
94+
95+
// Used by rustc for checking the definitions of other function with the same symbol names
96+
//
97+
// See the `invalid_runtime_symbols_definitions` lint.
98+
mod runtime_symbols {
99+
use crate::ffi::{c_char, c_int, c_void};
100+
101+
unsafe extern "C" {
102+
#[lang = "memcpy_fn"]
103+
fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
104+
105+
#[lang = "memmove_fn"]
106+
fn memmove(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
107+
108+
#[lang = "memset_fn"]
109+
fn memset(s: *mut c_void, c: c_int, n: usize) -> *mut c_void;
110+
111+
#[lang = "memcmp_fn"]
112+
fn memcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int;
113+
114+
#[lang = "bcmp_fn"]
115+
fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int;
116+
117+
#[lang = "strlen_fn"]
118+
fn strlen(s: *const c_char) -> usize;
119+
}
120+
}

0 commit comments

Comments
 (0)