Skip to content

Commit de687ce

Browse files
committed
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.
1 parent beae781 commit de687ce

16 files changed

Lines changed: 392 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

@@ -563,6 +565,44 @@ impl CombineAttributeParser for ForceTargetFeatureParser {
563565
}
564566
}
565567

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

568608
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
@@ -185,6 +185,7 @@ attribute_parsers!(
185185
Single<IgnoreParser>,
186186
Single<InlineParser>,
187187
Single<InstructionSetParser>,
188+
Single<InstrumentFnParser>,
188189
Single<LangParser>,
189190
Single<LinkNameParser>,
190191
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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[
208208
// - https://github.com/rust-lang/rust/issues/130494
209209
sym::pin_v2,
210210

211+
// RFC 3917
212+
// `#[instrument_fn = "on|off"]` to insert or inhibit instrumentation function
213+
// calls inside a function, usually around the prologue.
214+
sym::instrument_fn,
215+
211216
// ==========================================================================
212217
// Internal attributes: Stability, deprecation, and unsafe:
213218
// ==========================================================================

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,8 @@ declare_features! (
593593
(unstable, import_trait_associated_functions, "1.86.0", Some(134691)),
594594
/// Allows associated types in inherent impls.
595595
(incomplete, inherent_associated_types, "1.52.0", Some(8995)),
596+
/// Enable #[instrument_fn] on function.
597+
(unstable, instrument_fn, "CURRENT_RUSTC_VERSION", Some(157081)),
596598
/// Allows using `pointer` and `reference` in intra-doc links
597599
(unstable, intra_doc_pointers, "1.51.0", Some(80896)),
598600
/// 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
@@ -135,6 +135,14 @@ pub enum InstructionSetAttr {
135135
ArmT32,
136136
}
137137

138+
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, Eq, StableHash, PrintAttribute)]
139+
pub enum InstrumentFnAttr {
140+
/// `#[instrument_fn = "on"]`
141+
On,
142+
/// `#[instrument_fn = "off"]`
143+
Off,
144+
}
145+
138146
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default, PrintAttribute)]
139147
#[derive(Encodable, Decodable, StableHash)]
140148
pub enum OptimizeAttr {
@@ -1060,6 +1068,9 @@ pub enum AttributeKind {
10601068
/// Represents `#[instruction_set]`
10611069
InstructionSet(InstructionSetAttr),
10621070

1071+
/// Represents `#[instrument_fn]`
1072+
InstrumentFn(InstrumentFnAttr),
1073+
10631074
/// Represents `#[lang]`
10641075
Lang(LangItem),
10651076

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
@@ -109,6 +109,24 @@ pub struct CodegenFnAttrs {
109109
pub objc_class: Option<Symbol>,
110110
/// The `#[rustc_objc_selector = "..."]` attribute.
111111
pub objc_selector: Option<Symbol>,
112+
/// The `#[instrument_fn]` attribute.
113+
pub instrument_fn: InstrumentFnAttr,
114+
}
115+
116+
#[derive(Copy, Clone, TyEncodable, TyDecodable, StableHash, Debug)]
117+
pub enum InstrumentFnAttr {
118+
/// Always instrument function
119+
On,
120+
/// Never instrument function
121+
Off,
122+
/// Instrument based on command line options, if any.
123+
Default,
124+
}
125+
126+
const impl Default for InstrumentFnAttr {
127+
fn default() -> Self {
128+
InstrumentFnAttr::Default
129+
}
112130
}
113131

114132
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, StableHash, PartialEq, Eq)]
@@ -236,6 +254,7 @@ impl CodegenFnAttrs {
236254
patchable_function_entry: None,
237255
objc_class: None,
238256
objc_selector: None,
257+
instrument_fn: InstrumentFnAttr::default(),
239258
}
240259
}
241260

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
277277
AttributeKind::Fundamental => (),
278278
AttributeKind::Ignore { .. } => (),
279279
AttributeKind::InstructionSet(..) => (),
280+
AttributeKind::InstrumentFn(..) => (),
280281
AttributeKind::Lang(..) => (),
281282
AttributeKind::LinkName { .. } => (),
282283
AttributeKind::LinkOrdinal { .. } => (),

0 commit comments

Comments
 (0)