Skip to content

Commit abb5826

Browse files
committed
Auto merge of rust-lang#3721 - rust-lang:rustup-2024-06-29, r=RalfJung
Automatic Rustup
2 parents c471589 + ec7bcc0 commit abb5826

File tree

166 files changed

+4584
-1220
lines changed

Some content is hidden

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

166 files changed

+4584
-1220
lines changed

Cargo.lock

+9
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ dependencies = [
228228
"backtrace",
229229
]
230230

231+
[[package]]
232+
name = "ar"
233+
version = "0.9.0"
234+
source = "registry+https://github.com/rust-lang/crates.io-index"
235+
checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69"
236+
231237
[[package]]
232238
name = "ar_archive_writer"
233239
version = "0.2.0"
@@ -3394,6 +3400,7 @@ dependencies = [
33943400
name = "run_make_support"
33953401
version = "0.2.0"
33963402
dependencies = [
3403+
"ar",
33973404
"gimli 0.28.1",
33983405
"object 0.34.0",
33993406
"regex",
@@ -4668,6 +4675,8 @@ name = "rustc_smir"
46684675
version = "0.0.0"
46694676
dependencies = [
46704677
"rustc_abi",
4678+
"rustc_ast",
4679+
"rustc_ast_pretty",
46714680
"rustc_data_structures",
46724681
"rustc_hir",
46734682
"rustc_middle",

compiler/rustc_codegen_llvm/src/attributes.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use rustc_codegen_ssa::traits::*;
44
use rustc_hir::def_id::DefId;
5-
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
5+
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
66
use rustc_middle::ty::{self, TyCtxt};
77
use rustc_session::config::{FunctionReturn, OptLevel};
88
use rustc_span::symbol::sym;
@@ -53,6 +53,34 @@ fn inline_attr<'ll>(cx: &CodegenCx<'ll, '_>, inline: InlineAttr) -> Option<&'ll
5353
}
5454
}
5555

56+
#[inline]
57+
fn patchable_function_entry_attrs<'ll>(
58+
cx: &CodegenCx<'ll, '_>,
59+
attr: Option<PatchableFunctionEntry>,
60+
) -> SmallVec<[&'ll Attribute; 2]> {
61+
let mut attrs = SmallVec::new();
62+
let patchable_spec = attr.unwrap_or_else(|| {
63+
PatchableFunctionEntry::from_config(cx.tcx.sess.opts.unstable_opts.patchable_function_entry)
64+
});
65+
let entry = patchable_spec.entry();
66+
let prefix = patchable_spec.prefix();
67+
if entry > 0 {
68+
attrs.push(llvm::CreateAttrStringValue(
69+
cx.llcx,
70+
"patchable-function-entry",
71+
&format!("{}", entry),
72+
));
73+
}
74+
if prefix > 0 {
75+
attrs.push(llvm::CreateAttrStringValue(
76+
cx.llcx,
77+
"patchable-function-prefix",
78+
&format!("{}", prefix),
79+
));
80+
}
81+
attrs
82+
}
83+
5684
/// Get LLVM sanitize attributes.
5785
#[inline]
5886
pub fn sanitize_attrs<'ll>(
@@ -421,6 +449,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
421449
llvm::set_alignment(llfn, align);
422450
}
423451
to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
452+
to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));
424453

425454
// Always annotate functions with the target-cpu they are compiled for.
426455
// Without this, ThinLTO won't inline Rust functions into Clang generated

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+78-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
22
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
3-
use rustc_errors::{codes::*, struct_span_code_err};
3+
use rustc_errors::{codes::*, struct_span_code_err, DiagMessage, SubdiagMessage};
44
use rustc_hir as hir;
55
use rustc_hir::def::DefKind;
66
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
77
use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
8-
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
8+
use rustc_middle::middle::codegen_fn_attrs::{
9+
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
10+
};
911
use rustc_middle::mir::mono::Linkage;
1012
use rustc_middle::query::Providers;
1113
use rustc_middle::ty::{self as ty, TyCtxt};
@@ -447,6 +449,80 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
447449
None
448450
};
449451
}
452+
sym::patchable_function_entry => {
453+
codegen_fn_attrs.patchable_function_entry = attr.meta_item_list().and_then(|l| {
454+
let mut prefix = None;
455+
let mut entry = None;
456+
for item in l {
457+
let Some(meta_item) = item.meta_item() else {
458+
tcx.dcx().span_err(item.span(), "expected name value pair");
459+
continue;
460+
};
461+
462+
let Some(name_value_lit) = meta_item.name_value_literal() else {
463+
tcx.dcx().span_err(item.span(), "expected name value pair");
464+
continue;
465+
};
466+
467+
fn emit_error_with_label(
468+
tcx: TyCtxt<'_>,
469+
span: Span,
470+
error: impl Into<DiagMessage>,
471+
label: impl Into<SubdiagMessage>,
472+
) {
473+
let mut err: rustc_errors::Diag<'_, _> =
474+
tcx.dcx().struct_span_err(span, error);
475+
err.span_label(span, label);
476+
err.emit();
477+
}
478+
479+
let attrib_to_write = match meta_item.name_or_empty() {
480+
sym::prefix_nops => &mut prefix,
481+
sym::entry_nops => &mut entry,
482+
_ => {
483+
emit_error_with_label(
484+
tcx,
485+
item.span(),
486+
"unexpected parameter name",
487+
format!("expected {} or {}", sym::prefix_nops, sym::entry_nops),
488+
);
489+
continue;
490+
}
491+
};
492+
493+
let rustc_ast::LitKind::Int(val, _) = name_value_lit.kind else {
494+
emit_error_with_label(
495+
tcx,
496+
name_value_lit.span,
497+
"invalid literal value",
498+
"value must be an integer between `0` and `255`",
499+
);
500+
continue;
501+
};
502+
503+
let Ok(val) = val.get().try_into() else {
504+
emit_error_with_label(
505+
tcx,
506+
name_value_lit.span,
507+
"integer value out of range",
508+
"value must be between `0` and `255`",
509+
);
510+
continue;
511+
};
512+
513+
*attrib_to_write = Some(val);
514+
}
515+
516+
if let (None, None) = (prefix, entry) {
517+
tcx.dcx().span_err(attr.span, "must specify at least one parameter");
518+
}
519+
520+
Some(PatchableFunctionEntry::from_prefix_and_entry(
521+
prefix.unwrap_or(0),
522+
entry.unwrap_or(0),
523+
))
524+
})
525+
}
450526
_ => {}
451527
}
452528
}

