@@ -3,7 +3,8 @@ use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSettin
33use rustc_hir:: def_id:: DefId ;
44use rustc_hir:: find_attr;
55use rustc_middle:: middle:: codegen_fn_attrs:: {
6- CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry , SanitizerFnAttrs , TargetFeature ,
6+ CodegenFnAttrFlags , CodegenFnAttrs , InstrumentFnAttr , PatchableFunctionEntry , SanitizerFnAttrs ,
7+ TargetFeature ,
78} ;
89use rustc_middle:: ty:: { self , Instance , TyCtxt } ;
910use rustc_session:: config:: { BranchProtection , FunctionReturn , OptLevel , PAuthKey , PacRet } ;
@@ -210,35 +211,59 @@ fn function_return_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll
210211fn instrument_function_attr < ' ll > (
211212 cx : & SimpleCx < ' ll > ,
212213 sess : & Session ,
214+ instrument_fn : InstrumentFnAttr ,
213215) -> SmallVec < [ & ' ll Attribute ; 4 ] > {
214216 let mut attrs = SmallVec :: new ( ) ;
215217 if sess. opts . unstable_opts . instrument_mcount {
216218 // Similar to `clang -pg` behavior. Handled by the
217219 // `post-inline-ee-instrument` LLVM pass.
218220
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 ( ) ,
221+ let instrument_entry = match instrument_fn {
222+ InstrumentFnAttr :: Default | InstrumentFnAttr :: On => true ,
223+ InstrumentFnAttr :: Off => false ,
224224 } ;
225225
226- attrs. push ( llvm:: CreateAttrStringValue (
227- cx. llcx ,
228- "instrument-function-entry-inlined" ,
229- mcount_name,
230- ) ) ;
226+ if instrument_entry {
227+ // The function name varies on platforms.
228+ // See test/CodeGen/mcount.c in clang.
229+ let mcount_name = match & sess. target . llvm_mcount_intrinsic {
230+ Some ( llvm_mcount_intrinsic) => llvm_mcount_intrinsic. as_ref ( ) ,
231+ None => sess. target . mcount . as_ref ( ) ,
232+ } ;
233+
234+ attrs. push ( llvm:: CreateAttrStringValue (
235+ cx. llcx ,
236+ "instrument-function-entry-inlined" ,
237+ mcount_name,
238+ ) ) ;
239+ }
231240 }
232241 if let Some ( options) = & sess. opts . unstable_opts . instrument_xray {
233242 // XRay instrumentation is similar to __cyg_profile_func_{enter,exit}.
234243 // Function prologue and epilogue are instrumented with NOP sleds,
235244 // 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" ) ) ;
245+
246+ let mut never = options. never ;
247+ let mut always = options. always ;
248+
249+ // always and never may be overridden by the #[instrument_fn = ...] attribute.
250+ match instrument_fn {
251+ InstrumentFnAttr :: Default => { }
252+ InstrumentFnAttr :: On => {
253+ always = true ;
254+ }
255+ InstrumentFnAttr :: Off => {
256+ never = true ;
257+ }
238258 }
239- if options. never {
259+
260+ if never {
240261 attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "function-instrument" , "xray-never" ) ) ;
241262 }
263+ if always {
264+ attrs. push ( llvm:: CreateAttrStringValue ( cx. llcx , "function-instrument" , "xray-always" ) ) ;
265+ }
266+
242267 if options. ignore_loops {
243268 attrs. push ( llvm:: CreateAttrString ( cx. llcx , "xray-ignore-loops" ) ) ;
244269 }
@@ -442,7 +467,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
442467 // FIXME: none of these functions interact with source level attributes.
443468 to_add. extend ( frame_pointer_type_attr ( cx, sess) ) ;
444469 to_add. extend ( function_return_attr ( cx, sess) ) ;
445- to_add. extend ( instrument_function_attr ( cx, sess) ) ;
470+ to_add. extend ( instrument_function_attr ( cx, sess, codegen_fn_attrs . instrument_fn ) ) ;
446471 to_add. extend ( nojumptables_attr ( cx, sess) ) ;
447472 to_add. extend ( probestack_attr ( cx, tcx) ) ;
448473 to_add. extend ( stackprotector_attr ( cx, sess) ) ;
0 commit comments