pub struct Func {
pub name: Symbol,
pub linkage: Linkage,
pub visibility: Visibility,
pub section: Option<Symbol>,
pub attrs: Attrs,
/* private fields */
}Expand description
One function.
Fields§
§name: SymbolThe name it is called by, which is what a direct call to it names.
linkage: LinkageHow the linker sees it. Internal for a static function.
visibility: VisibilityHow the dynamic linker sees it.
section: Option<Symbol>The section to put it in, from __attribute__((section(...))), or None to let the
object writer choose.
attrs: AttrsWhat is true of the whole function, which is what a caller reads when it wants to know what a call to it does without looking inside.
Implementations§
Source§impl Func
impl Func
Sourcepub fn new(name: Symbol, signature: Signature) -> Self
pub fn new(name: Symbol, signature: Signature) -> Self
A function with that name and that signature, and nothing in it.
The signature becomes signature zero, which is what Func::signature gives back. The
entry block is not created here, because the caller is about to create it and give it
the parameters, and a half-built entry block is worse than no entry block. So a
function fresh from here is a declaration, and stops being one when it gets a block.
Sourcepub fn add_signature(&mut self, signature: Signature) -> Sig
pub fn add_signature(&mut self, signature: Signature) -> Sig
Records a signature a call_indirect is made with, and gives back its index.
Sourcepub fn entry(&self) -> Option<Block>
pub fn entry(&self) -> Option<Block>
The entry block, which is the first one in layout order.
None only before one has been created. The verifier is what insists a finished
function has one.
Sourcepub fn is_declaration(&self) -> bool
pub fn is_declaration(&self) -> bool
Whether this only says the function exists somewhere, which is a function with no blocks in it.
extern int puts(const char *); and every other declaration of something defined in
another object is one of these, and it is here rather than left out of the module
because a call needs its signature and its linkage.
Sourcepub fn create_block(&mut self) -> Block
pub fn create_block(&mut self) -> Block
Creates a block with no parameters and no instructions, at the end of the layout.
Sourcepub fn remove_block(&mut self, block: Block)
pub fn remove_block(&mut self, block: Block)
Takes a block out of the layout, along with everything in it.
The block keeps its number, the way a removed instruction keeps its own, because renumbering would move every block after it and invalidate every index anybody was holding. What it stops being is a block of this function: nothing walks it, nothing prints it, and the values defined in it are as gone as the instructions that defined them. Deleting one whose branches something still reaches is how a function ends up branching to nowhere, so the caller is the one that has to know nothing reaches it.
§Panics
Panics if the block is the entry block, which is the one block a function has to have.
Sourcepub fn append_param(&mut self, block: Block, ty: Type) -> Value
pub fn append_param(&mut self, block: Block, ty: Type) -> Value
Adds a parameter of that type to a block, and gives back the value it arrives as.
Every predecessor’s branch has to grow an argument to match, which is
Func::append_arg, and the verifier is what notices if one of them did not.
§Panics
Panics if the block already has four billion parameters, which no block does.
Sourcepub fn retain_params(&mut self, block: Block, keep: impl FnMut(Value) -> bool)
pub fn retain_params(&mut self, block: Block, keep: impl FnMut(Value) -> bool)
Drops the parameters of a block that a predicate turns down, and renumbers the rest.
The predicate is asked about each parameter in the order the block takes them. A parameter that goes has to take the argument in the same position out of every branch to the block, which is the caller’s work rather than this method’s, because only the caller knows which branches there are. This is what removing a redundant block parameter is, and SSA construction is the thing that makes them.
§Panics
Panics if the block has four billion parameters, which no block does.
Sourcepub fn insts(&self, block: Block) -> impl Iterator<Item = Inst> + use<'_>
pub fn insts(&self, block: Block) -> impl Iterator<Item = Inst> + use<'_>
Every instruction in a block, in order.
Sourcepub fn terminator(&self, block: Block) -> Option<Inst>
pub fn terminator(&self, block: Block) -> Option<Inst>
The last instruction of a block, which is its terminator once it is finished.
Sourcepub fn is_terminator(&self, inst: Inst) -> bool
pub fn is_terminator(&self, inst: Inst) -> bool
Whether control leaves the block at this instruction.
A question for the function rather than for the instruction, because inline assembly is
the one case where the opcode is not enough: asm goto has labels and everything else
does not, and the labels are in the function’s table rather than on the instruction.
Sourcepub fn create_inst(
&mut self,
data: InstData,
results: &[Type],
span: Span,
) -> Inst
pub fn create_inst( &mut self, data: InstData, results: &[Type], span: Span, ) -> Inst
Creates an instruction and its result values, without putting it in a block.
The results are allocated here and are contiguous, which is what lets an instruction hold the first of them and a count rather than a list.
§Panics
Panics if results has more than 255 types, which no instruction in the set does.
Sourcepub fn append_inst(&mut self, block: Block, inst: Inst)
pub fn append_inst(&mut self, block: Block, inst: Inst)
Puts an instruction at the end of a block.
§Panics
Panics if the instruction is already in a block. Moving one is removing it and appending it, and doing it by accident is how a linked list ends up in two pieces.
Sourcepub fn insert_before(&mut self, inst: Inst, before: Inst)
pub fn insert_before(&mut self, inst: Inst, before: Inst)
Puts an instruction immediately before another one, in the block that one is in.
§Panics
Panics if inst is already in a block, or if before is not in one.
Sourcepub fn remove_inst(&mut self, inst: Inst)
pub fn remove_inst(&mut self, inst: Inst)
Takes an instruction out of its block, leaving it and its results in the tables.
The instruction is not deleted, because deleting it would move every instruction after it. A removed instruction is unreachable from any block and is dropped when the whole function is.
§Panics
Panics if the instruction is not in a block.
Sourcepub fn block_of(&self, inst: Inst) -> Option<Block>
pub fn block_of(&self, inst: Inst) -> Option<Block>
The block an instruction is in, or None if it has been removed from one.
Sourcepub fn successors(
&self,
inst: Inst,
) -> impl Iterator<Item = BlockCall> + use<'_>
pub fn successors( &self, inst: Inst, ) -> impl Iterator<Item = BlockCall> + use<'_>
Where an instruction branches to, which is empty when it does not branch.
This is the one place that knows a switch keeps its targets in a side table and
asm goto in another one, so nothing walking the CFG has to.
Sourcepub fn target_list(&self, inst: Inst) -> BlockCallList
pub fn target_list(&self, inst: Inst) -> BlockCallList
Where a terminator keeps its targets, for something that edits them rather than reads them.
Func::successors is what walking the CFG wants. This is what recording an edge
wants, because an edge that will grow an argument later has to be named by its place in
the table rather than by the block it went to.
Sourcepub fn push_values(&mut self, values: &[Value]) -> ValueList
pub fn push_values(&mut self, values: &[Value]) -> ValueList
Records a run of value operands.
Sourcepub fn append_arg(&mut self, list: ValueList, value: Value) -> ValueList
pub fn append_arg(&mut self, list: ValueList, value: Value) -> ValueList
Adds one value to the end of a run, giving back the run it became.
The run grows in place when nothing has been put after it, which is the case while a list is being built. Otherwise it is copied to the end and the old space is left behind, which is what makes adding a parameter to a loop header possible at all. That happens once per value carried around a loop, so the copying is not what costs.
Sourcepub fn rewrite(&mut self, list: ValueList, with: impl FnMut(Value) -> Value)
pub fn rewrite(&mut self, list: ValueList, with: impl FnMut(Value) -> Value)
Replaces the values in a run, which is what substituting one definition for another is.
A run is a run whether it is an instruction’s operands or a branch’s arguments, so this is the whole of the rewriting a substitution has to do.
Sourcepub fn push_block_calls(&mut self, calls: &[BlockCall]) -> BlockCallList
pub fn push_block_calls(&mut self, calls: &[BlockCall]) -> BlockCallList
Records a run of branch targets.
Sourcepub fn set_block_call(&mut self, at: Idx<BlockCall>, call: BlockCall)
pub fn set_block_call(&mut self, at: Idx<BlockCall>, call: BlockCall)
Replaces one branch target, which is what redirecting an edge is.
Sourcepub fn add_call(&mut self, info: CallInfo) -> Idx<CallInfo>
pub fn add_call(&mut self, info: CallInfo) -> Idx<CallInfo>
Records a call’s callee and signature.
Sourcepub fn add_switch(&mut self, info: SwitchInfo) -> Idx<SwitchInfo>
pub fn add_switch(&mut self, info: SwitchInfo) -> Idx<SwitchInfo>
Records a switch’s targets and case values.
Trait Implementations§
Source§impl Index<Idx<SwitchInfo>> for Func
impl Index<Idx<SwitchInfo>> for Func
Source§type Output = SwitchInfo
type Output = SwitchInfo
Source§fn index(&self, at: Idx<SwitchInfo>) -> &SwitchInfo
fn index(&self, at: Idx<SwitchInfo>) -> &SwitchInfo
container[index]) operation. Read more