Skip to content

Commit daa8f1d

Browse files
committed
Refactor -Zinstrument-mcount, -Zinstrument-fentry, -Zinstrument-xray
Convert these into `-Zinstrument-function={none|fentry|xray}`. `-Zinstrument-xray` is split into `-Zinstrument-function=xray` and `-Zinstrument-xray-opts=...`. Also, rename `-Zinstrument-mcount-opts` to `-Zinstrument-fentry-opts` to reflect it is only usable with fentry. In theory, it could work with both (as it does on gcc), in practice the llvm support is limited to s390x/fentry as of llvm 22.
1 parent 327723b commit daa8f1d

28 files changed

Lines changed: 239 additions & 181 deletions

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 88 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use rustc_middle::middle::codegen_fn_attrs::{
66
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs, TargetFeature,
77
};
88
use rustc_middle::ty::{self, TyCtxt};
9-
use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
9+
use rustc_session::config::{
10+
BranchProtection, FunctionReturn, InstrumentFunction, OptLevel, PAuthKey, PacRet,
11+
};
1012
use rustc_span::sym;
1113
use rustc_symbol_mangling::mangle_internal_symbol;
1214
use rustc_target::spec::{Arch, FramePointer, SanitizerSet, StackProbeType, StackProtector};
@@ -175,7 +177,7 @@ pub(crate) fn frame_pointer_type_attr<'ll>(
175177
let opts = &sess.opts;
176178
// "mcount" function relies on stack pointer.
177179
// See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
178-
if opts.unstable_opts.instrument_mcount {
180+
if opts.unstable_opts.instrument_function == InstrumentFunction::Mcount {
179181
fp.ratchet(FramePointer::Always);
180182
}
181183
fp.ratchet(opts.cg.force_frame_pointers);
@@ -204,83 +206,101 @@ fn instrument_function_attr<'ll>(
204206
instrument_fn: &Option<bool>,
205207
) -> SmallVec<[&'ll Attribute; 4]> {
206208
let mut attrs = SmallVec::new();
207-
if sess.opts.unstable_opts.instrument_mcount || sess.opts.unstable_opts.instrument_fentry {
208-
// Similar to `clang -pg` behavior. Handled by the
209-
// `post-inline-ee-instrument` LLVM pass.
210-
211-
// #[instrument_fn], the default is on.
212-
let instrument_entry = instrument_fn.unwrap_or_else(|| true);
213-
214-
if instrument_entry && sess.opts.unstable_opts.instrument_mcount {
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-
};
209+
match sess.opts.unstable_opts.instrument_function {
210+
InstrumentFunction::Fentry => {
211+
// Similar to `clang -pg -mfentry` behavior.
221212

222-
attrs.push(llvm::CreateAttrStringValue(
223-
cx.llcx,
224-
"instrument-function-entry-inlined",
225-
mcount_name,
226-
));
227-
}
213+
// #[instrument_fn], the default is on.
214+
let instrument_entry = instrument_fn.unwrap_or_else(|| true);
228215

229-
if instrument_entry && sess.opts.unstable_opts.instrument_fentry {
230-
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "fentry-call", "true"));
231-
}
216+
if instrument_entry {
217+
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "fentry-call", "true"));
232218

