]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
Auto merge of #97176 - kraktus:cmd_debug, r=the8472
[rust.git] / compiler / rustc_middle / src / middle / codegen_fn_attrs.rs
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)]`: indicates that LLVM nor the linker can eliminate this function.
95         const USED_LINKER               = 1 << 16;
96         /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory.
97         const DEALLOCATOR               = 1 << 17;
98         /// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory.
99         const REALLOCATOR               = 1 << 18;
100         /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory.
101         const ALLOCATOR_ZEROED          = 1 << 19;
102     }
103 }
104
105 impl CodegenFnAttrs {
106     pub const EMPTY: &'static Self = &Self::new();
107
108     pub const fn new() -> CodegenFnAttrs {
109         CodegenFnAttrs {
110             flags: CodegenFnAttrFlags::empty(),
111             inline: InlineAttr::None,
112             optimize: OptimizeAttr::None,
113             export_name: None,
114             link_name: None,
115             link_ordinal: None,
116             target_features: vec![],
117             linkage: None,
118             import_linkage: None,
119             link_section: None,
120             no_sanitize: SanitizerSet::empty(),
121             instruction_set: None,
122             alignment: None,
123         }
124     }
125
126     /// Returns `true` if `#[inline]` or `#[inline(always)]` is present.
127     pub fn requests_inline(&self) -> bool {
128         match self.inline {
129             InlineAttr::Hint | InlineAttr::Always => true,
130             InlineAttr::None | InlineAttr::Never => false,
131         }
132     }
133
134     /// Returns `true` if it looks like this symbol needs to be exported, for example:
135     ///
136     /// * `#[no_mangle]` is present
137     /// * `#[export_name(...)]` is present
138     /// * `#[linkage]` is present
139     pub fn contains_extern_indicator(&self) -> bool {
140         self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
141             || self.export_name.is_some()
142             || match self.linkage {
143                 // These are private, so make sure we don't try to consider
144                 // them external.
145                 None | Some(Linkage::Internal | Linkage::Private) => false,
146                 Some(_) => true,
147             }
148     }
149 }