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;
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
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
45 pub alignment: Option<u32>,
49 #[derive(TyEncodable, TyDecodable, HashStable)]
50 pub struct CodegenFnAttrFlags: u32 {
51 /// `#[cold]`: a hint to LLVM that this function, when called, is never on
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.
63 /// `#[no_mangle]`: an indicator that the function's name should be the same
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
72 const THREAD_LOCAL = 1 << 8;
73 /// `#[used]`: indicates that LLVM can't eliminate this function (but the
76 /// `#[ffi_returns_twice]`, indicates that an extern function can return
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
83 const FFI_PURE = 1 << 12;
84 /// #[ffi_const]: applies clang's `const` attribute to a foreign function
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
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;
105 impl CodegenFnAttrs {
106 pub const EMPTY: &'static Self = &Self::new();
108 pub const fn new() -> CodegenFnAttrs {
110 flags: CodegenFnAttrFlags::empty(),
111 inline: InlineAttr::None,
112 optimize: OptimizeAttr::None,
116 target_features: vec![],
118 import_linkage: None,
120 no_sanitize: SanitizerSet::empty(),
121 instruction_set: None,
126 /// Returns `true` if `#[inline]` or `#[inline(always)]` is present.
127 pub fn requests_inline(&self) -> bool {
129 InlineAttr::Hint | InlineAttr::Always => true,
130 InlineAttr::None | InlineAttr::Never => false,
134 /// Returns `true` if it looks like this symbol needs to be exported, for example:
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
145 None | Some(Linkage::Internal | Linkage::Private) => false,