1 use crate::mir::mono::Linkage; 2 use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; 3 use rustc_span::symbol::Symbol; 4 use rustc_target::spec::SanitizerSet; 5 6 #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)] 7 pub struct CodegenFnAttrs { 8 pub flags: CodegenFnAttrFlags, 9 /// Parsed representation of the `#[inline]` attribute 10 pub inline: InlineAttr, 11 /// Parsed representation of the `#[optimize]` attribute 12 pub optimize: OptimizeAttr, 13 /// The `#[export_name = "..."]` attribute, indicating a custom symbol a 14 /// function should be exported under 15 pub export_name: Option<Symbol>, 16 /// The `#[link_name = "..."]` attribute, indicating a custom symbol an 17 /// imported function should be imported as. Note that `export_name` 18 /// probably isn't set when this is set, this is for foreign items while 19 /// `#[export_name]` is for Rust-defined functions. 20 pub link_name: Option<Symbol>, 21 /// The `#[link_ordinal = "..."]` attribute, indicating an ordinal an 22 /// imported function has in the dynamic library. Note that this must not 23 /// be set when `link_name` is set. This is for foreign items with the 24 /// "raw-dylib" kind. 25 pub link_ordinal: Option<u16>, 26 /// The `#[target_feature(enable = "...")]` attribute and the enabled 27 /// features (only enabled features are supported right now). 28 pub target_features: Vec<Symbol>, 29 /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. 30 pub linkage: Option<Linkage>, 31 /// The `#[linkage = "..."]` attribute on foreign items and the value we found. 32 pub import_linkage: Option<Linkage>, 33 /// The `#[link_section = "..."]` attribute, or what executable section this 34 /// should be placed in. 35 pub link_section: Option<Symbol>, 36 /// The `#[no_sanitize(...)]` attribute. Indicates sanitizers for which 37 /// instrumentation should be disabled inside the annotated function. 38 pub no_sanitize: SanitizerSet, 39 /// The `#[instruction_set(set)]` attribute. Indicates if the generated code should 40 /// be generated against a specific instruction set. Only usable on architectures which allow 41 /// switching between multiple instruction sets. 42 pub instruction_set: Option<InstructionSetAttr>, 43 /// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be 44 /// aligned to. 45 pub alignment: Option<u32>, 46 } 47 48 bitflags! { 49 #[derive(TyEncodable, TyDecodable, HashStable)] 50 pub struct CodegenFnAttrFlags: u32 { 51 /// `#[cold]`: a hint to LLVM that this function, when called, is never on 52 /// the hot path. 53 const COLD = 1 << 0; 54 /// `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this 55 /// function is never null and the function has no side effects other than allocating. 56 const ALLOCATOR = 1 << 1; 57 /// An indicator that function will never unwind. Will become obsolete 58 /// once C-unwind is fully stabilized. 59 const NEVER_UNWIND = 1 << 3; 60 /// `#[naked]`: an indicator to LLVM that no function prologue/epilogue 61 /// should be generated. 62 const NAKED = 1 << 4; 63 /// `#[no_mangle]`: an indicator that the function's name should be the same 64 /// as its symbol. 65 const NO_MANGLE = 1 << 5; 66 /// `#[rustc_std_internal_symbol]`: an indicator that this symbol is a 67 /// "weird symbol" for the standard library in that it has slightly 68 /// different linkage, visibility, and reachability rules. 69 const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6; 70 /// `#[thread_local]`: indicates a static is actually a thread local 71 /// piece of memory 72 const THREAD_LOCAL = 1 << 8; 73 /// `#[used]`: indicates that LLVM can't eliminate this function (but the 74 /// linker can!). 75 const USED = 1 << 9; 76 /// `#[ffi_returns_twice]`, indicates that an extern function can return 77 /// multiple times 78 const FFI_RETURNS_TWICE = 1 << 10; 79 /// `#[track_caller]`: allow access to the caller location 80 const TRACK_CALLER = 1 << 11; 81 /// #[ffi_pure]: applies clang's `pure` attribute to a foreign function 82 /// declaration. 83 const FFI_PURE = 1 << 12; 84 /// #[ffi_const]: applies clang's `const` attribute to a foreign function 85 /// declaration. 86 const FFI_CONST = 1 << 13; 87 /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a 88 /// function as an entry function from Non-Secure code. 89 const CMSE_NONSECURE_ENTRY = 1 << 14; 90 /// `#[no_coverage]`: indicates that the function should be ignored by 91 /// the MIR `InstrumentCoverage` pass and not added to the coverage map 92 /// during codegen. 93 const NO_COVERAGE = 1 << 15; 94 /// `#[used(linker)]`: 95 /// indicates that neither LLVM nor the linker will eliminate this function. 96 const USED_LINKER = 1 << 16; 97 /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory. 98 const DEALLOCATOR = 1 << 17; 99 /// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory. 100 const REALLOCATOR = 1 << 18; 101 /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory. 102 const ALLOCATOR_ZEROED = 1 << 19; 103 } 104 } 105 106 impl CodegenFnAttrs { 107 pub const EMPTY: &'static Self = &Self::new(); 108 new() -> CodegenFnAttrs109 pub const fn new() -> CodegenFnAttrs { 110 CodegenFnAttrs { 111 flags: CodegenFnAttrFlags::empty(), 112 inline: InlineAttr::None, 113 optimize: OptimizeAttr::None, 114 export_name: None, 115 link_name: None, 116 link_ordinal: None, 117 target_features: vec![], 118 linkage: None, 119 import_linkage: None, 120 link_section: None, 121 no_sanitize: SanitizerSet::empty(), 122 instruction_set: None, 123 alignment: None, 124 } 125 } 126 127 /// Returns `true` if `#[inline]` or `#[inline(always)]` is present. requests_inline(&self) -> bool128 pub fn requests_inline(&self) -> bool { 129 match self.inline { 130 InlineAttr::Hint | InlineAttr::Always => true, 131 InlineAttr::None | InlineAttr::Never => false, 132 } 133 } 134 135 /// Returns `true` if it looks like this symbol needs to be exported, for example: 136 /// 137 /// * `#[no_mangle]` is present 138 /// * `#[export_name(...)]` is present 139 /// * `#[linkage]` is present contains_extern_indicator(&self) -> bool140 pub fn contains_extern_indicator(&self) -> bool { 141 self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) 142 || self.export_name.is_some() 143 || match self.linkage { 144 // These are private, so make sure we don't try to consider 145 // them external. 146 None | Some(Linkage::Internal | Linkage::Private) => false, 147 Some(_) => true, 148 } 149 } 150 } 151