@@ -6,7 +6,9 @@ use rustc_middle::middle::codegen_fn_attrs::{
66 CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry , SanitizerFnAttrs ,
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_symbol_mangling:: mangle_internal_symbol;
1113use rustc_target:: spec:: { Arch , FramePointer , SanitizerSet , StackProbeType , StackProtector } ;
1214use smallvec:: SmallVec ;
@@ -173,7 +175,7 @@ pub(crate) fn frame_pointer_type_attr<'ll>(
173175 let opts = & sess. opts ;
174176 // "mcount" function relies on stack pointer.
175177 // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
176- if opts. unstable_opts . instrument_mcount {
178+ if opts. unstable_opts . instrument_function == InstrumentFunction :: Mcount {
177179 fp. ratchet ( FramePointer :: Always ) ;
178180 }
179181 fp. ratchet ( opts. cg . force_frame_pointers ) ;
@@ -202,83 +204,101 @@ fn instrument_function_attr<'ll>(
202204 instrument_fn : & Option < bool > ,
203205) -> SmallVec < [ & ' ll Attribute ; 4 ] > {
204206 let mut attrs = SmallVec :: new ( ) ;
205- if sess. opts . unstable_opts . instrument_mcount || sess. opts . unstable_opts . instrument_fentry {
206- // Similar to `clang -pg` behavior. Handled by the
207- // `post-inline-ee-instrument` LLVM pass.
208-
209- // #[instrument_fn], the default is on.
210- let instrument_entry = instrument_fn. unwrap_or_else ( || true ) ;
211-
212- if instrument_entry && sess. opts . unstable_opts . instrument_mcount {
213- // The function name varies on platforms.
214- // See test/CodeGen/mcount.c in clang.
215- let mcount_name = match & sess. target . llvm_mcount_intrinsic {
216- Some ( llvm_mcount_intrinsic) => llvm_mcount_intrinsic. as_ref ( ) ,
217- None => sess. target . mcount . as_ref ( ) ,
218- } ;
207+ match sess. opts . unstable_opts . instrument_function {
208+ InstrumentFunction :: Fentry => {
209+ // Similar to `clang -pg -mfentry` behavior.
219210
220- attrs. push ( llvm:: CreateAttrStringValue (
221- cx. llcx ,
222- "instrument-function-entry-inlined" ,
223- mcount_name,
224- ) ) ;
225- }
211+ // #[instrument_fn], the default is on.
212+ let instrument_entry = instrument_fn. unwrap_or_else ( || true ) ;
226213
227- if instrument_entry && sess. opts . unstable_opts . instrument_fentry {
228- attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "fentry-call" , "true" ) ) ;
229- }
214+ if instrument_entry {
215+ attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "fentry-call" , "true" ) ) ;
230216
231- if sess. opts . unstable_opts . instrument_mcount_opts . no_call {
232- attrs. push ( llvm:: CreateAttrString ( cx. llcx , "mnop-mcount" ) ) ;
217+ if sess. opts . unstable_opts . instrument_fentry_opts . no_call {
218+ attrs. push ( llvm:: CreateAttrString ( cx. llcx , "mnop-mcount" ) ) ;
219+ }
220+ if sess. opts . unstable_opts . instrument_fentry_opts . record {
221+ attrs. push ( llvm:: CreateAttrString ( cx. llcx , "mrecord-mcount" ) ) ;
222+ }
223+ }
233224 }
234- if sess. opts . unstable_opts . instrument_mcount_opts . record {
235- attrs. push ( llvm:: CreateAttrString ( cx. llcx , "mrecord-mcount" ) ) ;
225+ InstrumentFunction :: Mcount => {
226+ // Similar to `clang -pg` behavior. Handled by the
227+ // `post-inline-ee-instrument` LLVM pass.
228+
229+ // #[instrument_fn], the default is on.
230+ let instrument_entry = instrument_fn. unwrap_or_else ( || true ) ;
231+
232+ if instrument_entry {
233+ // The function name varies on platforms.
234+ // See test/CodeGen/mcount.c in clang.
235+ let mcount_name = match & sess. target . llvm_mcount_intrinsic {
236+ Some ( llvm_mcount_intrinsic) => llvm_mcount_intrinsic. as_ref ( ) ,
237+ None => sess. target . mcount . as_ref ( ) ,
238+ } ;
239+
240+ attrs. push ( llvm:: CreateAttrStringValue (
241+ cx. llcx ,
242+ "instrument-function-entry-inlined" ,
243+ mcount_name,
244+ ) ) ;
245+ }
236246 }
237- }
238- if let Some ( options) = & sess. opts . unstable_opts . instrument_xray {
239- // XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
240- // Function prologue and epilogue are instrumented with NOP sleds,
241- // a runtime library later replaces them with detours into tracing code.
242-
243- let mut never = options. never ;
244- let mut always = options. always ;
247+ InstrumentFunction :: XRay => {
248+ // XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
249+ // Function prologue and epilogue are instrumented with NOP sleds,
250+ // a runtime library later replaces them with detours into tracing code.
251+ let options = & sess. opts . unstable_opts . instrument_xray_opts ;
252+
253+ let mut never = options. never ;
254+ let mut always = options. always ;
255+
256+ // Apply optional #[instrument_fn] override.
257+ match instrument_fn {
258+ Some ( true ) => {
259+ always = true ;
260+ }
261+ Some ( false ) => {
262+ never = true ;
263+ }
264+ None => { }
265+ }
245266
246- // Apply optional #[instrument_fn] override.
247- match instrument_fn {
248- Some ( true ) => {
249- always = true ;
267+ if never {
268+ attrs. push ( llvm:: CreateAttrStringValue (
269+ cx. llcx ,
270+ "function-instrument" ,
271+ "xray-never" ,
272+ ) ) ;
250273 }
251- Some ( false ) => {
252- never = true ;
274+ if always {
275+ attrs. push ( llvm:: CreateAttrStringValue (
276+ cx. llcx ,
277+ "function-instrument" ,
278+ "xray-always" ,
279+ ) ) ;
253280 }
254- None => { }
255- }
256281
257- if never {
258- attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "function-instrument" , "xray-never" ) ) ;
259- }
260- if always {
261- attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "function-instrument" , "xray-always" ) ) ;
262- }
263-
264- if options. ignore_loops {
265- attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-ignore-loops" ) ) ;
266- }
267- // LLVM will not choose the default for us, but rather requires specific
268- // threshold in absence of "xray-always". Use the same default as Clang.
269- let threshold = options. instruction_threshold . unwrap_or ( 200 ) ;
270- attrs. push ( llvm:: CreateAttrStringValue (
271- cx. llcx ,
272- "xray-instruction-threshold" ,
273- & threshold. to_string ( ) ,
274- ) ) ;
282+ if options. ignore_loops {
283+ attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-ignore-loops" ) ) ;
284+ }
285+ // LLVM will not choose the default for us, but rather requires specific
286+ // threshold in absence of "xray-always". Use the same default as Clang.
287+ let threshold = options. instruction_threshold . unwrap_or ( 200 ) ;
288+ attrs. push ( llvm:: CreateAttrStringValue (
289+ cx. llcx ,
290+ "xray-instruction-threshold" ,
291+ & threshold. to_string ( ) ,
292+ ) ) ;
275293
276- if options. skip_entry {
277- attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-skip-entry" ) ) ;
278- }
279- if options. skip_exit {
280- attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-skip-exit" ) ) ;
294+ if options. skip_entry {
295+ attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-skip-entry" ) ) ;
296+ }
297+ if options. skip_exit {
298+ attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-skip-exit" ) ) ;
299+ }
281300 }
301+ InstrumentFunction :: No => { }
282302 }
283303 attrs
284304}
0 commit comments