compiler/rustc_feature/src/builtin_attrs.rs

+7
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
585585
EncodeCrossCrate::No, derive_smart_pointer, experimental!(pointee)
586586
),
587587

588+
// RFC 3543
589+
// `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
590+
gated!(
591+
patchable_function_entry, Normal, template!(List: "prefix_nops = m, entry_nops = n"), ErrorPreceding,
592+
EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
593+
),
594+
588595
// ==========================================================================
589596
// Internal attributes: Stability, deprecation, and unsafe:
590597
// ==========================================================================

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,8 @@ declare_features! (
563563
(unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)),
564564
/// Allows using `#[optimize(X)]`.
565565
(unstable, optimize_attribute, "1.34.0", Some(54882)),
566+
/// Allows specifying nop padding on functions for dynamic patching.
567+
(unstable, patchable_function_entry, "CURRENT_RUSTC_VERSION", Some(123115)),
566568
/// Allows postfix match `expr.match { ... }`
567569
(unstable, postfix_match, "1.79.0", Some(121618)),
568570
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.

compiler/rustc_interface/src/tests.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use rustc_session::config::{
88
ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold,
99
Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
1010
LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey,
11-
PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
12-
SymbolManglingVersion, WasiExecModel,
11+
PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip,
12+
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
1313
};
1414
use rustc_session::lint::Level;
1515
use rustc_session::search_paths::SearchPath;
@@ -813,6 +813,11 @@ fn test_unstable_options_tracking_hash() {
813813
tracked!(packed_bundled_libs, true);
814814
tracked!(panic_abort_tests, true);
815815
tracked!(panic_in_drop, PanicStrategy::Abort);
816+
tracked!(
817+
patchable_function_entry,
818+
PatchableFunctionEntry::from_total_and_prefix_nops(10, 5)
819+
.expect("total must be greater than or equal to prefix")
820+
);
816821
tracked!(plt, Some(true));
817822
tracked!(polonius, Polonius::Legacy);
818823
tracked!(precise_enum_drop_elaboration, false);

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

+27
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,32 @@ pub struct CodegenFnAttrs {
4545
/// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
4646
/// aligned to.
4747
pub alignment: Option<Align>,
48+
/// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
49+
/// the function entry.
50+
pub patchable_function_entry: Option<PatchableFunctionEntry>,
51+
}
52+
53+
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
54+
pub struct PatchableFunctionEntry {
55+
/// Nops to prepend to the function
56+
prefix: u8,
57+
/// Nops after entry, but before body
58+
entry: u8,
59+
}
60+
61+
impl PatchableFunctionEntry {
62+
pub fn from_config(config: rustc_session::config::PatchableFunctionEntry) -> Self {
63+
Self { prefix: config.prefix(), entry: config.entry() }
64+
}
65+
pub fn from_prefix_and_entry(prefix: u8, entry: u8) -> Self {
66+
Self { prefix, entry }
67+
}
68+
pub fn prefix(&self) -> u8 {
69+
self.prefix
70+
}
71+
pub fn entry(&self) -> u8 {
72+
self.entry
73+
}
4874
}
4975

5076
#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
@@ -121,6 +147,7 @@ impl CodegenFnAttrs {
121147
no_sanitize: SanitizerSet::empty(),
122148
instruction_set: None,
123149
alignment: None,
150+
patchable_function_entry: None,
124151
}
125152
}
126153

