Skip to content

Commit b4e75bd

Browse files
committed
Auto merge of #127067 - matthiaskrgr:rollup-85ecygb, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #124741 (patchable-function-entry: Add unstable compiler flag and attribute) - #126470 (make cargo submodule optional) - #126701 (ignore `llvm::Lld` if lld is not enabled) - #126956 (core: avoid `extern type`s in formatting infrastructure) - #126970 (Simplify `str::clone_into`) - #127058 (Tighten `fn_decl_span` for async blocks) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 9c3bc80 + f305466 commit b4e75bd

File tree

78 files changed

+753
-315
lines changed

Some content is hidden

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

78 files changed

+753
-315
lines changed

compiler/rustc_ast/src/ast.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,10 @@ pub enum ExprKind {
14541454
Block(P<Block>, Option<Label>),
14551455
/// An `async` block (`async move { ... }`),
14561456
/// or a `gen` block (`gen move { ... }`)
1457-
Gen(CaptureBy, P<Block>, GenBlockKind),
1457+
///
1458+
/// The span is the "decl", which is the header before the body `{ }`
1459+
/// including the `asyng`/`gen` keywords and possibly `move`.
1460+
Gen(CaptureBy, P<Block>, GenBlockKind, Span),
14581461
/// An await expression (`my_future.await`). Span is of await keyword.
14591462
Await(P<Expr>, Span),
14601463

compiler/rustc_ast/src/mut_visit.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1528,8 +1528,9 @@ pub fn noop_visit_expr<T: MutVisitor>(
15281528
visit_opt(label, |label| vis.visit_label(label));
15291529
vis.visit_block(blk);
15301530
}
1531-
ExprKind::Gen(_capture_by, body, _kind) => {
1531+
ExprKind::Gen(_capture_by, body, _kind, decl_span) => {
15321532
vis.visit_block(body);
1533+
vis.visit_span(decl_span);
15331534
}
15341535
ExprKind::Await(expr, await_kw_span) => {
15351536
vis.visit_expr(expr);

compiler/rustc_ast/src/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
11221122
visit_opt!(visitor, visit_label, opt_label);
11231123
try_visit!(visitor.visit_block(block));
11241124
}
1125-
ExprKind::Gen(_capt, body, _kind) => try_visit!(visitor.visit_block(body)),
1125+
ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)),
11261126
ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)),
11271127
ExprKind::Assign(lhs, rhs, _span) => {
11281128
try_visit!(visitor.visit_expr(lhs));

compiler/rustc_ast_lowering/src/expr.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
227227
*fn_arg_span,
228228
),
229229
},
230-
ExprKind::Gen(capture_clause, block, genblock_kind) => {
230+
ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {
231231
let desugaring_kind = match genblock_kind {
232232
GenBlockKind::Async => hir::CoroutineDesugaring::Async,
233233
GenBlockKind::Gen => hir::CoroutineDesugaring::Gen,
@@ -237,6 +237,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
237237
*capture_clause,
238238
e.id,
239239
None,
240+
*decl_span,
240241
e.span,
241242
desugaring_kind,
242243
hir::CoroutineSource::Block,
@@ -616,6 +617,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
616617
capture_clause: CaptureBy,
617618
closure_node_id: NodeId,
618619
return_ty: Option<hir::FnRetTy<'hir>>,
620+
fn_decl_span: Span,
619621
span: Span,
620622
desugaring_kind: hir::CoroutineDesugaring,
621623
coroutine_source: hir::CoroutineSource,
@@ -692,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
692694
bound_generic_params: &[],
693695
fn_decl,
694696
body,
695-
fn_decl_span: self.lower_span(span),
697+
fn_decl_span: self.lower_span(fn_decl_span),
696698
fn_arg_span: None,
697699
kind: hir::ClosureKind::Coroutine(coroutine_kind),
698700
constness: hir::Constness::NotConst,
@@ -1083,6 +1085,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10831085
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
10841086
&inner_decl,
10851087
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
1088+
fn_decl_span,
10861089
body.span,
10871090
coroutine_kind,
10881091
hir::CoroutineSource::Closure,

compiler/rustc_ast_lowering/src/item.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
211211
// declaration (decl), not the return types.
212212
let coroutine_kind = header.coroutine_kind;
213213
let body_id = this.lower_maybe_coroutine_body(
214+
*fn_sig_span,
214215
span,
215216
hir_id,
216217
decl,
@@ -799,6 +800,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
799800
}
800801
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
801802
let body_id = self.lower_maybe_coroutine_body(
803+
sig.span,
802804
i.span,
803805
hir_id,
804806
&sig.decl,
@@ -915,6 +917,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
915917
),
916918
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
917919
let body_id = self.lower_maybe_coroutine_body(
920+
sig.span,
918921
i.span,
919922
hir_id,
920923
&sig.decl,
@@ -1111,6 +1114,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11111114
/// `gen {}` block as appropriate.
11121115
fn lower_maybe_coroutine_body(
11131116
&mut self,
1117+
fn_decl_span: Span,
11141118
span: Span,
11151119
fn_id: hir::HirId,
11161120
decl: &FnDecl,
@@ -1124,6 +1128,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11241128
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
11251129
decl,
11261130
|this| this.lower_block_expr(body),
1131+
fn_decl_span,
11271132
body.span,
11281133
coroutine_kind,
11291134
hir::CoroutineSource::Fn,
@@ -1145,6 +1150,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11451150
&mut self,
11461151
decl: &FnDecl,
11471152
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
1153+
fn_decl_span: Span,
11481154
body_span: Span,
11491155
coroutine_kind: CoroutineKind,
11501156
coroutine_source: hir::CoroutineSource,
@@ -1315,13 +1321,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
13151321
};
13161322
let closure_id = coroutine_kind.closure_id();
13171323

1318-
let span = if let FnRetTy::Default(span) = decl.output
1319-
&& matches!(coroutine_source, rustc_hir::CoroutineSource::Closure)
1320-
{
1321-
body_span.with_lo(span.lo())
1322-
} else {
1323-
body_span
1324-
};
13251324
let coroutine_expr = self.make_desugared_coroutine_expr(
13261325
// The default capture mode here is by-ref. Later on during upvar analysis,
13271326
// we will force the captured arguments to by-move, but for async closures,
@@ -1330,7 +1329,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
13301329
CaptureBy::Ref,
13311330
closure_id,
13321331
None,
1333-
span,
1332+
fn_decl_span,
1333+
body_span,
13341334
desugaring_kind,
13351335
coroutine_source,
13361336
mkbody,

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ impl<'a> State<'a> {
540540
self.ibox(0);
541541
self.print_block_with_attrs(blk, attrs);
542542
}
543-
ast::ExprKind::Gen(capture_clause, blk, kind) => {
543+
ast::ExprKind::Gen(capture_clause, blk, kind, _decl_span) => {
544544
self.word_nbsp(kind.modifier());
545545
self.print_capture_clause(*capture_clause);
546546
// cbox/ibox in analogy to the `ExprKind::Block` arm above

compiler/rustc_builtin_macros/src/assert/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
298298
// sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test.
299299
ExprKind::Assign(_, _, _)
300300
| ExprKind::AssignOp(_, _, _)
301-
| ExprKind::Gen(_, _, _)
301+
| ExprKind::Gen(_, _, _, _)
302302
| ExprKind::Await(_, _)
303303
| ExprKind::Block(_, _)
304304
| ExprKind::Break(_, _)

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

0 commit comments

Comments
 (0)