-
-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Lower #[no_mangle] to #[symbol_name]/#[link_name] #159374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1fee4f7
4125bce
104c06c
22ac858
afdcdc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,8 +93,19 @@ fn process_builtin_attrs( | |
| AttributeKind::LinkSection { name } => codegen_fn_attrs.link_section = Some(*name), | ||
| AttributeKind::NoMangle(attr_span) => { | ||
| interesting_spans.no_mangle = Some(*attr_span); | ||
| if tcx.opt_item_name(did.to_def_id()).is_some() { | ||
| codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; | ||
| if let Some(name) = tcx.opt_item_name(did.to_def_id()) { | ||
| // Don't override #[export_name]. | ||
|
|
||
| // Also don't override #[link_name]. All places where #[link_name] is allowed | ||
| // shouldn't allow #[no_mangle], so #[link_name] shouldn't be a concern here, | ||
| // however currently #[no_mangle] is currently merely a warning on foreign | ||
| // items rather than a hard error, so we still need to take #[no_mangle] + | ||
| // #[link_name] into account. | ||
| // FIXME remove this comment once #[no_mangle] on foreign items is a hard error. | ||
|
|
||
| if codegen_fn_attrs.symbol_name.is_none() { | ||
| codegen_fn_attrs.symbol_name = Some(name); | ||
| } | ||
| } else { | ||
| tcx.dcx() | ||
| .span_delayed_bug(*attr_span, "no_mangle should be on a named function"); | ||
|
|
@@ -402,6 +413,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code | |
| // get the same symbol name as the *mangled* foreign item they refer to so that's all good. | ||
| } else if codegen_fn_attrs.symbol_name.is_some() { | ||
| // * This can be overridden with the `#[link_name]` attribute | ||
| } else if codegen_fn_attrs.link_ordinal.is_some() { | ||
| // * `#[link_ordinal]` and `#[link_name]` are incompatible with each other | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a behavior change. We no longer keep the symbol that Rust code refers to unmangled when
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that makes sense, what's the process here? Nominate for t-lang and let them decide whether to accept this change?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally, separate refactors from behavior changes. Doing both in the same PR makes things more complicated to manage.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is non-trivial to keep the old behavior after this refactor. I could open a PR to change the behavior first.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that would be better, yeah.
It is unclear to me whether you are calling the old or new behavior inconsistent here.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think the current PR is small enough to get away with this, no need to split it up here. However, you can probably simplify much more by lowering into the same attribute during attribute parsing instead. (that would be a more intrusive change where refactors and behavior changes should be split)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The old behavior is consistent with non-ordinal imports on windows. The new behavior is consistent with imports on wasm, but not with non-ordinal imports on windows.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand how this comment explains why we should keep the symbol name unset here. |
||
| } else { | ||
| // NOTE: there's one more exception that we cannot apply here. On wasm, | ||
| // some items cannot be `no_mangle`. | ||
|
|
@@ -410,7 +423,7 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code | |
| // import will *still* be mangled despite this. | ||
| // | ||
| // if none of the exceptions apply; apply no_mangle | ||
| codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; | ||
| codegen_fn_attrs.symbol_name = Some(tcx.item_name(did)); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -543,22 +556,24 @@ fn handle_lang_items( | |
| // strippable by the linker. | ||
| // | ||
| // Additionally weak lang items have predetermined symbol names. | ||
| if let Some(lang_item) = lang_item | ||
| let link_name_override = if let Some(lang_item) = lang_item | ||
| && let Some(link_name) = lang_item.link_name() | ||
| { | ||
| codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; | ||
| codegen_fn_attrs.symbol_name = Some(link_name); | ||
| } | ||
| Some(link_name) | ||
| } else { | ||
| None | ||
| }; | ||
|
|
||
| // error when using no_mangle on a lang item item | ||
| // error when using no_mangle, or export_name on a lang item item | ||
| if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) | ||
| && codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) | ||
| && codegen_fn_attrs.symbol_name.is_some() | ||
| { | ||
| let mut err = tcx | ||
| .dcx() | ||
| .struct_span_err( | ||
| interesting_spans.no_mangle.unwrap_or_default(), | ||
| "`#[no_mangle]` cannot be used on internal language items", | ||
| "`#[no_mangle]` and `#[export_name]` cannot be used on internal language items", | ||
| ) | ||
| .with_note("Rustc requires this item to have a specific mangled name.") | ||
| .with_span_label(tcx.def_span(did), "should be the internal language item"); | ||
|
|
@@ -574,6 +589,10 @@ fn handle_lang_items( | |
| } | ||
| err.emit(); | ||
| } | ||
|
|
||
| if let Some(link_name_override) = link_name_override { | ||
| codegen_fn_attrs.symbol_name = Some(link_name_override); | ||
| } | ||
| } | ||
|
|
||
| /// Generate the [`CodegenFnAttrs`] for an item (identified by the [`LocalDefId`]). | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what way do
no_mangleandlink_nameinteract when it looks like they're not allowed to be on the same item?emits the
unused_attributeslint, so I expect it to do nothing there.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that
no_mangleisn't yet a hard error inside extern blocks. Bothexport_name(and by extensionno_mangle) andlink_namewrite to the samesymbol_namefield incodegen_fn_attrs, so without this check, I think the following would result inwrong_nameas name rather thancorrect_nameas#[unsafe(no_mangle)]runs second and overrides thesymbol_nameset by#[unsafe(link_name)].There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. Can you add a comment about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done