pub struct Function {Show 23 fields
pub name: String,
pub sig: Signature,
pub params: Vec<ObjectId>,
pub param_names: Vec<Option<String>>,
pub is_static: bool,
pub is_inline: bool,
pub noreturn: bool,
pub inline_hint: Option<InlineHint>,
pub cold: bool,
pub deprecated: Option<Option<String>>,
pub section: Option<String>,
pub asm_label: Option<String>,
pub init_kind: Option<InitKind>,
pub target_features: Vec<String>,
pub address_taken: bool,
pub intrinsic: Option<&'static Intrinsic>,
pub safe: Option<SourceRange>,
pub uses_arena: bool,
pub locals: Vec<ObjectId>,
pub body: Option<Body>,
pub item_name: Option<String>,
pub env: Vec<EnvParam>,
pub range: SourceRange,
}Expand description
A function declared or defined in the translation unit.
Fields§
§name: StringThe name as written in C.
sig: SignatureThe signature every declaration of it must agree on.
params: Vec<ObjectId>The parameter objects. Empty until the definition is seen.
param_names: Vec<Option<String>>The parameter names as first declared, for the generated extern block.
is_static: boolWhether the function was declared static, i.e. is private to the unit.
is_inline: boolWhether the function was declared inline.
noreturn: boolWhether the function was declared _Noreturn (or [[noreturn]]), so
that a call to it ends the statement it is in.
inline_hint: Option<InlineHint>What always_inline / noinline asked for.
cold: boolWhether __attribute__((cold)) marked it unlikely.
deprecated: Option<Option<String>>The message __attribute__((deprecated)) gave, if it was there at all.
section: Option<String>The section __attribute__((section("…"))) asked for.
asm_label: Option<String>The symbol __asm__("name") renamed the function to.
init_kind: Option<InitKind>Whether __attribute__((constructor)) asked for it to run before
main, or destructor for after it.
target_features: Vec<String>The instruction sets __attribute__((target("…"))) or
#pragma GCC target("…") asked for, in Rust’s spelling, which the
generated item carries as #[target_feature(enable = "…")].
Only a definition can carry them: an extern declaration has no item
for the attribute to go on, and the function it names was compiled
somewhere else.
address_taken: boolWhether anything in the unit uses the function other than by calling
it by name: its address taken as a value (&f, or f where a pointer
is wanted), or it named by __attribute__((cleanup)), whose guard
holds a pointer to it. Such a function has to be an extern "C" fn,
since that is what a C function pointer is; one that is only ever called
can be a Rust function, which is what an
always-inline helper with target features
needs.
intrinsic: Option<&'static Intrinsic>Set when this name is an x86 intrinsic rather than a
symbol: a call to it is generated as ::core::arch::x86_64::<name>,
and it is left out of the unit’s extern block because there is
nothing to link.
safe: Option<SourceRange>Where the function was asked to be safe, if
it was: [[cinrs::safe]], __attribute__((cinrs_safe)) or
#pragma cinrs safe.
A safe function is generated as extern "C" fn rather than
unsafe extern "C" fn, and its body is not wrapped in an unsafe
block, so rustc checks it. The range is where the request was
written, which is what the diagnostics about it point at.
uses_arena: boolWhether the body declares a variable length array or calls alloca,
in which case the generated item opens with the bump arena both
emulations allocate out of.
The arena is per function and is dropped by the return, which frees
everything in it: that is alloca’s lifetime, and a variable length
array gives its space back earlier, at the end of its block, by moving
the arena’s position back down. See codegen.
locals: Vec<ObjectId>Every automatic object the body declared, in declaration order.
Code generation needs the whole list — not only the ones a let
statement is visible for — because a local declared inside a statement
expression is a binding too and may need renaming apart.
body: Option<Body>The body, present once a definition has been type checked.
item_name: Option<String>The Rust item name, when it is not the C name.
Only a lifted GNU nested function has one: it becomes a
file-scope item, so it needs a name that cannot collide with the C
function of the same name at file scope, while Function::name stays
what the program called it — which is what diagnostics and __func__
say.
env: Vec<EnvParam>The hidden environment parameters a lifted GNU nested function takes in front of its declared ones, in the order they are passed.
Empty for every ordinary function, and for a nested one that captures nothing — which is why such a nested function’s address may still be taken: the generated item has exactly the signature C gave it.
range: SourceRangeWhere the function’s name was written, at its definition if there is one and at its first declaration otherwise.
Implementations§
Source§impl Function
impl Function
Sourcepub fn is_extern(&self) -> bool
pub fn is_extern(&self) -> bool
Whether this function is only declared here and linked from elsewhere.
Sourcepub fn is_safe(&self) -> bool
pub fn is_safe(&self) -> bool
Whether the function is generated without unsafe; see
Function::safe.
Sourcepub fn inline_helper(&self) -> bool
pub fn inline_helper(&self) -> bool
Whether the function is an always_inline helper under a target
feature that is generated as a Rust #[inline(always)] unsafe fn
without #[target_feature].
rustc refuses #[inline(always)] together with #[target_feature]
(rust-lang/rust#145574), and #[inline] alone is a hint LLVM may
decline: BLAKE3’s round_fn16, called seven times from one kernel, was
left out of line, its state spilled to the stack around every call.
GCC’s contract makes the attribute unnecessary: it refuses to inline an
always_inline function into a caller without its target options, so
every caller of one that compiles has the features, and once the helper
is inlined into such a caller the intrinsics in its body are inlined
there too. Without the attribute the helper must not be a C-ABI
function — the C ABI passes a 256- or 512-bit vector in registers the
feature provides — so it is a Rust function, and that is only possible
when nothing needs it as a C function pointer: it is static, never
has its address taken, is not variadic, nested, safe (whose body would
then call intrinsics without unsafe), a constructor or an intrinsic.