233-
if sess.opts.unstable_opts.instrument_mcount_opts.no_call {
234-
attrs.push(llvm::CreateAttrString(cx.llcx, "mnop-mcount"));
219+
if sess.opts.unstable_opts.instrument_fentry_opts.no_call {
220+
attrs.push(llvm::CreateAttrString(cx.llcx, "mnop-mcount"));
221+
}
222+
if sess.opts.unstable_opts.instrument_fentry_opts.record {
223+
attrs.push(llvm::CreateAttrString(cx.llcx, "mrecord-mcount"));
224+
}
225+
}
235226
}
236-
if sess.opts.unstable_opts.instrument_mcount_opts.record {
237-
attrs.push(llvm::CreateAttrString(cx.llcx, "mrecord-mcount"));
227+
InstrumentFunction::Mcount => {
228+
// Similar to `clang -pg` behavior. Handled by the
229+
// `post-inline-ee-instrument` LLVM pass.
230+
231+
// #[instrument_fn], the default is on.
232+
let instrument_entry = instrument_fn.unwrap_or_else(|| true);
233+
234+
if instrument_entry {
235+
// The function name varies on platforms.
236+
// See test/CodeGen/mcount.c in clang.
237+
let mcount_name = match &sess.target.llvm_mcount_intrinsic {
238+
Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
239+
None => sess.target.mcount.as_ref(),
240+
};
241+
242+
attrs.push(llvm::CreateAttrStringValue(
243+
cx.llcx,
244+
"instrument-function-entry-inlined",
245+
mcount_name,
246+
));
247+
}
238248
}
239-
}
240-
if let Some(options) = &sess.opts.unstable_opts.instrument_xray {
241-
// XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
242-
// Function prologue and epilogue are instrumented with NOP sleds,
243-
// a runtime library later replaces them with detours into tracing code.
244-
245-
let mut never = options.never;
246-
let mut always = options.always;
249+
InstrumentFunction::XRay => {
250+
// XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
251+
// Function prologue and epilogue are instrumented with NOP sleds,
252+
// a runtime library later replaces them with detours into tracing code.
253+
let options = &sess.opts.unstable_opts.instrument_xray_opts;
254+
255+
let mut never = options.never;
256+
let mut always = options.always;
257+
258+
// Apply optional #[instrument_fn] override.
259+
match instrument_fn {
260+
Some(true) => {
261+
always = true;
262+
}
263+
Some(false) => {
264+
never = true;
265+
}
266+
None => {}
267+
}
247268

248-
// Apply optional #[instrument_fn] override.
249-
match instrument_fn {
250-
Some(true) => {
251-
always = true;
269+
if never {
270+
attrs.push(llvm::CreateAttrStringValue(
271+
cx.llcx,
272+
"function-instrument",
273+
"xray-never",
274+
));
252275
}
253-
Some(false) => {
254-
never = true;
276+
if always {
277+
attrs.push(llvm::CreateAttrStringValue(
278+
cx.llcx,
279+
"function-instrument",
280+
"xray-always",
281+
));
255282
}
256-
None => {}
257-
}
258283

259-
if never {
260-
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-never"));
261-
}
262-
if always {
263-
attrs.push(llvm::CreateAttrStringValue(cx.llcx, "function-instrument", "xray-always"));
264-
}
265-
266-
if options.ignore_loops {
267-
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-ignore-loops"));
268-
}
269-
// LLVM will not choose the default for us, but rather requires specific
270-
// threshold in absence of "xray-always". Use the same default as Clang.
271-
let threshold = options.instruction_threshold.unwrap_or(200);
272-
attrs.push(llvm::CreateAttrStringValue(
273-
cx.llcx,
274-
"xray-instruction-threshold",
275-
&threshold.to_string(),
276-
));
284+
if options.ignore_loops {
285+
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-ignore-loops"));
286+
}
287+
// LLVM will not choose the default for us, but rather requires specific
288+
// threshold in absence of "xray-always". Use the same default as Clang.
289+
let threshold = options.instruction_threshold.unwrap_or(200);
290+
attrs.push(llvm::CreateAttrStringValue(
291+
cx.llcx,
292+
"xray-instruction-threshold",
293+
&threshold.to_string(),
294+
));
277295

278-
if options.skip_entry {
279-
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-entry"));
280-
}
281-
if options.skip_exit {
282-
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-exit"));
296+
if options.skip_entry {
297+
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-entry"));
298+
}
299+
if options.skip_exit {
300+
attrs.push(llvm::CreateAttrString(cx.llcx, "xray-skip-exit"));
301+
}
283302
}
303+
InstrumentFunction::No => {}
284304
}
285305
attrs
286306
}

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
3535
use rustc_middle::middle::dependency_format::Linkage;
3636
use rustc_middle::middle::exported_symbols::SymbolExportKind;
3737
use rustc_session::config::{
38-
self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames,
39-
OutputType, PrintKind, SplitDwarfKind, Strip,
38+
self, CFGuard, CrateType, DebugInfo, InstrumentFunction, LinkerFeaturesCli, OutFileName,
39+
OutputFilenames, OutputType, PrintKind, SplitDwarfKind, Strip,
4040
};
4141
use rustc_session::lint::builtin::LINKER_MESSAGES;
4242
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
@@ -2767,8 +2767,11 @@ fn add_order_independent_options(
27672767
cmd.pgo_gen();
27682768
}
27692769

2770-
if sess.opts.unstable_opts.instrument_mcount {
2771-
cmd.enable_profiling();
2770+
match sess.opts.unstable_opts.instrument_function {
2771+
InstrumentFunction::Mcount | InstrumentFunction::Fentry => {
2772+
cmd.enable_profiling();
2773+
}
2774+
_ => {}
27722775
}
27732776

27742777
if sess.opts.cg.control_flow_guard != CFGuard::Disabled {

compiler/rustc_interface/src/tests.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ use rustc_session::config::{
1313
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CoverageLevel, CoverageOptions,
1414
DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
1515
FmtDebug, FunctionReturn, IncrementalStateAssertion, InliningThreshold, Input,
16-
InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli,
17-
MirIncludeSpans, NextSolverConfig, Offload, Options, OutFileName, OutputType, OutputTypes,
18-
PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip,
19-
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, build_configuration,
20-
build_session_options, rustc_optgroups,
16+
InstrumentCoverage, InstrumentFunction, InstrumentMcountOpts, InstrumentXRayOpts,
17+
LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig,
18+
Offload, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes,
19+
PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath,
20+
SymbolManglingVersion, WasiExecModel, build_configuration, build_session_options,
21+
rustc_optgroups,
2122
};
2223
use rustc_session::lint::Level;
2324
use rustc_session::search_paths::SearchPath;
@@ -810,8 +811,12 @@ fn test_unstable_options_tracking_hash() {
810811
tracked!(inline_mir, Some(true));
811812
tracked!(inline_mir_hint_threshold, Some(123));
812813
tracked!(inline_mir_threshold, Some(123));
813-
tracked!(instrument_mcount, true);
814-
tracked!(instrument_xray, Some(InstrumentXRay::default()));
814+
tracked!(instrument_fentry_opts, InstrumentMcountOpts { no_call: true, record: true });
815+
tracked!(instrument_function, InstrumentFunction::Fentry);
816+
tracked!(
817+
instrument_xray_opts,
818+
InstrumentXRayOpts { always: true, ..InstrumentXRayOpts::default() }
819+
);
815820
tracked!(link_directives, false);
816821
tracked!(link_only, true);
817822
tracked!(lint_llvm_ir, true);

compiler/rustc_session/src/config.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,19 @@ pub enum InstrumentCoverage {
151151
Yes,
152152
}
153153

154+
/// The different settings that the `-Z instrument-function` flag can have.
155+
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
156+
pub enum InstrumentFunction {
157+
/// No instrumentation requested, or `-Z instrument-function=none`
158+
No,
159+
/// `-Z instrument-function=fentry`
160+
Fentry,
161+
/// `-Z instrument-function=mcount`
162+
Mcount,
163+
/// `-Z instrument-function=xray`
164+
XRay,
165+
}
166+
154167
/// Individual flag values controlled by `-Zcoverage-options`.
155168
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
156169
pub struct CoverageOptions {
@@ -256,22 +269,22 @@ pub struct InstrumentMcountOpts {
256269
pub record: bool,
257270
}
258271

259-
/// Settings for `-Z instrument-xray` flag.
272+
/// Settings for `-Z instrument-xray-opts` flag.
260273
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
261-
pub struct InstrumentXRay {
262-
/// `-Z instrument-xray=always`, force instrumentation
274+
pub struct InstrumentXRayOpts {
275+
/// `-Z instrument-xray-opts=always`, force instrumentation
263276
pub always: bool,
264-
/// `-Z instrument-xray=never`, disable instrumentation
277+
/// `-Z instrument-xray-opts=never`, disable instrumentation
265278
pub never: bool,
266-
/// `-Z instrument-xray=ignore-loops`, ignore presence of loops,
279+
/// `-Z instrument-xray-opts=ignore-loops`, ignore presence of loops,
267280
/// instrument functions based only on instruction count
268281
pub ignore_loops: bool,
269-
/// `-Z instrument-xray=instruction-threshold=N`, explicitly set instruction threshold
282+
/// `-Z instrument-xray-opts=instruction-threshold=N`, explicitly set instruction threshold
270283
/// for instrumentation, or `None` to use compiler's default
271284
pub instruction_threshold: Option<usize>,
272-
/// `-Z instrument-xray=skip-entry`, do not instrument function entry
285+
/// `-Z instrument-xray-opts=skip-entry`, do not instrument function entry
273286
pub skip_entry: bool,
274-
/// `-Z instrument-xray=skip-exit`, do not instrument function exit
287+
/// `-Z instrument-xray-opts=skip-exit`, do not instrument function exit
275288
pub skip_exit: bool,
276289
}
277290

@@ -3066,11 +3079,11 @@ pub(crate) mod dep_tracking {
30663079
use super::{
30673080
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CoverageOptions,
30683081
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
3069-
InliningThreshold, InstrumentCoverage, InstrumentMcountOpts, InstrumentXRay,
3070-
LinkerPluginLto, LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload,
3071-
OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius,
3072-
ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath,
3073-
SymbolManglingVersion, WasiExecModel,
3082+
InliningThreshold, InstrumentCoverage, InstrumentFunction, InstrumentMcountOpts,
3083+
InstrumentXRayOpts, LinkerPluginLto, LocationDetail, LtoCli, MirStripDebugInfo,
3084+
NextSolverConfig, Offload, OptLevel, OutFileName, OutputType, OutputTypes,
3085+
PatchableFunctionEntry, Polonius, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
3086+
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
30743087
};
30753088
use crate::lint;
30763089
use crate::utils::NativeLib;
@@ -3131,9 +3144,10 @@ pub(crate) mod dep_tracking {
31313144
CodeModel,
31323145
TlsModel,
31333146
InstrumentCoverage,
3147+
InstrumentFunction,
31343148
CoverageOptions,
31353149
InstrumentMcountOpts,
3136-
InstrumentXRay,
3150+
InstrumentXRayOpts,
31373151
CrateType,
31383152
MergeFunctions,
31393153
OnBrokenPipe,

0 commit comments

Comments
 (0)