compiler/rustc_passes/src/reachable.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
3030
use rustc_hir::intravisit::{self, Visitor};
3131
use rustc_hir::Node;
3232
use rustc_middle::bug;
33-
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
33+
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
3434
use rustc_middle::middle::privacy::{self, Level};
3535
use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc};
3636
use rustc_middle::query::Providers;
@@ -178,7 +178,15 @@ impl<'tcx> ReachableContext<'tcx> {
178178
if !self.any_library {
179179
// If we are building an executable, only explicitly extern
180180
// types need to be exported.
181-
if has_custom_linkage(self.tcx, search_item) {
181+
let codegen_attrs = if self.tcx.def_kind(search_item).has_codegen_attrs() {
182+
self.tcx.codegen_fn_attrs(search_item)
183+
} else {
184+
CodegenFnAttrs::EMPTY
185+
};
186+
let is_extern = codegen_attrs.contains_extern_indicator();
187+
let std_internal =
188+
codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
189+
if is_extern || std_internal {
182190
self.reachable_symbols.insert(search_item);
183191
}
184192
} else {

compiler/rustc_session/src/config.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -2965,8 +2965,9 @@ pub(crate) mod dep_tracking {
29652965
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
29662966
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
29672967
LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
2968-
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
2969-
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
2968+
PatchableFunctionEntry, Polonius, RemapPathScopeComponents, ResolveDocLinks,
2969+
SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
2970+
WasiExecModel,
29702971
};
29712972
use crate::lint;
29722973
use crate::utils::NativeLib;
@@ -3073,6 +3074,7 @@ pub(crate) mod dep_tracking {
30733074
OomStrategy,
30743075
LanguageIdentifier,
30753076
NextSolverConfig,
3077+
PatchableFunctionEntry,
30763078
Polonius,
30773079
InliningThreshold,
30783080
FunctionReturn,
@@ -3250,6 +3252,35 @@ impl DumpMonoStatsFormat {
32503252
}
32513253
}
32523254

3255+
/// `-Z patchable-function-entry` representation - how many nops to put before and after function
3256+
/// entry.
3257+
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]
3258+
pub struct PatchableFunctionEntry {
3259+
/// Nops before the entry
3260+
prefix: u8,
3261+
/// Nops after the entry
3262+
entry: u8,
3263+
}
3264+
3265+
impl PatchableFunctionEntry {
3266+
pub fn from_total_and_prefix_nops(
3267+
total_nops: u8,
3268+
prefix_nops: u8,
3269+
) -> Option<PatchableFunctionEntry> {
3270+
if total_nops < prefix_nops {
3271+
None
3272+
} else {
3273+
Some(Self { prefix: prefix_nops, entry: total_nops - prefix_nops })
3274+
}
3275+
}
3276+
pub fn prefix(&self) -> u8 {
3277+
self.prefix
3278+
}
3279+
pub fn entry(&self) -> u8 {
3280+
self.entry
3281+
}
3282+
}
3283+
32533284
/// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
32543285
/// or future prototype.
32553286
#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)]

compiler/rustc_session/src/options.rs

+29
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ mod desc {
379379
pub const parse_passes: &str = "a space-separated list of passes, or `all`";
380380
pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
381381
pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
382+
pub const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)";
382383
pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
383384
pub const parse_oom_strategy: &str = "either `panic` or `abort`";
384385
pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
@@ -734,6 +735,32 @@ mod parse {
734735
true
735736
}
736737

738+
pub(crate) fn parse_patchable_function_entry(
739+
slot: &mut PatchableFunctionEntry,
740+
v: Option<&str>,
741+
) -> bool {
742+
let mut total_nops = 0;
743+
let mut prefix_nops = 0;
744+
745+
if !parse_number(&mut total_nops, v) {
746+
let parts = v.and_then(|v| v.split_once(',')).unzip();
747+
if !parse_number(&mut total_nops, parts.0) {
748+
return false;
749+
}
750+
if !parse_number(&mut prefix_nops, parts.1) {
751+
return false;
752+
}
753+
}
754+
755+
if let Some(pfe) =
756+
PatchableFunctionEntry::from_total_and_prefix_nops(total_nops, prefix_nops)
757+
{
758+
*slot = pfe;
759+
return true;
760+
}
761+
false
762+
}
763+
737764
pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
738765
match v {
739766
Some("panic") => *slot = OomStrategy::Panic,
@@ -1859,6 +1886,8 @@ options! {
18591886
"panic strategy for panics in drops"),
18601887
parse_only: bool = (false, parse_bool, [UNTRACKED],
18611888
"parse only; do not compile, assemble, or link (default: no)"),
1889+
patchable_function_entry: PatchableFunctionEntry = (PatchableFunctionEntry::default(), parse_patchable_function_entry, [TRACKED],
1890+
"nop padding at function entry"),
18621891
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
18631892
"whether to use the PLT when calling into shared libraries;
18641893
only has effect for PIC code on systems with ELF binaries

0 commit comments

Comments
 (0)