@@ -6,7 +6,9 @@ use rustc_middle::middle::codegen_fn_attrs::{
66 CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry , SanitizerFnAttrs , TargetFeature ,
77} ;
88use 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+ } ;
1012use rustc_span:: sym;
1113use rustc_symbol_mangling:: mangle_internal_symbol;
1214use 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}
0 commit comments