@@ -210,35 +210,57 @@ fn function_return_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll
210210fn instrument_function_attr < ' ll > (
211211 cx : & SimpleCx < ' ll > ,
212212 sess : & Session ,
213+ instrument_fn : & Option < bool > ,
213214) -> SmallVec < [ & ' ll Attribute ; 4 ] > {
214215 let mut attrs = SmallVec :: new ( ) ;
215216 if sess. opts . unstable_opts . instrument_mcount {
216217 // Similar to `clang -pg` behavior. Handled by the
217218 // `post-inline-ee-instrument` LLVM pass.
218219
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 ( ) ,
224- } ;
220+ // #[instrument_fn], the default is on.
221+ let instrument_entry = instrument_fn. unwrap_or_else ( || true ) ;
225222
226- attrs. push ( llvm:: CreateAttrStringValue (
227- cx. llcx ,
228- "instrument-function-entry-inlined" ,
229- mcount_name,
230- ) ) ;
223+ if instrument_entry {
224+ // The function name varies on platforms.
225+ // See test/CodeGen/mcount.c in clang.
226+ let mcount_name = match & sess. target . llvm_mcount_intrinsic {
227+ Some ( llvm_mcount_intrinsic) => llvm_mcount_intrinsic. as_ref ( ) ,
228+ None => sess. target . mcount . as_ref ( ) ,
229+ } ;
230+
231+ attrs. push ( llvm:: CreateAttrStringValue (
232+ cx. llcx ,
233+ "instrument-function-entry-inlined" ,
234+ mcount_name,
235+ ) ) ;
236+ }
231237 }
232238 if let Some ( options) = & sess. opts . unstable_opts . instrument_xray {
233239 // XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
234240 // Function prologue and epilogue are instrumented with NOP sleds,
235241 // 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" ) ) ;
242+
243+ let mut never = options. never ;
244+ let mut always = options. always ;
245+
246+ // Apply optional #[instrument_fn] override.
247+ match instrument_fn {
248+ Some ( true ) => {
249+ always = true ;
250+ }
251+ Some ( false ) => {
252+ never = true ;
253+ }
254+ None => { }
238255 }
239- if options. never {
256+
257+ if never {
240258 attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "function-instrument" , "xray-never" ) ) ;
241259 }
260+ if always {
261+ attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "function-instrument" , "xray-always" ) ) ;
262+ }
263+
242264 if options. ignore_loops {
243265 attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-ignore-loops" ) ) ;
244266 }
@@ -250,6 +272,7 @@ fn instrument_function_attr<'ll>(
250272 "xray-instruction-threshold" ,
251273 & threshold. to_string ( ) ,
252274 ) ) ;
275+
253276 if options. skip_entry {
254277 attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-skip-entry" ) ) ;
255278 }
@@ -442,7 +465,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
442465 // FIXME: none of these functions interact with source level attributes.
443466 to_add. extend ( frame_pointer_type_attr ( cx, sess) ) ;
444467 to_add. extend ( function_return_attr ( cx, sess) ) ;
445- to_add. extend ( instrument_function_attr ( cx, sess) ) ;
468+ to_add. extend ( instrument_function_attr ( cx, sess, & codegen_fn_attrs . instrument_fn ) ) ;
446469 to_add. extend ( nojumptables_attr ( cx, sess) ) ;
447470 to_add. extend ( probestack_attr ( cx, tcx) ) ;
448471 to_add. extend ( stackprotector_attr ( cx, sess) ) ;
0 commit comments