rustc_middle/middle/
codegen_fn_attrs.rs

1use rustc_abi::Align;
2use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs;
3use rustc_attr_data_structures::{InlineAttr, InstructionSetAttr, OptimizeAttr};
4use rustc_macros::{HashStable, TyDecodable, TyEncodable};
5use rustc_span::Symbol;
6use rustc_target::spec::SanitizerSet;
7
8use crate::mir::mono::Linkage;
9
10#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
11pub struct CodegenFnAttrs {
12    pub flags: CodegenFnAttrFlags,
13    /// Parsed representation of the `#[inline]` attribute
14    pub inline: InlineAttr,
15    /// Parsed representation of the `#[optimize]` attribute
16    pub optimize: OptimizeAttr,
17    /// The `#[export_name = "..."]` attribute, indicating a custom symbol a
18    /// function should be exported under
19    pub export_name: Option<Symbol>,
20    /// The `#[link_name = "..."]` attribute, indicating a custom symbol an
21    /// imported function should be imported as. Note that `export_name`
22    /// probably isn't set when this is set, this is for foreign items while
23    /// `#[export_name]` is for Rust-defined functions.
24    pub link_name: Option<Symbol>,
25    /// The `#[link_ordinal = "..."]` attribute, indicating an ordinal an
26    /// imported function has in the dynamic library. Note that this must not
27    /// be set when `link_name` is set. This is for foreign items with the
28    /// "raw-dylib" kind.
29    pub link_ordinal: Option<u16>,
30    /// The `#[target_feature(enable = "...")]` attribute and the enabled
31    /// features (only enabled features are supported right now).
32    /// Implied target features have already been applied.
33    pub target_features: Vec<TargetFeature>,
34    /// Whether the function was declared safe, but has target features
35    pub safe_target_features: bool,
36    /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
37    pub linkage: Option<Linkage>,
38    /// The `#[linkage = "..."]` attribute on foreign items and the value we found.
39    pub import_linkage: Option<Linkage>,
40    /// The `#[link_section = "..."]` attribute, or what executable section this
41    /// should be placed in.
42    pub link_section: Option<Symbol>,
43    /// The `#[no_sanitize(...)]` attribute. Indicates sanitizers for which
44    /// instrumentation should be disabled inside the annotated function.
45    pub no_sanitize: SanitizerSet,
46    /// The `#[instruction_set(set)]` attribute. Indicates if the generated code should
47    /// be generated against a specific instruction set. Only usable on architectures which allow
48    /// switching between multiple instruction sets.
49    pub instruction_set: Option<InstructionSetAttr>,
50    /// The `#[repr(align(...))]` attribute. Indicates the value of which the function should be
51    /// aligned to.
52    pub alignment: Option<Align>,
53    /// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
54    /// the function entry.
55    pub patchable_function_entry: Option<PatchableFunctionEntry>,
56    /// For the `#[autodiff]` macros.
57    pub autodiff_item: Option<AutoDiffAttrs>,
58}
59
60#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
61pub struct TargetFeature {
62    /// The name of the target feature (e.g. "avx")
63    pub name: Symbol,
64    /// The feature is implied by another feature, rather than explicitly added by the
65    /// `#[target_feature]` attribute
66    pub implied: bool,
67}
68
69#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
70pub struct PatchableFunctionEntry {
71    /// Nops to prepend to the function
72    prefix: u8,
73    /// Nops after entry, but before body
74    entry: u8,
75}
76
77impl PatchableFunctionEntry {
78    pub fn from_config(config: rustc_session::config::PatchableFunctionEntry) -> Self {
79        Self { prefix: config.prefix(), entry: config.entry() }
80    }
81    pub fn from_prefix_and_entry(prefix: u8, entry: u8) -> Self {
82        Self { prefix, entry }
83    }
84    pub fn prefix(&self) -> u8 {
85        self.prefix
86    }
87    pub fn entry(&self) -> u8 {
88        self.entry
89    }
90}
91
92#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
93pub struct CodegenFnAttrFlags(u32);
94bitflags::bitflags! {
95    impl CodegenFnAttrFlags: u32 {
96        /// `#[cold]`: a hint to LLVM that this function, when called, is never on
97        /// the hot path.
98        const COLD                      = 1 << 0;
99        /// `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this
100        /// function is never null and the function has no side effects other than allocating.
101        const ALLOCATOR                 = 1 << 1;
102        /// An indicator that function will never unwind. Will become obsolete
103        /// once C-unwind is fully stabilized.
104        const NEVER_UNWIND              = 1 << 3;
105        /// `#[naked]`: an indicator to LLVM that no function prologue/epilogue
106        /// should be generated.
107        const NAKED                     = 1 << 4;
108        /// `#[no_mangle]`: an indicator that the function's name should be the same
109        /// as its symbol.
110        const NO_MANGLE                 = 1 << 5;
111        /// `#[rustc_std_internal_symbol]`: an indicator that this symbol is a
112        /// "weird symbol" for the standard library in that it has slightly
113        /// different linkage, visibility, and reachability rules.
114        const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6;
115        /// `#[thread_local]`: indicates a static is actually a thread local
116        /// piece of memory
117        const THREAD_LOCAL              = 1 << 8;
118        /// `#[used]`: indicates that LLVM can't eliminate this function (but the
119        /// linker can!).
120        const USED                      = 1 << 9;
121        /// `#[track_caller]`: allow access to the caller location
122        const TRACK_CALLER              = 1 << 10;
123        /// #[ffi_pure]: applies clang's `pure` attribute to a foreign function
124        /// declaration.
125        const FFI_PURE                  = 1 << 11;
126        /// #[ffi_const]: applies clang's `const` attribute to a foreign function
127        /// declaration.
128        const FFI_CONST                 = 1 << 12;
129        // (Bit 13 was used for `#[cmse_nonsecure_entry]`, but is now unused.)
130        // (Bit 14 was used for `#[coverage(off)]`, but is now unused.)
131        /// `#[used(linker)]`:
132        /// indicates that neither LLVM nor the linker will eliminate this function.
133        const USED_LINKER               = 1 << 15;
134        /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory.
135        const DEALLOCATOR               = 1 << 16;
136        /// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory.
137        const REALLOCATOR               = 1 << 17;
138        /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory.
139        const ALLOCATOR_ZEROED          = 1 << 18;
140        /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
141        const NO_BUILTINS               = 1 << 19;
142    }
143}
144rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
145
146impl CodegenFnAttrs {
147    pub const EMPTY: &'static Self = &Self::new();
148
149    pub const fn new() -> CodegenFnAttrs {
150        CodegenFnAttrs {
151            flags: CodegenFnAttrFlags::empty(),
152            inline: InlineAttr::None,
153            optimize: OptimizeAttr::Default,
154            export_name: None,
155            link_name: None,
156            link_ordinal: None,
157            target_features: vec![],
158            safe_target_features: false,
159            linkage: None,
160            import_linkage: None,
161            link_section: None,
162            no_sanitize: SanitizerSet::empty(),
163            instruction_set: None,
164            alignment: None,
165            patchable_function_entry: None,
166            autodiff_item: None,
167        }
168    }
169
170    /// Returns `true` if it looks like this symbol needs to be exported, for example:
171    ///
172    /// * `#[no_mangle]` is present
173    /// * `#[export_name(...)]` is present
174    /// * `#[linkage]` is present
175    ///
176    /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
177    pub fn contains_extern_indicator(&self) -> bool {
178        self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
179            || self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
180            || self.export_name.is_some()
181            || match self.linkage {
182                // These are private, so make sure we don't try to consider
183                // them external.
184                None | Some(Linkage::Internal) => false,
185                Some(_) => true,
186            }
187    }
188}