-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Use decorated names for linked_symbols on Windows #96444
Changes from all commits
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 |
---|---|---|
|
@@ -12,7 +12,7 @@ use rustc_middle::middle::exported_symbols::{ | |
use rustc_middle::ty::query::{ExternProviders, Providers}; | ||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; | ||
use rustc_middle::ty::Instance; | ||
use rustc_middle::ty::{SymbolName, TyCtxt}; | ||
use rustc_middle::ty::{self, SymbolName, TyCtxt}; | ||
use rustc_session::config::CrateType; | ||
use rustc_target::spec::SanitizerSet; | ||
|
||
|
@@ -493,6 +493,76 @@ pub fn symbol_name_for_instance_in_crate<'tcx>( | |
} | ||
} | ||
|
||
/// This is the symbol name of the given instance as seen by the linker. | ||
/// | ||
/// On 32-bit Windows symbols are decorated according to their calling conventions. | ||
pub fn linking_symbol_name_for_instance_in_crate<'tcx>( | ||
tcx: TyCtxt<'tcx>, | ||
symbol: ExportedSymbol<'tcx>, | ||
instantiating_crate: CrateNum, | ||
) -> String { | ||
use rustc_target::abi::call::Conv; | ||
|
||
let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate); | ||
|
||
let target = &tcx.sess.target; | ||
if !target.is_like_windows { | ||
// Mach-O has a global "_" suffix and `object` crate will handle it. | ||
// ELF does not have any symbol decorations. | ||
return undecorated; | ||
} | ||
|
||
let x86 = match &target.arch[..] { | ||
"x86" => true, | ||
"x86_64" => false, | ||
// Only x86/64 use symbol decorations. | ||
_ => return undecorated, | ||
}; | ||
|
||
let instance = match symbol { | ||
ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _) | ||
if tcx.is_static(def_id) => | ||
{ | ||
None | ||
} | ||
ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)), | ||
ExportedSymbol::Generic(def_id, substs) => Some(Instance::new(def_id, substs)), | ||
// DropGlue always use the Rust calling convention and thus follow the target's default | ||
// symbol decoration scheme. | ||
ExportedSymbol::DropGlue(..) => None, | ||
// NoDefId always follow the target's default symbol decoration scheme. | ||
ExportedSymbol::NoDefId(..) => None, | ||
}; | ||
|
||
let (conv, args) = instance | ||
.map(|i| { | ||
tcx.fn_abi_of_instance(ty::ParamEnv::reveal_all().and((i, ty::List::empty()))) | ||
.unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed")) | ||
}) | ||
.map(|fnabi| (fnabi.conv, &fnabi.args[..])) | ||
.unwrap_or((Conv::Rust, &[])); | ||
|
||
// Decorate symbols with prefices, suffices and total number of bytes of arguments. | ||
// Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170 | ||
let (prefix, suffix) = match conv { | ||
Conv::X86Fastcall => ("@", "@"), | ||
Conv::X86Stdcall => ("_", "@"), | ||
Conv::X86VectorCall => ("", "@@"), | ||
_ => { | ||
if x86 { | ||
undecorated.insert(0, '_'); | ||
} | ||
return undecorated; | ||
} | ||
}; | ||
|
||
let args_in_bytes: u64 = args | ||
.iter() | ||
.map(|abi| abi.layout.size.bytes().next_multiple_of(target.pointer_width as u64 / 8)) | ||
.sum(); | ||
format!("{prefix}{undecorated}{suffix}{args_in_bytes}") | ||
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've seen this logic elsewhere, it's split into Could you make sure these two implementations do the same thing? 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 just checked that the current behaviour in i686_decorated_name to not add There are no other behavioural differences. |
||
} | ||
|
||
fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId, String> { | ||
// Build up a map from DefId to a `NativeLib` structure, where | ||
// `NativeLib` internally contains information about | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// build-pass | ||
// only-x86-windows | ||
#![crate_type = "cdylib"] | ||
#![feature(abi_vectorcall)] | ||
|
||
#[no_mangle] | ||
extern "stdcall" fn foo(_: bool) {} | ||
|
||
#[no_mangle] | ||
extern "fastcall" fn bar(_: u8) {} | ||
|
||
#[no_mangle] | ||
extern "vectorcall" fn baz(_: u16) {} |
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.
Looks like this case also always results in undecorated names.
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.
x86_64 code can still use "vectorcall" convention
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 linked MS doc says "Note that in a 64-bit environment, functions are not decorated.", apparently it applies to vectorcall too?
Raw-dylib didn't attempt to support vector call yet, so I don't know what is the correct behavior 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.
That's an inaccurate statement, it should rather say that functions are not decorated by default. Vector call is still a separate calling convention on x64 however, and is still decorated (https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-170, https://godbolt.org/z/asdbdzePz)
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.
Yeah, I was aware of that, but wasn't sure about the decoration.
Just checked it with Visual Studio's C compiler, and looks like it's indeed the only calling convention that is decorated on x64.
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.
Filed MicrosoftDocs/cpp-docs#3854
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.
Ha, I didn't even know this stuff is in open source now.