1 use crate::mir::mono::Linkage;
2 use rustc_attr::{InlineAttr, OptimizeAttr};
3 use rustc_span::symbol::Symbol;
5 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
6 pub struct CodegenFnAttrs {
7 pub flags: CodegenFnAttrFlags,
8 /// Parsed representation of the `#[inline]` attribute
9 pub inline: InlineAttr,
10 /// Parsed representation of the `#[optimize]` attribute
11 pub optimize: OptimizeAttr,
12 /// The `#[export_name = "..."]` attribute, indicating a custom symbol a
13 /// function should be exported under
14 pub export_name: Option<Symbol>,
15 /// The `#[link_name = "..."]` attribute, indicating a custom symbol an
16 /// imported function should be imported as. Note that `export_name`
17 /// probably isn't set when this is set, this is for foreign items while
18 /// `#[export_name]` is for Rust-defined functions.
19 pub link_name: Option<Symbol>,
20 /// The `#[link_ordinal = "..."]` attribute, indicating an ordinal an
21 /// imported function has in the dynamic library. Note that this must not
22 /// be set when `link_name` is set. This is for foreign items with the
24 pub link_ordinal: Option<usize>,
25 /// The `#[target_feature(enable = "...")]` attribute and the enabled
26 /// features (only enabled features are supported right now).
27 pub target_features: Vec<Symbol>,
28 /// The `#[linkage = "..."]` attribute and the value we found.
29 pub linkage: Option<Linkage>,
30 /// The `#[link_section = "..."]` attribute, or what executable section this
31 /// should be placed in.
32 pub link_section: Option<Symbol>,
36 #[derive(RustcEncodable, RustcDecodable, HashStable)]
37 pub struct CodegenFnAttrFlags: u32 {
38 /// `#[cold]`: a hint to LLVM that this function, when called, is never on
41 /// `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this
42 /// function is never null.
43 const ALLOCATOR = 1 << 1;
44 /// `#[unwind]`: an indicator that this function may unwind despite what
45 /// its ABI signature may otherwise imply.
46 const UNWIND = 1 << 2;
47 /// `#[rust_allocator_nounwind]`, an indicator that an imported FFI
48 /// function will never unwind. Probably obsolete by recent changes with
49 /// #[unwind], but hasn't been removed/migrated yet
50 const RUSTC_ALLOCATOR_NOUNWIND = 1 << 3;
51 /// `#[naked]`: an indicator to LLVM that no function prologue/epilogue
52 /// should be generated.
54 /// `#[no_mangle]`: an indicator that the function's name should be the same
56 const NO_MANGLE = 1 << 5;
57 /// `#[rustc_std_internal_symbol]`: an indicator that this symbol is a
58 /// "weird symbol" for the standard library in that it has slightly
59 /// different linkage, visibility, and reachability rules.
60 const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6;
61 /// `#[thread_local]`: indicates a static is actually a thread local
63 const THREAD_LOCAL = 1 << 8;
64 /// `#[used]`: indicates that LLVM can't eliminate this function (but the
67 /// `#[ffi_returns_twice]`, indicates that an extern function can return
69 const FFI_RETURNS_TWICE = 1 << 10;
70 /// `#[track_caller]`: allow access to the caller location
71 const TRACK_CALLER = 1 << 11;
72 /// `#[no_sanitize(address)]`: disables address sanitizer instrumentation
73 const NO_SANITIZE_ADDRESS = 1 << 12;
74 /// `#[no_sanitize(memory)]`: disables memory sanitizer instrumentation
75 const NO_SANITIZE_MEMORY = 1 << 13;
76 /// `#[no_sanitize(thread)]`: disables thread sanitizer instrumentation
77 const NO_SANITIZE_THREAD = 1 << 14;
78 /// All `#[no_sanitize(...)]` attributes.
79 const NO_SANITIZE_ANY = Self::NO_SANITIZE_ADDRESS.bits | Self::NO_SANITIZE_MEMORY.bits | Self::NO_SANITIZE_THREAD.bits;
84 pub fn new() -> CodegenFnAttrs {
86 flags: CodegenFnAttrFlags::empty(),
87 inline: InlineAttr::None,
88 optimize: OptimizeAttr::None,
92 target_features: vec![],
98 /// Returns `true` if `#[inline]` or `#[inline(always)]` is present.
99 pub fn requests_inline(&self) -> bool {
101 InlineAttr::Hint | InlineAttr::Always => true,
102 InlineAttr::None | InlineAttr::Never => false,
106 /// Returns `true` if it looks like this symbol needs to be exported, for example:
108 /// * `#[no_mangle]` is present
109 /// * `#[export_name(...)]` is present
110 /// * `#[linkage]` is present
111 pub fn contains_extern_indicator(&self) -> bool {
112 self.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
113 || self.export_name.is_some()
114 || match self.linkage {
115 // These are private, so make sure we don't try to consider
117 None | Some(Linkage::Internal) | Some(Linkage::Private) => false,