Skip to content

Commit ebc3b52

Browse files
authored
Rollup merge of #157681 - pmur:murp/add-instrument_fn-attr, r=oli-obk,mejrs
Add instrument_fn attribute This attribute enables or disables function instrumentation when using `-Zinstrument-xray` or `-Zinstrument-mcount`. It supports the following usage: `#[instrument_fn = "on|off"]` For XRay, "on" is equivalent to always instrument, and "off" is equivalent to never instrumenting. For mcount, "on" has no effect. "off" disables instrumentation of the function. This is tracked by #157081, and related to the pending rfc rust-lang/rfcs#3917, and earlier as part mcp rust-lang/compiler-team#561
2 parents 9e2abe0 + f638abc commit ebc3b52

16 files changed

Lines changed: 395 additions & 18 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use rustc_feature::AttributeStability;
2-
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy};
2+
use rustc_hir::attrs::{
3+
CoverageAttrKind, InstrumentFnAttr, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy,
4+
};
35
use rustc_session::errors::feature_err;
46
use rustc_span::edition::Edition::Edition2024;
57

@@ -575,6 +577,44 @@ impl CombineAttributeParser for ForceTargetFeatureParser {
575577
}
576578
}
577579

580+
pub(crate) struct InstrumentFnParser;
581+
582+
impl SingleAttributeParser for InstrumentFnParser {
583+
const PATH: &[Symbol] = &[sym::instrument_fn];
584+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
585+
Allow(Target::Fn),
586+
Allow(Target::Method(MethodKind::Inherent)),
587+
Allow(Target::Method(MethodKind::Trait { body: true })),
588+
Allow(Target::Method(MethodKind::TraitImpl)),
589+
]);
590+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "on|off");
591+
const STABILITY: AttributeStability = unstable!(instrument_fn);
592+
593+
fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
594+
let instrument = match args {
595+
ArgParser::NameValue(nv) => match nv.value_as_str() {
596+
Some(sym::on) => Some(AttributeKind::InstrumentFn(InstrumentFnAttr::On)),
597+
Some(sym::off) => Some(AttributeKind::InstrumentFn(InstrumentFnAttr::Off)),
598+
_ => {
599+
cx.adcx()
600+
.expected_specific_argument_strings(nv.value_span, &[sym::on, sym::off]);
601+
None
602+
}
603+
},
604+
ArgParser::List(l) => {
605+
cx.adcx().expected_single_argument(l.span, l.len());
606+
None
607+
}
608+
ArgParser::NoArgs => {
609+
let span = cx.attr_span;
610+
cx.adcx().expected_specific_argument_strings(span, &[sym::on, sym::off]);
611+
None
612+
}
613+
};
614+
instrument
615+
}
616+
}
617+
578618
pub(crate) struct SanitizeParser;
579619

