Skip to content

Commit dbc85e5

Browse files
authored
Rollup merge of rust-lang#147117 - iximeow:ixi/illumos-used-attr, r=Noratrieb
interpret `#[used]` as `#[used(compiler)]` on illumos helps rust-lang#146169 not be as painful: fixes the illumos regression in rust-lang#140872, but `#[used(linker)]` is still erroneous on illumos generally. illumos' `ld` does not support a flag like either SHF_GNU_RETAIN or SHF_SUNW_NODISCARD, so there is no way to communicate `#[used(linker)]` for that target. Setting `USED_LINKER` to try results in LLVM setting SHF_SUNW_NODISCARD for Solaris-like targets, which is an unknown section header flag for illumos `ld` and prevents sections from being merged that otherwise would. As a motivating example, the `inventory` crate produces `#[used]` items to merge into `.init_array`. Because those items have an unknown section header flag they are not merged with the default `.init_array` with `frame_dummy`, and end up never executed. Downgrading `#[used]` to `#[used(compiler)]` on illumos keeps so-attributed items as preserved as they had been before rust-lang#140872. As was the case before that change, because rustc passes `-z ignore` to illumos `ld`, it's possible that `used` sections are GC'd at link time. rust-lang#146169 describes this unfortunate circumstance. ---- as it turns out, `tests/ui/attributes/used_with_archive.rs` had broken on `x86_64-unknown-illumos`, and this patch fixes it. the trials and tribulations of tier 2 :( r? `@Noratrieb` probably?
2 parents bfdcdb6 + c721fa2 commit dbc85e5

File tree

3 files changed

+43
-9
lines changed

3 files changed

+43
-9
lines changed

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for NoMangleParser {
370370
pub(crate) struct UsedParser {
371371
first_compiler: Option<Span>,
372372
first_linker: Option<Span>,
373+
first_default: Option<Span>,
373374
}
374375

375376
// A custom `AttributeParser` is used rather than a Simple attribute parser because
@@ -382,7 +383,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
382383
template!(Word, List: &["compiler", "linker"]),
383384
|group: &mut Self, cx, args| {
384385
let used_by = match args {
385-
ArgParser::NoArgs => UsedBy::Linker,
386+
ArgParser::NoArgs => UsedBy::Default,
386387
ArgParser::List(list) => {
387388
let Some(l) = list.single() else {
388389
cx.expected_single_argument(list.span);
@@ -423,12 +424,29 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
423424
ArgParser::NameValue(_) => return,
424425
};
425426

427+
let attr_span = cx.attr_span;
428+
429+
// `#[used]` is interpreted as `#[used(linker)]` (though depending on target OS the
430+
// circumstances are more complicated). While we're checking `used_by`, also report
431+
// these cross-`UsedBy` duplicates to warn.
426432
let target = match used_by {
427433
UsedBy::Compiler => &mut group.first_compiler,
428-
UsedBy::Linker => &mut group.first_linker,
434+
UsedBy::Linker => {
435+
if let Some(prev) = group.first_default {
436+
cx.warn_unused_duplicate(prev, attr_span);
437+
return;
438+
}
439+
&mut group.first_linker
440+
}
441+
UsedBy::Default => {
442+
if let Some(prev) = group.first_linker {
443+
cx.warn_unused_duplicate(prev, attr_span);
444+
return;
445+
}
446+
&mut group.first_default
447+
}
429448
};
430449

431-
let attr_span = cx.attr_span;
432450
if let Some(prev) = *target {
433451
cx.warn_unused_duplicate(prev, attr_span);
434452
} else {
@@ -440,11 +458,13 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
440458
AllowedTargets::AllowList(&[Allow(Target::Static), Warn(Target::MacroCall)]);
441459

442460
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
443-
// Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker`
444-
Some(match (self.first_compiler, self.first_linker) {
445-
(_, Some(span)) => AttributeKind::Used { used_by: UsedBy::Linker, span },
446-
(Some(span), _) => AttributeKind::Used { used_by: UsedBy::Compiler, span },
447-
(None, None) => return None,
461+
// If a specific form of `used` is specified, it takes precedence over generic `#[used]`.
462+
// If both `linker` and `compiler` are specified, use `linker`.
463+
Some(match (self.first_compiler, self.first_linker, self.first_default) {
464+
(_, Some(span), _) => AttributeKind::Used { used_by: UsedBy::Linker, span },
465+
(Some(span), _, _) => AttributeKind::Used { used_by: UsedBy::Compiler, span },
466+
(_, _, Some(span)) => AttributeKind::Used { used_by: UsedBy::Default, span },
467+
(None, None, None) => return None,
448468
})
449469
}
450470
}

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,19 @@ fn process_builtin_attrs(
263263
AttributeKind::Used { used_by, .. } => match used_by {
264264
UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER,
265265
UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER,
266+
UsedBy::Default => {
267+
let used_form = if tcx.sess.target.os == "illumos" {
268+
// illumos' `ld` doesn't support a section header that would represent
269+
// `#[used(linker)]`, see
270+
// https://github.com/rust-lang/rust/issues/146169. For that target,
271+
// downgrade as if `#[used(compiler)]` was requested and hope for the
272+
// best.
273+
CodegenFnAttrFlags::USED_COMPILER
274+
} else {
275+
CodegenFnAttrFlags::USED_LINKER
276+
};
277+
codegen_fn_attrs.flags |= used_form;
278+
}
266279
},
267280
AttributeKind::FfiConst(_) => {
268281
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,13 @@ impl Deprecation {
146146
}
147147

148148
/// There are three valid forms of the attribute:
149-
/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable.
149+
/// `#[used]`, which is equivalent to `#[used(linker)]` on targets that support it, but `#[used(compiler)]` if not.
150150
/// `#[used(compiler)]`
151151
/// `#[used(linker)]`
152152
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
153153
#[derive(HashStable_Generic, PrintAttribute)]
154154
pub enum UsedBy {
155+
Default,
155156
Compiler,
156157
Linker,
157158
}

0 commit comments

Comments
 (0)