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 `#[align(...)]` attribute. Determines the alignment of the function body.
51 pub alignment: Option<Align>,
52 /// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around
53 /// the function entry.
54 pub patchable_function_entry: Option<PatchableFunctionEntry>,
55 /// For the `#[autodiff]` macros.
56 pub autodiff_item: Option<AutoDiffAttrs>,
57}
58
59#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
60pub struct TargetFeature {
61 /// The name of the target feature (e.g. "avx")
62 pub name: Symbol,
63 /// The feature is implied by another feature, rather than explicitly added by the
64 /// `#[target_feature]` attribute
65 pub implied: bool,
66}
67
68#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
69pub struct PatchableFunctionEntry {
70 /// Nops to prepend to the function
71 prefix: u8,
72 /// Nops after entry, but before body
73 entry: u8,
74}
75
76impl PatchableFunctionEntry {
77 pub fn from_config(config: rustc_session::config::PatchableFunctionEntry) -> Self {
78 Self { prefix: config.prefix(), entry: config.entry() }
79 }
80 pub fn from_prefix_and_entry(prefix: u8, entry: u8) -> Self {
81 Self { prefix, entry }
82 }
83 pub fn prefix(&self) -> u8 {
84 self.prefix
85 }
86 pub fn entry(&self) -> u8 {
87 self.entry
88 }
89}
90
91#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
92pub struct CodegenFnAttrFlags(u32);
93bitflags::bitflags! {
94 impl CodegenFnAttrFlags: u32 {
95 /// `#[cold]`: a hint to LLVM that this function, when called, is never on
96 /// the hot path.
97 const COLD = 1 << 0;
98 /// `#[rustc_nounwind]`: An indicator that function will never unwind.
99 const NEVER_UNWIND = 1 << 1;
100 /// `#[naked]`: an indicator to LLVM that no function prologue/epilogue
101 /// should be generated.
102 const NAKED = 1 << 2;
103 /// `#[no_mangle]`: an indicator that the function's name should be the same
104 /// as its symbol.
105 const NO_MANGLE = 1 << 3;
106 /// `#[rustc_std_internal_symbol]`: an indicator that this symbol is a
107 /// "weird symbol" for the standard library in that it has slightly
108 /// different linkage, visibility, and reachability rules.
109 const RUSTC_STD_INTERNAL_SYMBOL = 1 << 4;
110 /// `#[thread_local]`: indicates a static is actually a thread local
111 /// piece of memory
112 const THREAD_LOCAL = 1 << 5;
113 /// `#[used(compiler)]`: indicates that LLVM can't eliminate this function (but the
114 /// linker can!).
115 const USED_COMPILER = 1 << 6;
116 /// `#[used(linker)]`:
117 /// indicates that neither LLVM nor the linker will eliminate this function.
118 const USED_LINKER = 1 << 7;
119 /// `#[track_caller]`: allow access to the caller location
120 const TRACK_CALLER = 1 << 8;
121 /// #[ffi_pure]: applies clang's `pure` attribute to a foreign function
122 /// declaration.
123 const FFI_PURE = 1 << 9;
124 /// #[ffi_const]: applies clang's `const` attribute to a foreign function
125 /// declaration.
126 const FFI_CONST = 1 << 10;
127 /// `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this
128 /// function is never null and the function has no side effects other than allocating.
129 const ALLOCATOR = 1 << 11;
130 /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory.
131 const DEALLOCATOR = 1 << 12;
132 /// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory.
133 const REALLOCATOR = 1 << 13;
134 /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory.
135 const ALLOCATOR_ZEROED = 1 << 14;
136 /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
137 const NO_BUILTINS = 1 << 15;
138 }
139}
140rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
141
142impl CodegenFnAttrs {
143 pub const EMPTY: &'static Self = &Self::new();
144
145 pub const fn new() -> CodegenFnAttrs {
146 CodegenFnAttrs {
147 flags: CodegenFnAttrFlags::empty(),
148 inline: InlineAttr::None,
149 optimize: OptimizeAttr::Default,
150 export_name: None,
151 link_name: None,
152 link_ordinal: None,
153 target_features: vec![],
154 safe_target_features: false,
155 linkage: None,
156 import_linkage: None,
157 link_section: None,
158 no_sanitize: SanitizerSet::empty(),
159 instruction_set: None,
160 alignment: None,
161 patchable_function_entry: None,
162 autodiff_item: None,
163 }
164 }
165
166 /// Returns `true` if it looks like this symbol needs to be exported, for example:
167 ///
168 /// * `#[no_mangle]` is present
169 /// * `#[export_name(...)]` is present
170 /// * `#[linkage]` is present
171 ///
172 /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
173 pub fn contains_extern_indicator(&self) -> bool {
174 self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
175 || self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
176 || self.export_name.is_some()
177 || match self.linkage {
178 // These are private, so make sure we don't try to consider
179 // them external.
180 None | Some(Linkage::Internal) => false,
181 Some(_) => true,
182 }
183 }
184}