Skip to main content

Function

Struct Function 

Source
pub struct Function {
Show 14 fields pub module: Arc<str>, pub name: Arc<str>, pub params: Vec<LayoutId>, pub reprs: Vec<Repr>, pub refs: RefMap, pub returns: LayoutId, pub captures: Vec<Capture>, pub code: Vec<Inst>, pub spans: Vec<Span>, pub locals: Vec<Local>, pub inlined: Vec<Inlined>, pub span: Span, pub is_async: bool, pub stub: bool,
}
Expand description

One lowered function.

Fields§

§module: Arc<str>

The module and name the source declared, for diagnostics and for Program::function_named.

§name: Arc<str>§params: Vec<LayoutId>

The layout of each parameter, in declaration order.

Parameters occupy the frame from slot 0 onward, each taking the words its layout says: a (Int, Point, Int) list occupies slots 0, 1–2 and 3. Declaration order, not a permutation into type groups — ADR 0034’s “a mixed list such as (Int, String, Int) is not permuted into type regions”. There are no type regions to permute into.

§reprs: Vec<Repr>

What each slot of the frame holds. reprs.len() is the frame size.

A slot’s Repr is fixed for the whole function; that is what makes Function::refs correct at every program counter. A slot may be reused by a later value of the same Repr, and a reference slot is cleared to null at its last use, so the static map costs no retention beyond a value’s live range.

§refs: RefMap

Which slots are references, derived from Function::reprs.

§returns: LayoutId

The layout of what the function answers.

Inst::Return names the base slot of the answer in the callee’s frame and the caller’s Inst::Call names the base slot of the destination location in its own; the machine copies this many words between them.

§captures: Vec<Capture>

The values the enclosing body handed this function, if it is a lambda. Empty for a declared function.

§code: Vec<Inst>§spans: Vec<Span>

The source span of each instruction, parallel to Function::code.

A parallel array rather than a field of Inst: a span is read when a run fails or a trace is written, and never in the dispatch loop, so it should not be in the cache line the loop is reading.

§locals: Vec<Local>

What the source called the values in the frame, and where each name meant which slot.

In declaration order, which is the order the shadowing rule reads them in; see Local. Not parallel to anything — a function binds as many names as it binds — and empty is a legal answer for a body that binds none.

§inlined: Vec<Inlined>

The bodies this function holds that were written somewhere else.

lower::inline expands a call to a small leaf where it is made, and the frame that call would have pushed then does not exist. Nothing downstream can tell: a run of instructions in the middle of this function is another function, and every reader that walks frames — an error’s chain, a backtrace, a profile — sees one frame where there were two.

So the expansion writes down what it removed. This is that record, and it is Local’s shape for Local’s reason: a slot number is not an answer to “what did the source call this”, and a program counter is not an answer to “whose instruction is this”.

In the order the expansions were made, which is program-counter order, and ranges nest rather than overlap. A reader takes the last range that contains the pc, which is the innermost body — the same rule Function::local_at follows, for the same reason.

§span: Span

Where the declaration itself is, for a diagnostic that is about the function rather than about one of its instructions.

§is_async: bool

Whether the body is a task’s: async fn, or the lambda a spawn was handed.

§stub: bool

Whether this is a stand-in the lowering left for a declaration it did not lower a body for. See lower::stub, and Function::is_stub.

Implementations§

Source§

impl Function

Source

pub fn frame_size(&self) -> u32

How many words a call to this function occupies on the stack.

Source

pub fn arity(&self) -> u32

How many parameters the function declares.

Source

pub fn param_slot(&self, at: usize, layouts: &[Layout]) -> Slot

The first slot of parameter at, which is the widths of the ones before it.

Source

pub fn param_words(&self, layouts: &[Layout]) -> u32

How many slots the parameters occupy in total.

Source

pub fn repr(&self, slot: Slot) -> Option<Repr>

What slot slot holds.

Source

pub fn span_at(&self, pc: usize) -> Span

The span of the instruction at pc, or the declaration’s own.

Source

pub fn local_at(&self, name: &str, pc: Pc) -> Option<&Local>

Which slot name denotes at pc, if the source bound it there.

The last match wins, because a shadowing declaration is recorded beside the one it shadows rather than in place of it: see Local.

Source

pub fn inlined_at(&self, pc: Pc) -> impl Iterator<Item = &Inlined> + '_

The expanded bodies pc is inside, innermost last.

A reader that wants one frame’s worth of context wants the last of them; a reader rebuilding a chain wants all of them, innermost first, which is this reversed. Ranges nest, so “contains the pc” and “in the order they were made” is enough to order them: an inner expansion is always written after the outer one it sits in.

Source

pub fn qualified(&self) -> String

module.name, as a diagnostic writes it.

Source

pub fn is_stub(&self) -> bool

Whether this is a stand-in rather than a lowered body.

A stub has no body to stop at: its one instruction is a Return written at the declaration’s own span, and it has no parameters and no names, because there was no boundary and no scope to bind them from. A tool that resolves a source location or a breakpoint against a program — a debugger walking Function::locals, a stack trace reading Function::span_at — has to skip a stub rather than answer out of it, or it answers a question about a function that was never written.

It answers true for all three kinds lower::stub’s doc comment describes, because stub is the one place any of them is built and this reads back exactly what it recorded. But a program that actually runs — the output of lower_roots or lower_entry once a lowering finishes without error — can only hold two of the three: the declaration a slice left out, and a generic declaration whose instantiations carry the real code beside it. The third kind, a declaration this lowering reported a gap about, belongs to a lowering that never got handed back — a gap is an error, so the program it would have been part of does not exist for a caller of this method to ask about.

This is a stored fact rather than a test of the four fields above, because a shape a stub happens to have is not a shape only a stub has. lower::stub’s own construction is the only place that knows why the instruction, span, and empty lists are what they are; asking a shape test to recover that intent at a distance means the day a real body of one instruction is ever written at its declaration’s own span, the test is wrong and nothing says so. Recording the fact the lowering already has costs one field; re-deriving it costs a convention two crates now have to keep in sync by hand.

Trait Implementations§

Source§

impl Clone for Function

Source§

fn clone(&self) -> Function

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Function

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.