Skip to content

Commit 62b33fc

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. TODO: make and update tracking issue
1 parent eab3d97 commit 62b33fc

16 files changed

Lines changed: 328 additions & 15 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,47 @@ impl CombineAttributeParser for ForceTargetFeatureParser {
550550
}
551551
}
552552

553+
pub(crate) struct InstrumentFnParser;
554+
555+
impl SingleAttributeParser for InstrumentFnParser {
556+
const PATH: &[Symbol] = &[sym::instrument_fn];
557+
558+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
559+
Allow(Target::Fn),
560+
Allow(Target::Method(MethodKind::Inherent)),
561+
Allow(Target::Method(MethodKind::Trait { body: true })),
562+
Allow(Target::Method(MethodKind::TraitImpl)),
563+
]);
564+
565+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "on|off");
566+
567+
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error;
568+
569+
fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
570+
let mut instrument = None;
571+
match args {
572+
ArgParser::NameValue(nv) => {
573+
if let Some(option) = nv.value_as_str()
574+
&& (option == sym::off || option == sym::on)
575+
{
576+
instrument = Some(option == sym::on);
577+
} else {
578+
cx.adcx()
579+
.expected_specific_argument_strings(nv.value_span, &[sym::on, sym::off]);
580+
}
581+
}
582+
ArgParser::List(l) => {
583+
cx.adcx().expected_single_argument(l.span, l.len());
584+
}
585+
ArgParser::NoArgs => {
586+
let span = cx.attr_span;
587+
cx.adcx().expected_specific_argument_strings(span, &[sym::on, sym::off]);
588+
}
589+
}
590+
Some(AttributeKind::InstrumentFn(instrument))
591+
}
592+
}
593+
553594
pub(crate) struct SanitizeParser;
554595

555596
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
@@ -180,6 +180,7 @@ attribute_parsers!(
180180
Single<IgnoreParser>,
181181
Single<InlineParser>,
182182
Single<InstructionSetParser>,
183+
Single<InstrumentFnParser>,
183184
Single<LangParser>,
184185
Single<LinkNameParser>,
185186
Single<LinkOrdinalParser>,

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -201,35 +201,57 @@ fn function_return_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll
201201
fn instrument_function_attr<'ll>(
202202
cx: &SimpleCx<'ll>,
203203
sess: &Session,
204+
instrument_fn: &Option<bool>,
204205
) -> SmallVec<[&'ll Attribute; 4]> {
205206
let mut attrs = SmallVec::new();
206207
if sess.opts.unstable_opts.instrument_mcount {
207208
// Similar to `clang -pg` behavior. Handled by the
208209
// `post-inline-ee-instrument` LLVM pass.
209210

210-
// The function name varies on platforms.
211-
// See test/CodeGen/mcount.c in clang.
212-
let mcount_name = match &sess.target.llvm_mcount_intrinsic {
213-
Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
214-
None => sess.target.mcount.as_ref(),
215-
};
211+
// #[instrument_fn], the default is on.
212+
let instrument_entry = instrument_fn.unwrap_or_else(|| true);
216213

217-
attrs.push(llvm::CreateAttrStringValue(
218-
cx.llcx,
219-
"instrument-function-entry-inlined",
220-
mcount_name,
221-
));
214+
if instrument_entry {
215+
// The function name varies on platforms.
216+
// See test/CodeGen/mcount.c in clang.
217+
let mcount_name = match &sess.target.llvm_mcount_intrinsic {
218+
Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
219+
None => sess.target.mcount.as_ref(),
220+
};
221+
222+
attrs.push(llvm::CreateAttrStringValue(
223+
cx.llcx,
224+
"instrument-function-entry-inlined",
225+
mcount_name,
226+
));
227+
}
222228
}
223229
if let Some(options) = &sess.opts.unstable_opts.instrument_xray {
224230
// XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
225231
// Function prologue and epilogue are instrumented with NOP sleds,
226232
// a runtime library later replaces them with detours into tracing code.
227-
if options.always {
228-
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-always"));
233+
234+
let mut never = options.never;
235+
let mut always = options.always;
236+
237+
// Apply optional #[instrument_fn] override.
238+
match instrument_fn {
239+
Some(true) => {
240+
always = true;
241+
}
242+
Some(false) => {
243+
never = true;
244+
}
245+
None => {}
229246
}
230-
if options.never {
247+
248+
if never {
231249
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-never"));
232250
}
251+
if always {
252+
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-always"));
253+
}
254+
233255
if options.ignore_loops {
234256
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-ignore-loops"));
235257
}
@@ -241,6 +263,7 @@ fn instrument_function_attr<'ll>(
241263
"xray-instruction-threshold",
242264
&threshold.to_string(),
243265
));
266+
244267
if options.skip_entry {
245268
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-entry"));
246269
}
@@ -429,7 +452,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
429452
// FIXME: none of these functions interact with source level attributes.
430453
to_add.extend(frame_pointer_type_attr(cx, sess));
431454
to_add.extend(function_return_attr(cx, sess));
432-
to_add.extend(instrument_function_attr(cx, sess));
455+
to_add.extend(instrument_function_attr(cx, sess, &codegen_fn_attrs.instrument_fn));
433456
to_add.extend(nojumptables_attr(cx, sess));
434457
to_add.extend(probestack_attr(cx, tcx));
435458
to_add.extend(stackprotector_attr(cx, sess));

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ fn process_builtin_attrs(
293293
codegen_fn_attrs.patchable_function_entry =
294294
Some(PatchableFunctionEntry::from_prefix_and_entry(*prefix, *entry));
295295
}
296+
AttributeKind::InstrumentFn(instrument_fn) => {
297+
codegen_fn_attrs.instrument_fn = *instrument_fn;
298+
}
296299
_ => {}
297300
}
298301
}

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
392392
// - https://github.com/rust-lang/rust/issues/130494
393393
gated!(pin_v2, pin_ergonomics, experimental!(pin_v2)),
394394

395+
// RFC 3917
396+
// `#[instrument_fn = "on|off"]` to insert or inhibit instrumentation function
397+
// calls inside a function, usually around the prologue.
398+
gated!(
399+
instrument_fn, instrument_fn, experimental!(instrument_fn),
400+
),
401+
395402
// ==========================================================================
396403
// Internal attributes: Stability, deprecation, and unsafe:
397404
// ==========================================================================

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 (todo: tracking issue)
597+
(unstable, instrument_fn, "CURRENT_RUSTC_VERSION", Some(99999)),
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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,9 @@ pub enum AttributeKind {
10601060
/// Represents `#[instruction_set]`
10611061
InstructionSet(InstructionSetAttr),
10621062

1063+
/// Represents `#[instrument_fn]`
1064+
InstrumentFn(Option<bool>),
1065+
10631066
/// Represents `#[lang]`
10641067
Lang(LangItem),
10651068

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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ 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: Option<bool>,
112114
}
113115

114116
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, StableHash, PartialEq, Eq)]
@@ -236,6 +238,7 @@ impl CodegenFnAttrs {
236238
patchable_function_entry: None,
237239
objc_class: None,
238240
objc_selector: None,
241+
instrument_fn: None,
239242
}
240243
}
241244

compiler/rustc_passes/src/check_attr.rs

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

0 commit comments

Comments
 (0)