580620
impl SingleAttributeParser for SanitizeParser {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ attribute_parsers!(
189189
Single<IgnoreParser>,
190190
Single<InlineParser>,
191191
Single<InstructionSetParser>,
192+
Single<InstrumentFnParser>,
192193
Single<LangParser>,
193194
Single<LinkNameParser>,
194195
Single<LinkOrdinalParser>,

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSettin
33
use rustc_hir::def_id::DefId;
44
use rustc_hir::find_attr;
55
use rustc_middle::middle::codegen_fn_attrs::{
6-
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, TargetFeature,
6+
CodegenFnAttrFlags, CodegenFnAttrs, InstrumentFnAttr, PatchableFunctionEntry, SanitizerFnAttrs,
7+
TargetFeature,
78
};
89
use rustc_middle::ty::{self, Instance, TyCtxt};
910
use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
@@ -210,35 +211,59 @@ fn function_return_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll
210211
fn instrument_function_attr<'ll>(
211212
cx: &SimpleCx<'ll>,
212213
sess: &Session,
214+
instrument_fn: InstrumentFnAttr,
213215
) -> SmallVec<[&'ll Attribute; 4]> {
214216
let mut attrs = SmallVec::new();
215217
if sess.opts.unstable_opts.instrument_mcount {
216218
// Similar to `clang -pg` behavior. Handled by the
217219
// `post-inline-ee-instrument` LLVM pass.
218220

219-
// The function name varies on platforms.
220-
// See test/CodeGen/mcount.c in clang.
221-
let mcount_name = match &sess.target.llvm_mcount_intrinsic {
222-
Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
223-
None => sess.target.mcount.as_ref(),
221+
let instrument_entry = match instrument_fn {
222+
InstrumentFnAttr::Default | InstrumentFnAttr::On => true,
223+
InstrumentFnAttr::Off => false,
224224
};
225225

226-
attrs.push(llvm::CreateAttrStringValue(
227-
cx.llcx,
228-
"instrument-function-entry-inlined",
229-
mcount_name,
230-
));
226+
if instrument_entry {
227+
// The function name varies on platforms.
228+
// See test/CodeGen/mcount.c in clang.
229+
let mcount_name = match &sess.target.llvm_mcount_intrinsic {
230+
Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
231+
None => sess.target.mcount.as_ref(),
232+
};
233+
234+
attrs.push(llvm::CreateAttrStringValue(
235+
cx.llcx,
236+
"instrument-function-entry-inlined",
237+
mcount_name,
238+
));
239+
}
231240
}
232241
if let Some(options) = &sess.opts.unstable_opts.instrument_xray {
233242
// XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
234243
// Function prologue and epilogue are instrumented with NOP sleds,
235244
// a runtime library later replaces them with detours into tracing code.
236-
if options.always {
237-
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-always"));
245+
246+
let mut never = options.never;
247+
let mut always = options.always;
248+
249+
// always and never may be overridden by the #[instrument_fn = ...] attribute.
250+
match instrument_fn {
251+
InstrumentFnAttr::Default => {}
252+
InstrumentFnAttr::On => {
253+
always = true;
254+
}
255+
InstrumentFnAttr::Off => {
256+
never = true;
257+
}
238258
}
239-
if options.never {
259+
260+
if never {
240261
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-never"));
241262
}
263+
if always {
264+
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-always"));
265+
}
266+
242267
if options.ignore_loops {
243268
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-ignore-loops"));
244269
}
@@ -442,7 +467,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
442467
// FIXME: none of these functions interact with source level attributes.
443468
to_add.extend(frame_pointer_type_attr(cx, sess));
444469
to_add.extend(function_return_attr(cx, sess));
445-
to_add.extend(instrument_function_attr(cx, sess));
470+
to_add.extend(instrument_function_attr(cx, sess, codegen_fn_attrs.instrument_fn));
446471
to_add.extend(nojumptables_attr(cx, sess));
447472
to_add.extend(probestack_attr(cx, tcx));
448473
to_add.extend(stackprotector_attr(cx, sess));

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use rustc_abi::{Align, ExternAbi};
22
use rustc_hir::attrs::{
3-
AttributeKind, EiiImplResolution, InlineAttr, Linkage, RtsanSetting, UsedBy,
3+
AttributeKind, EiiImplResolution, InlineAttr, InstrumentFnAttr as HirInstrumentFnAttr, Linkage,
4+
RtsanSetting, UsedBy,
45
};
56
use rustc_hir::def::DefKind;
67
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
78
use rustc_hir::{self as hir, Attribute, find_attr};
89
use rustc_macros::Diagnostic;
910
use rustc_middle::middle::codegen_fn_attrs::{
10-
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs,
11+
CodegenFnAttrFlags, CodegenFnAttrs, InstrumentFnAttr, PatchableFunctionEntry, SanitizerFnAttrs,
1112
};
1213
use rustc_middle::mono::Visibility;
1314
use rustc_middle::query::Providers;
@@ -293,6 +294,12 @@ fn process_builtin_attrs(
293294
codegen_fn_attrs.patchable_function_entry =
294295
Some(PatchableFunctionEntry::from_prefix_and_entry(*prefix, *entry));
295296
}
297+
AttributeKind::InstrumentFn(instrument_fn) => {
298+
codegen_fn_attrs.instrument_fn = match instrument_fn {
299+
HirInstrumentFnAttr::On => InstrumentFnAttr::On,
300+
HirInstrumentFnAttr::Off => InstrumentFnAttr::Off,
301+
};
302+
}
296303
_ => {}
297304
}
298305
}

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[
219219
// - https://github.com/rust-lang/rust/pull/156816
220220
sym::unroll,
221221

222+
// `#[instrument_fn = "on|off"]` to insert or inhibit instrumentation function
223+
// calls inside a function, usually around the prologue.
224+
//
225+
// - https://github.com/rust-lang/rust/issues/157081
226+
sym::instrument_fn,
227+
222228
// ==========================================================================
223229
// Internal attributes: Stability, deprecation, and unsafe:
224230
// ==========================================================================

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,8 @@ declare_features! (
595595
(unstable, import_trait_associated_functions, "1.86.0", Some(134691)),
596596
/// Allows associated types in inherent impls.
597597
(incomplete, inherent_associated_types, "1.52.0", Some(8995)),
598+
/// Enable #[instrument_fn] on function.
599+
(unstable, instrument_fn, "CURRENT_RUSTC_VERSION", Some(157081)),
598600
/// Allows using `pointer` and `reference` in intra-doc links
599601
(unstable, intra_doc_pointers, "1.51.0", Some(80896)),
600602
/// lahfsahf target feature on x86.

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ pub enum InstructionSetAttr {
143143
ArmT32,
144144
}
145145

146+
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, Eq, StableHash, PrintAttribute)]
147+
pub enum InstrumentFnAttr {
148+
/// `#[instrument_fn = "on"]`
149+
On,
150+
/// `#[instrument_fn = "off"]`
151+
Off,
152+
}
153+
146154
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default, PrintAttribute)]
147155
#[derive(Encodable, Decodable, StableHash)]
148156
pub enum OptimizeAttr {
@@ -1068,6 +1076,9 @@ pub enum AttributeKind {
10681076
/// Represents `#[instruction_set]`
10691077
InstructionSet(InstructionSetAttr),
10701078

1079+
/// Represents `#[instrument_fn]`
1080+
InstrumentFn(InstrumentFnAttr),
1081+
10711082
/// Represents `#[lang]`
10721083
Lang(LangItem),
10731084

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl AttributeKind {
5050
Ignore { .. } => No,
5151
Inline(..) => No,
5252
InstructionSet(..) => No,
53+
InstrumentFn(..) => No,
5354
Lang(..) => Yes,
5455
Link(..) => No,
5556
LinkName { .. } => Yes, // Needed for rustdoc

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,24 @@ pub struct CodegenFnAttrs {
117117
pub objc_class: Option<Symbol>,
118118
/// The `#[rustc_objc_selector = "..."]` attribute.
119119
pub objc_selector: Option<Symbol>,
120+
/// The `#[instrument_fn]` attribute.
121+
pub instrument_fn: InstrumentFnAttr,
122+
}
123+
124+
#[derive(Copy, Clone, TyEncodable, TyDecodable, StableHash, Debug)]
125+
pub enum InstrumentFnAttr {
126+
/// Always instrument function
127+
On,
128+
/// Never instrument function
129+
Off,
130+
/// Instrument based on command line options, if any.
131+
Default,
132+
}
133+
134+
const impl Default for InstrumentFnAttr {
135+
fn default() -> Self {
136+
InstrumentFnAttr::Default
137+
}
120138
}
121139

122140
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, StableHash, PartialEq, Eq)]
@@ -244,6 +262,7 @@ impl CodegenFnAttrs {
244262
patchable_function_entry: None,
245263
objc_class: None,
246264
objc_selector: None,
265+
instrument_fn: InstrumentFnAttr::default(),
247266
}
248267
}
249268

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
280280
AttributeKind::Fundamental => (),
281281
AttributeKind::Ignore { .. } => (),
282282
AttributeKind::InstructionSet(..) => (),
283+
AttributeKind::InstrumentFn(..) => (),
283284
AttributeKind::Lang(..) => (),
284285
AttributeKind::LinkName { .. } => (),
285286
AttributeKind::LinkOrdinal { .. } => (),

0 commit comments

Comments
 (0)