From d735aa68107bbe4d617903f221088eeef92ee223 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 27 Apr 2022 18:58:59 +0800 Subject: [PATCH 1/8] Eliminate duplication of building panic langcall in codegen --- compiler/rustc_codegen_ssa/src/common.rs | 16 +++++++++----- compiler/rustc_codegen_ssa/src/mir/block.rs | 24 +++++---------------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index ae54442e884a8..94c63b98ff9a0 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -2,7 +2,6 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::LangItem; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt}; @@ -10,7 +9,6 @@ use rustc_session::Session; use rustc_span::Span; use crate::base; -use crate::traits::BuilderMethods; use crate::traits::*; pub enum IntPredicate { @@ -118,14 +116,22 @@ mod temp_stable_hash_impls { } } -pub fn langcall(tcx: TyCtxt<'_>, span: Option, msg: &str, li: LangItem) -> DefId { - tcx.lang_items().require(li).unwrap_or_else(|s| { +pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + bx: &Bx, + span: Option, + msg: &str, + li: LangItem, +) -> (Bx::FnAbiOfResult, Bx::Value) { + let tcx = bx.tcx(); + let def_id = tcx.lang_items().require(li).unwrap_or_else(|s| { let msg = format!("{} {}", msg, s); match span { Some(span) => tcx.sess.span_fatal(span, &msg), None => tcx.sess.fatal(&msg), } - }) + }); + let instance = ty::Instance::mono(tcx, def_id); + (bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance)) } // To avoid UB from LLVM, these two functions mask RHS with an diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index b7d760bfbabe1..9f28bc7138172 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -489,11 +489,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; - // Obtain the panic entry point. - let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); - let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); - let llfn = bx.get_fn_addr(instance); + let (fn_abi, llfn) = common::build_langcall(&bx, Some(span), "", lang_item); // Codegen the actual panic invoke/call. helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); @@ -509,10 +505,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.set_debug_loc(&mut bx, terminator.source_info); // Obtain the panic entry point. - let def_id = common::langcall(bx.tcx(), Some(span), "", LangItem::PanicNoUnwind); - let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); - let llfn = bx.get_fn_addr(instance); + let (fn_abi, llfn) = common::build_langcall(&bx, Some(span), "", LangItem::PanicNoUnwind); // Codegen the actual panic invoke/call. helper.do_call(self, &mut bx, fn_abi, llfn, &[], None, None); @@ -573,12 +566,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let location = self.get_caller_location(bx, source_info).immediate(); // Obtain the panic entry point. - // FIXME: dedup this with `codegen_assert_terminator` above. - let def_id = - common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic); - let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); - let llfn = bx.get_fn_addr(instance); + let (fn_abi, llfn) = + common::build_langcall(bx, Some(source_info.span), "", LangItem::Panic); // Codegen the actual panic invoke/call. helper.do_call( @@ -1440,10 +1429,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llretty = self.landing_pad_type(); bx.cleanup_landing_pad(llretty, llpersonality); - let def_id = common::langcall(bx.tcx(), None, "", LangItem::PanicNoUnwind); - let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); - let fn_ptr = bx.get_fn_addr(instance); + let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, "", LangItem::PanicNoUnwind); let fn_ty = bx.fn_decl_backend_type(&fn_abi); let llret = bx.call(fn_ty, fn_ptr, &[], None); From 4f9acb268704a1c7f78c8c55da0d7614eac57ade Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 26 Apr 2022 18:01:10 +0100 Subject: [PATCH 2/8] Use decorated names for linked_symbols on Windows --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 ++ compiler/rustc_codegen_ssa/src/back/linker.rs | 2 +- .../src/back/symbol_export.rs | 72 ++++++++++++++++++- compiler/rustc_codegen_ssa/src/lib.rs | 1 + src/test/ui/symbol-names/x86-stdcall.rs | 13 ++++ 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/symbol-names/x86-stdcall.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 743f6c0e5703d..54a69fcf68110 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1696,6 +1696,10 @@ fn add_linked_symbol_object( // so add an empty section. if file.format() == object::BinaryFormat::Coff { file.add_section(Vec::new(), ".text".into(), object::SectionKind::Text); + + // We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the + // default mangler in `object` crate. + file.set_mangling(object::write::Mangling::None); } for (sym, kind) in symbols.iter() { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 6e13e0d0e43b1..0805df5dad6bf 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1576,7 +1576,7 @@ pub(crate) fn linked_symbols( for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| { if info.level.is_below_threshold(export_threshold) || info.used { symbols.push(( - symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum), + symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum), info.kind, )); } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 3a416c8a2b54b..f651814be7ea6 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -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}") +} + fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap { // Build up a map from DefId to a `NativeLib` structure, where // `NativeLib` internally contains information about diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index d430800220930..05d32972dab17 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -7,6 +7,7 @@ #![feature(nll)] #![feature(associated_type_bounds)] #![feature(strict_provenance)] +#![feature(int_roundings)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/src/test/ui/symbol-names/x86-stdcall.rs b/src/test/ui/symbol-names/x86-stdcall.rs new file mode 100644 index 0000000000000..9948488c0e950 --- /dev/null +++ b/src/test/ui/symbol-names/x86-stdcall.rs @@ -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) {} From d51702ae8447137b6b0db1e0d05cee26f599ca37 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 27 Apr 2022 07:24:43 -0700 Subject: [PATCH 3/8] Update data layout string for wasm64-unknown-unknown Looks like this changed in a recent LLVM update but wasm64 isn't built on CI so it wasn't caught until now. Closes #96463 --- compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs index 609b7d42e43a1..6826c0ac62b3a 100644 --- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs @@ -36,7 +36,7 @@ pub fn target() -> Target { Target { llvm_target: "wasm64-unknown-unknown".into(), pointer_width: 64, - data_layout: "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20".into(), + data_layout: "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(), arch: "wasm64".into(), options, } From 762bb1f506fa0d239d0fb52234d3353b41645a8d Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Wed, 27 Apr 2022 15:56:29 -0400 Subject: [PATCH 4/8] Revert "impl From<&[T; N]> and From<&mut [T; N]> for Vec" This reverts commit 5dd702763ae0e112332a4447171adbed51aeee3d. --- library/alloc/src/vec/mod.rs | 42 ------------------------------------ 1 file changed, 42 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8c2f52172ee70..cbb5b0627b77d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2987,48 +2987,6 @@ impl From<[T; N]> for Vec { } } -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "vec_from_array_ref", since = "1.61.0")] -impl From<&[T; N]> for Vec { - /// Allocate a `Vec` and fill it by cloning `s`'s items. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from(b"raw"), vec![b'r', b'a', b'w']); - /// ``` - #[cfg(not(test))] - fn from(s: &[T; N]) -> Vec { - s.to_vec() - } - - #[cfg(test)] - fn from(s: &[T; N]) -> Vec { - crate::slice::to_vec(s, Global) - } -} - -#[cfg(not(no_global_oom_handling))] -#[stable(feature = "vec_from_array_ref", since = "1.61.0")] -impl From<&mut [T; N]> for Vec { - /// Allocate a `Vec` and fill it by cloning `s`'s items. - /// - /// # Examples - /// - /// ``` - /// assert_eq!(Vec::from(&mut [1, 2, 3]), vec![1, 2, 3]); - /// ``` - #[cfg(not(test))] - fn from(s: &mut [T; N]) -> Vec { - s.to_vec() - } - - #[cfg(test)] - fn from(s: &mut [T; N]) -> Vec { - crate::slice::to_vec(s, Global) - } -} - #[stable(feature = "vec_from_cow_slice", since = "1.14.0")] impl<'a, T> From> for Vec where From 42d96bb2f68c7cdc7ac67708daca0bfca37812da Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 27 Apr 2022 14:00:45 -0700 Subject: [PATCH 5/8] Remove use of reverted std::ffi::c_char --- library/alloc/tests/c_str.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/alloc/tests/c_str.rs b/library/alloc/tests/c_str.rs index 8fbb10e1d5cb6..4a5817939567b 100644 --- a/library/alloc/tests/c_str.rs +++ b/library/alloc/tests/c_str.rs @@ -1,5 +1,6 @@ use std::borrow::Cow::{Borrowed, Owned}; -use std::ffi::{c_char, CStr}; +use std::ffi::CStr; +use std::os::raw::c_char; #[test] fn to_str() { From 07ea143f96929ac7f0b7af0f025be48a472273e5 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 27 Apr 2022 13:47:10 -0700 Subject: [PATCH 6/8] Revert "Re-export core::ffi types from std::ffi" This reverts commit 9aed829fe6cdf5eaf278c6c3972f7acd0830887d. Fixes https://github.com/rust-lang/rust/issues/96435 , a regression in crates doing `use std::ffi::*;` and `use std::os::raw::*;`. We can re-add this re-export once the `core::ffi` types are stable, and thus the `std::os::raw` types can become re-exports as well, which will avoid the conflict. (Type aliases to the same type still conflict, but re-exports of the same type don't.) --- library/std/src/ffi/mod.rs | 9 --------- library/std/src/lib.rs | 1 - 2 files changed, 10 deletions(-) diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 0141a2bccdf16..10983a3323265 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -171,15 +171,6 @@ pub use self::os_str::{OsStr, OsString}; #[stable(feature = "core_c_void", since = "1.30.0")] pub use core::ffi::c_void; -#[unstable(feature = "core_ffi_c", issue = "94501")] -pub use core::ffi::{ - c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, - c_ulong, c_ulonglong, c_ushort, -}; - -#[unstable(feature = "c_size_t", issue = "88345")] -pub use core::ffi::{c_ptrdiff_t, c_size_t, c_ssize_t}; - #[unstable( feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f60b604f1b167..97c30c422827e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -307,7 +307,6 @@ // Only for re-exporting: #![feature(assert_matches)] #![feature(async_iterator)] -#![feature(c_size_t)] #![feature(c_variadic)] #![feature(cfg_accessible)] #![feature(cfg_eval)] From cf00142b4db822735b31392ded7c039844411a74 Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Thu, 28 Apr 2022 20:18:01 +0800 Subject: [PATCH 7/8] use tcx.require_lang_item() instead --- compiler/rustc_codegen_ssa/src/common.rs | 9 +-------- compiler/rustc_codegen_ssa/src/mir/block.rs | 8 ++++---- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 94c63b98ff9a0..1574b30497b4b 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -119,17 +119,10 @@ mod temp_stable_hash_impls { pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &Bx, span: Option, - msg: &str, li: LangItem, ) -> (Bx::FnAbiOfResult, Bx::Value) { let tcx = bx.tcx(); - let def_id = tcx.lang_items().require(li).unwrap_or_else(|s| { - let msg = format!("{} {}", msg, s); - match span { - Some(span) => tcx.sess.span_fatal(span, &msg), - None => tcx.sess.fatal(&msg), - } - }); + let def_id = tcx.require_lang_item(li, span); let instance = ty::Instance::mono(tcx, def_id); (bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance)) } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 9f28bc7138172..a185eb298e092 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -489,7 +489,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; - let (fn_abi, llfn) = common::build_langcall(&bx, Some(span), "", lang_item); + let (fn_abi, llfn) = common::build_langcall(&bx, Some(span), lang_item); // Codegen the actual panic invoke/call. helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); @@ -505,7 +505,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.set_debug_loc(&mut bx, terminator.source_info); // Obtain the panic entry point. - let (fn_abi, llfn) = common::build_langcall(&bx, Some(span), "", LangItem::PanicNoUnwind); + let (fn_abi, llfn) = common::build_langcall(&bx, Some(span), LangItem::PanicNoUnwind); // Codegen the actual panic invoke/call. helper.do_call(self, &mut bx, fn_abi, llfn, &[], None, None); @@ -567,7 +567,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Obtain the panic entry point. let (fn_abi, llfn) = - common::build_langcall(bx, Some(source_info.span), "", LangItem::Panic); + common::build_langcall(bx, Some(source_info.span), LangItem::Panic); // Codegen the actual panic invoke/call. helper.do_call( @@ -1429,7 +1429,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llretty = self.landing_pad_type(); bx.cleanup_landing_pad(llretty, llpersonality); - let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, "", LangItem::PanicNoUnwind); + let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind); let fn_ty = bx.fn_decl_backend_type(&fn_abi); let llret = bx.call(fn_ty, fn_ptr, &[], None); From 0fce0db96f5d7f3b42d25412d3989014551852ac Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 28 Apr 2022 16:22:40 +0100 Subject: [PATCH 8/8] Add `@feat.00` symbol to symbols.o for COFF --- compiler/rustc_codegen_ssa/src/back/link.rs | 23 +++++++++++++++++++++ src/test/run-make/issue-96498/Makefile | 8 +++++++ src/test/run-make/issue-96498/foo.rs | 4 ++++ 3 files changed, 35 insertions(+) create mode 100644 src/test/run-make/issue-96498/Makefile create mode 100644 src/test/run-make/issue-96498/foo.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 54a69fcf68110..886ca9681e2b2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1700,6 +1700,29 @@ fn add_linked_symbol_object( // We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the // default mangler in `object` crate. file.set_mangling(object::write::Mangling::None); + + // Add feature flags to the object file. On MSVC this is optional but LLD will complain if + // not present. + let mut feature = 0; + + if file.architecture() == object::Architecture::I386 { + // Indicate that all SEH handlers are registered in .sxdata section. + // We don't have generate any code, so we don't need .sxdata section but LLD still + // expects us to set this bit (see #96498). + // Reference: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format + feature |= 1; + } + + file.add_symbol(object::write::Symbol { + name: "@feat.00".into(), + value: feature, + size: 0, + kind: object::SymbolKind::Data, + scope: object::SymbolScope::Compilation, + weak: false, + section: object::write::SymbolSection::Absolute, + flags: object::SymbolFlags::None, + }); } for (sym, kind) in symbols.iter() { diff --git a/src/test/run-make/issue-96498/Makefile b/src/test/run-make/issue-96498/Makefile new file mode 100644 index 0000000000000..eae6400aee43a --- /dev/null +++ b/src/test/run-make/issue-96498/Makefile @@ -0,0 +1,8 @@ +# only-windows +# needs-rust-lld + +-include ../../run-make-fulldeps/tools.mk + +# Ensure that LLD can link +all: + $(RUSTC) -C linker=rust-lld foo.rs diff --git a/src/test/run-make/issue-96498/foo.rs b/src/test/run-make/issue-96498/foo.rs new file mode 100644 index 0000000000000..93ac3641b098c --- /dev/null +++ b/src/test/run-make/issue-96498/foo.rs @@ -0,0 +1,4 @@ +#![crate_type = "cdylib"] + +#[no_mangle] +extern "C" fn foo() {}