Skip to content

Commit 5bcd716

Browse files
committed
Auto merge of #144387 - fmease:rollup-nh0gn9t, r=fmease
Rollup of 16 pull requests Successful merges: - #143374 (Unquerify extern_mod_stmt_cnum.) - #143838 (std: net: uefi: Add support to query connection data) - #144014 (don't link to the nightly version of the Edition Guide in stable lints) - #144094 (Ensure we codegen the main fn) - #144218 (Use serde for target spec json deserialize) - #144221 (generate elf symbol version in raw-dylib) - #144232 (Implement support for `become` and explicit tail call codegen for the LLVM backend) - #144240 (Add more test case to check if the false note related to sealed trait suppressed) - #144247 (coretests/num: use ldexp instead of hard-coding a power of 2) - #144276 (Use less HIR in check_private_in_public.) - #144278 (add Rev::into_inner) - #144317 (pass build.npm from bootstrap to tidy and use it for npm install) - #144320 (rustdoc: avoid allocating a temp String for aliases in search index) - #144334 (rustc_resolve: get rid of unused rustdoc::span_of_fragments_with_expansion) - #144335 (Don't suggest assoc ty bound on non-angle-bracketed problematic assoc ty binding) - #144358 (Stop using the old `validate_attr` logic for stability attributes) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 3c30dbb + 7c241fc commit 5bcd716

File tree

198 files changed

+2024
-1590
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

198 files changed

+2024
-1590
lines changed

Cargo.lock

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4563,7 +4563,10 @@ dependencies = [
45634563
"rustc_macros",
45644564
"rustc_serialize",
45654565
"rustc_span",
4566+
"serde",
4567+
"serde_derive",
45664568
"serde_json",
4569+
"serde_path_to_error",
45674570
"tracing",
45684571
]
45694572

@@ -4955,6 +4958,16 @@ dependencies = [
49554958
"serde",
49564959
]
49574960

4961+
[[package]]
4962+
name = "serde_path_to_error"
4963+
version = "0.1.17"
4964+
source = "registry+https://github.com/rust-lang/crates.io-index"
4965+
checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
4966+
dependencies = [
4967+
"itoa",
4968+
"serde",
4969+
]
4970+
49584971
[[package]]
49594972
name = "serde_spanned"
49604973
version = "0.6.9"

