use crate::mir::mono::Linkage; use rustc_attr::{InlineAttr, OptimizeAttr}; use rustc_session::config::SanitizerSet; use rustc_span::symbol::Symbol; #[derive(Clone, TyEncodable, TyDecodable, HashStable)] pub struct CodegenFnAttrs { pub flags: CodegenFnAttrFlags, /// Parsed representation of the `#[inline]` attribute pub inline: InlineAttr, /// Parsed representation of the `#[optimize]` attribute pub optimize: OptimizeAttr, /// The `#[export_name = "..."]` attribute, indicating a custom symbol a /// function should be exported under pub export_name: Option, /// The `#[link_name = "..."]` attribute, indicating a custom symbol an /// imported function should be imported as. Note that `export_name` /// probably isn't set when this is set, this is for foreign items while /// `#[export_name]` is for Rust-defined functions. pub link_name: Option, /// The `#[link_ordinal = "..."]` attribute, indicating an ordinal an /// imported function has in the dynamic library. Note that this must not /// be set when `link_name` is set. This is for foreign items with the /// "raw-dylib" kind. pub link_ordinal: Option, /// The `#[target_feature(enable = "...")]` attribute and the enabled /// features (only enabled features are supported right now). pub target_features: Vec, /// The `#[linkage = "..."]` attribute and the value we found. pub linkage: Option, /// The `#[link_section = "..."]` attribute, or what executable section this /// should be placed in. pub link_section: Option, /// The `#[no_sanitize(...)]` attribute. Indicates sanitizers for which /// instrumentation should be disabled inside the annotated function. pub no_sanitize: SanitizerSet, } bitflags! { #[derive(TyEncodable, TyDecodable, HashStable)] pub struct CodegenFnAttrFlags: u32 { /// `#[cold]`: a hint to LLVM that this function, when called, is never on /// the hot path. const COLD = 1 << 0; /// `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this /// function is never null. const ALLOCATOR = 1 << 1; /// `#[unwind]`: an indicator that this function may unwind despite what /// its ABI signature may otherwise imply. const UNWIND = 1 << 2; /// `#[rust_allocator_nounwind]`, an indicator that an imported FFI /// function will never unwind. Probably obsolete by recent changes with /// #[unwind], but hasn't been removed/migrated yet const RUSTC_ALLOCATOR_NOUNWIND = 1 << 3; /// `#[naked]`: an indicator to LLVM that no function prologue/epilogue /// should be generated. const NAKED = 1 << 4; /// `#[no_mangle]`: an indicator that the function's name should be the same /// as its symbol. const NO_MANGLE = 1 << 5; /// `#[rustc_std_internal_symbol]`: an indicator that this symbol is a /// "weird symbol" for the standard library in that it has slightly /// different linkage, visibility, and reachability rules. const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6; /// `#[thread_local]`: indicates a static is actually a thread local /// piece of memory const THREAD_LOCAL = 1 << 8; /// `#[used]`: indicates that LLVM can't eliminate this function (but the /// linker can!). const USED = 1 << 9; /// `#[ffi_returns_twice]`, indicates that an extern function can return /// multiple times const FFI_RETURNS_TWICE = 1 << 10; /// `#[track_caller]`: allow access to the caller location const TRACK_CALLER = 1 << 11; /// #[ffi_pure]: applies clang's `pure` attribute to a foreign function /// declaration. const FFI_PURE = 1 << 12; /// #[ffi_const]: applies clang's `const` attribute to a foreign function /// declaration. const FFI_CONST = 1 << 13; } } impl CodegenFnAttrs { pub fn new() -> CodegenFnAttrs { CodegenFnAttrs { flags: CodegenFnAttrFlags::empty(), inline: InlineAttr::None, optimize: OptimizeAttr::None, export_name: None, link_name: None, link_ordinal: None, target_features: vec![], linkage: None, link_section: None, no_sanitize: SanitizerSet::empty(), } } /// Returns `true` if `#[inline]` or `#[inline(always)]` is present. pub fn requests_inline(&self) -> bool { match self.inline { InlineAttr::Hint | InlineAttr::Always => true, InlineAttr::None | InlineAttr::Never => false, } } /// Returns `true` if it looks like this symbol needs to be exported, for example: /// /// * `#[no_mangle]` is present /// * `#[export_name(...)]` is present /// * `#[linkage]` is present pub fn contains_extern_indicator(&self) -> bool { self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) || self.export_name.is_some() || match self.linkage { // These are private, so make sure we don't try to consider // them external. None | Some(Linkage::Internal | Linkage::Private) => false, Some(_) => true, } } }