compiler/rustc_attr_parsing/src/attributes/stability.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,15 @@ impl<S: Stage> AttributeParser<S> for StabilityParser {
7474
template!(NameValueStr: "deprecation message"),
7575
|this, cx, args| {
7676
reject_outside_std!(cx);
77-
this.allowed_through_unstable_modules =
78-
args.name_value().and_then(|i| i.value_as_str())
77+
let Some(nv) = args.name_value() else {
78+
cx.expected_name_value(cx.attr_span, None);
79+
return;
80+
};
81+
let Some(value_str) = nv.value_as_str() else {
82+
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
83+
return;
84+
};
85+
this.allowed_through_unstable_modules = Some(value_str);
7986
},
8087
),
8188
];
@@ -247,7 +254,12 @@ pub(crate) fn parse_stability<S: Stage>(
247254
let mut feature = None;
248255
let mut since = None;
249256

250-
for param in args.list()?.mixed() {
257+
let ArgParser::List(list) = args else {
258+
cx.expected_list(cx.attr_span);
259+
return None;
260+
};
261+
262+
for param in list.mixed() {
251263
let param_span = param.span();
252264
let Some(param) = param.meta_item() else {
253265
cx.emit_err(session_diagnostics::UnsupportedLiteral {
@@ -322,7 +334,13 @@ pub(crate) fn parse_unstability<S: Stage>(
322334
let mut is_soft = false;
323335
let mut implied_by = None;
324336
let mut old_name = None;
325-
for param in args.list()?.mixed() {
337+
338+
let ArgParser::List(list) = args else {
339+
cx.expected_list(cx.attr_span);
340+
return None;
341+
};
342+
343+
for param in list.mixed() {
326344
let Some(param) = param.meta_item() else {
327345
cx.emit_err(session_diagnostics::UnsupportedLiteral {
328346
span: param.span(),

compiler/rustc_codegen_gcc/src/builder.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,21 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
17421742
call
17431743
}
17441744

1745+
fn tail_call(
1746+
&mut self,
1747+
_llty: Self::Type,
1748+
_fn_attrs: Option<&CodegenFnAttrs>,
1749+
_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
1750+
_llfn: Self::Value,
1751+
_args: &[Self::Value],
1752+
_funclet: Option<&Self::Funclet>,
1753+
_instance: Option<Instance<'tcx>>,
1754+
) {
1755+
bug!(
1756+
"Guaranteed tail calls with the 'become' keyword are not implemented in the GCC backend"
1757+
);
1758+
}
1759+
17451760
fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
17461761
// FIXME(antoyo): this does not zero-extend.
17471762
self.gcc_int_cast(value, dest_typ)

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
1515
use rustc_codegen_ssa::traits::*;
1616
use rustc_data_structures::small_c_str::SmallCStr;
1717
use rustc_hir::def_id::DefId;
18+
use rustc_middle::bug;
1819
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
1920
use rustc_middle::ty::layout::{
2021
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers,
@@ -24,7 +25,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
2425
use rustc_sanitizers::{cfi, kcfi};
2526
use rustc_session::config::OptLevel;
2627
use rustc_span::Span;
27-
use rustc_target::callconv::FnAbi;
28+
use rustc_target::callconv::{FnAbi, PassMode};
2829
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
2930
use smallvec::SmallVec;
3031
use tracing::{debug, instrument};
@@ -1431,6 +1432,29 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
14311432
call
14321433
}
14331434

1435+
fn tail_call(
1436+
&mut self,
1437+
llty: Self::Type,
1438+
fn_attrs: Option<&CodegenFnAttrs>,
1439+
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
1440+
llfn: Self::Value,
1441+
args: &[Self::Value],
1442+
funclet: Option<&Self::Funclet>,
1443+
instance: Option<Instance<'tcx>>,
1444+
) {
1445+
let call = self.call(llty, fn_attrs, Some(fn_abi), llfn, args, funclet, instance);
1446+
1447+
match &fn_abi.ret.mode {
1448+
PassMode::Ignore | PassMode::Indirect { .. } => self.ret_void(),
1449+
PassMode::Direct(_) | PassMode::Pair { .. } => self.ret(call),
1450+
mode @ PassMode::Cast { .. } => {
1451+
bug!("Encountered `PassMode::{mode:?}` during codegen")
1452+
}
1453+
}
1454+
1455+
llvm::LLVMRustSetTailCallKind(call, llvm::TailCallKind::MustTail);
1456+
}
1457+
14341458
fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
14351459
unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) }
14361460
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ pub(crate) enum ModuleFlagMergeBehavior {
9797

9898
// Consts for the LLVM CallConv type, pre-cast to usize.
9999

100+
#[derive(Copy, Clone, PartialEq, Debug)]
101+
#[repr(C)]
102+
#[allow(dead_code)]
103+
pub(crate) enum TailCallKind {
104+
None = 0,
105+
Tail = 1,
106+
MustTail = 2,
107+
NoTail = 3,
108+
}
109+
100110
/// LLVM CallingConv::ID. Should we wrap this?
101111
///
102112
/// See <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/CallingConv.h>
@@ -1186,6 +1196,7 @@ unsafe extern "C" {
11861196
pub(crate) safe fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
11871197
pub(crate) safe fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool);
11881198
pub(crate) safe fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool);
1199+
pub(crate) safe fn LLVMRustSetTailCallKind(CallInst: &Value, Kind: TailCallKind);
11891200

11901201
// Operations on attributes
11911202
pub(crate) fn LLVMCreateStringAttribute(

compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs

Lines changed: 106 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
44

55
use rustc_abi::Endian;
66
use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
7-
use rustc_data_structures::fx::FxIndexMap;
7+
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
88
use rustc_data_structures::stable_hasher::StableHasher;
99
use rustc_hashes::Hash128;
1010
use rustc_session::Session;
@@ -214,7 +214,7 @@ pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>(
214214
/// It exports all the provided symbols, but is otherwise empty.
215215
fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]) -> Vec<u8> {
216216
use object::write::elf as write;
217-
use object::{Architecture, elf};
217+
use object::{AddressSize, Architecture, elf};
218218

219219
let mut stub_buf = Vec::new();
220220

@@ -226,54 +226,94 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
226226
// It is important that the order of reservation matches the order of writing.
227227
// The object crate contains many debug asserts that fire if you get this wrong.
228228

229+
let Some((arch, sub_arch)) = sess.target.object_architecture(&sess.unstable_target_features)
230+
else {
231+
sess.dcx().fatal(format!(
232+
"raw-dylib is not supported for the architecture `{}`",
233+
sess.target.arch
234+
));
235+
};
236+
229237
let endianness = match sess.target.options.endian {
230238
Endian::Little => object::Endianness::Little,
231239
Endian::Big => object::Endianness::Big,
232240
};
233-
let mut stub = write::Writer::new(endianness, true, &mut stub_buf);
241+
242+
let is_64 = match arch.address_size() {
243+
Some(AddressSize::U8 | AddressSize::U16 | AddressSize::U32) => false,
244+
Some(AddressSize::U64) => true,
245+
_ => sess.dcx().fatal(format!(
246+
"raw-dylib is not supported for the architecture `{}`",
247+
sess.target.arch
248+
)),
249+
};
250+
251+
let mut stub = write::Writer::new(endianness, is_64, &mut stub_buf);
252+
253+
let mut vers = Vec::new();
254+
let mut vers_map = FxHashMap::default();
255+
let mut syms = Vec::new();
256+
257+
for symbol in symbols {
258+
let symbol_name = symbol.name.as_str();
259+
if let Some((name, version_name)) = symbol_name.split_once('@') {
260+
assert!(!version_name.contains('@'));
261+
let dynstr = stub.add_dynamic_string(name.as_bytes());
262+
let ver = if let Some(&ver_id) = vers_map.get(version_name) {
263+
ver_id
264+
} else {
265+
let id = vers.len();
266+
vers_map.insert(version_name, id);
267+
let dynstr = stub.add_dynamic_string(version_name.as_bytes());
268+
vers.push((version_name, dynstr));
269+
id
270+
};
271+
syms.push((name, dynstr, Some(ver)));
272+
} else {
273+
let dynstr = stub.add_dynamic_string(symbol_name.as_bytes());
274+
syms.push((symbol_name, dynstr, None));
275+
}
276+
}
277+
278+
let soname = stub.add_dynamic_string(soname.as_bytes());
234279

235280
// These initial reservations don't reserve any bytes in the binary yet,
236281
// they just allocate in the internal data structures.
237282

238-
// First, we crate the dynamic symbol table. It starts with a null symbol
283+
// First, we create the dynamic symbol table. It starts with a null symbol
239284
// and then all the symbols and their dynamic strings.
240285
stub.reserve_null_dynamic_symbol_index();
241286

242-
let dynstrs = symbols
243-
.iter()
244-
.map(|sym| {
245-
stub.reserve_dynamic_symbol_index();
246-
(sym, stub.add_dynamic_string(sym.name.as_str().as_bytes()))
247-
})
248-
.collect::<Vec<_>>();
249-
250-
let soname = stub.add_dynamic_string(soname.as_bytes());
287+
for _ in syms.iter() {
288+
stub.reserve_dynamic_symbol_index();
289+
}
251290

252291
// Reserve the sections.
253292
// We have the minimal sections for a dynamic SO and .text where we point our dummy symbols to.
254293
stub.reserve_shstrtab_section_index();
255294
let text_section_name = stub.add_section_name(".text".as_bytes());
256295
let text_section = stub.reserve_section_index();
257-
stub.reserve_dynstr_section_index();
258296
stub.reserve_dynsym_section_index();
297+
stub.reserve_dynstr_section_index();
298+
if !vers.is_empty() {
299+
stub.reserve_gnu_versym_section_index();
300+
stub.reserve_gnu_verdef_section_index();
301+
}
259302
stub.reserve_dynamic_section_index();
260303

261304
// These reservations now determine the actual layout order of the object file.
262305
stub.reserve_file_header();
263306
stub.reserve_shstrtab();
264307
stub.reserve_section_headers();
265-
stub.reserve_dynstr();
266308
stub.reserve_dynsym();
309+
stub.reserve_dynstr();
310+
if !vers.is_empty() {
311+
stub.reserve_gnu_versym();
312+
stub.reserve_gnu_verdef(1 + vers.len(), 1 + vers.len());
313+
}
267314
stub.reserve_dynamic(2); // DT_SONAME, DT_NULL
268315

269316
// First write the ELF header with the arch information.
270-
let Some((arch, sub_arch)) = sess.target.object_architecture(&sess.unstable_target_features)
271-
else {
272-
sess.dcx().fatal(format!(
273-
"raw-dylib is not supported for the architecture `{}`",
274-
sess.target.arch
275-
));
276-
};
277317
let e_machine = match (arch, sub_arch) {
278318
(Architecture::Aarch64, None) => elf::EM_AARCH64,
279319
(Architecture::Aarch64_Ilp32, None) => elf::EM_AARCH64,
@@ -342,18 +382,19 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
342382
sh_addralign: 1,
343383
sh_entsize: 0,
344384
});
345-
stub.write_dynstr_section_header(0);
346385
stub.write_dynsym_section_header(0, 1);
386+
stub.write_dynstr_section_header(0);
387+
if !vers.is_empty() {
388+
stub.write_gnu_versym_section_header(0);
389+
stub.write_gnu_verdef_section_header(0);
390+
}
347391
stub.write_dynamic_section_header(0);
348392

349-
// .dynstr
350-
stub.write_dynstr();
351-
352393
// .dynsym
353394
stub.write_null_dynamic_symbol();
354-
for (_, name) in dynstrs {
395+
for (_name, dynstr, _ver) in syms.iter().copied() {
355396
stub.write_dynamic_symbol(&write::Sym {
356-
name: Some(name),
397+
name: Some(dynstr),
357398
st_info: (elf::STB_GLOBAL << 4) | elf::STT_NOTYPE,
358399
st_other: elf::STV_DEFAULT,
359400
section: Some(text_section),
@@ -363,10 +404,47 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
363404
});
364405
}
365406

407+
// .dynstr
408+
stub.write_dynstr();
409+
410+
// ld.bfd is unhappy if these sections exist without any symbols, so we only generate them when necessary.
411+
if !vers.is_empty() {
412+
// .gnu_version
413+
stub.write_null_gnu_versym();
414+
for (_name, _dynstr, ver) in syms.iter().copied() {
415+
stub.write_gnu_versym(if let Some(ver) = ver {
416+
assert!((2 + ver as u16) < elf::VERSYM_HIDDEN);
417+
elf::VERSYM_HIDDEN | (2 + ver as u16)
418+
} else {
419+
1
420+
});
421+
}
422+
423+
// .gnu_version_d
424+
stub.write_align_gnu_verdef();
425+
stub.write_gnu_verdef(&write::Verdef {
426+
version: elf::VER_DEF_CURRENT,
427+
flags: elf::VER_FLG_BASE,
428+
index: 1,
429+
aux_count: 1,
430+
name: soname,
431+
});
432+
for (ver, (_name, dynstr)) in vers.into_iter().enumerate() {
433+
stub.write_gnu_verdef(&write::Verdef {
434+
version: elf::VER_DEF_CURRENT,
435+
flags: 0,
436+
index: 2 + ver as u16,
437+
aux_count: 1,
438+
name: dynstr,
439+
});
440+
}
441+
}
442+
366443
// .dynamic
367444
// the DT_SONAME will be used by the linker to populate DT_NEEDED
368445
// which the loader uses to find the library.
369446
// DT_NULL terminates the .dynamic table.
447+
stub.write_align_dynamic();
370448
stub.write_dynamic_string(elf::DT_SONAME, soname);
371449
stub.write_dynamic(elf::DT_NULL, 0);
372450

0 commit comments

Comments
 (0)