pub trait Function {
Show 21 methods fn num_insts(&self) -> usize;
fn num_blocks(&self) -> usize;
fn entry_block(&self) -> Block;
fn block_insns(&self, block: Block) -> InstRange;
fn block_succs(&self, block: Block) -> &[Block];
fn block_preds(&self, block: Block) -> &[Block];
fn block_params(&self, block: Block) -> &[VReg];
fn is_ret(&self, insn: Inst) -> bool;
fn is_branch(&self, insn: Inst) -> bool;
fn branch_blockparams(
        &self,
        block: Block,
        insn: Inst,
        succ_idx: usize
    ) -> &[VReg];
fn is_move(&self, insn: Inst) -> Option<(Operand, Operand)>;
fn inst_operands(&self, insn: Inst) -> &[Operand];
fn inst_clobbers(&self, insn: Inst) -> PRegSet;
fn num_vregs(&self) -> usize;
fn spillslot_size(&self, regclass: RegClass) -> usize; fn requires_refs_on_stack(&self, _: Inst) -> bool { ... }
fn reftype_vregs(&self) -> &[VReg] { ... }
fn debug_value_labels(&self) -> &[(VReg, Inst, Inst, u32)] { ... }
fn is_pinned_vreg(&self, _: VReg) -> Option<PReg> { ... }
fn multi_spillslot_named_by_last_slot(&self) -> bool { ... }
fn allow_multiple_vreg_defs(&self) -> bool { ... }
}
Expand description

A trait defined by the regalloc client to provide access to its machine-instruction / CFG representation.

(This trait’s design is inspired by, and derives heavily from, the trait of the same name in regalloc.rs.)

Required methods

How many instructions are there?

How many blocks are there?

Get the index of the entry block.

Provide the range of instruction indices contained in each block.

Get CFG successors for a given block.

Get the CFG predecessors for a given block.

Get the block parameters for a given block.

Determine whether an instruction is a return instruction.

Determine whether an instruction is the end-of-block branch.

If insn is a branch at the end of block, returns the outgoing blockparam arguments for the given successor. The number of arguments must match the number incoming blockparams for each respective successor block.

Determine whether an instruction is a move; if so, return the Operands for (src, dst).

Get the Operands for an instruction.

Get the clobbers for an instruction; these are the registers that, after the instruction has executed, hold values that are arbitrary, separately from the usual outputs to the instruction. It is invalid to read a register that has been clobbered; the register allocator is free to assume that clobbered registers are filled with garbage and available for reuse. It will avoid storing any value in a clobbered register that must be live across the instruction.

Another way of seeing this is that a clobber is equivalent to an “early def” of a fresh vreg that is not used anywhere else in the program, with a fixed-register constraint that places it in a given PReg chosen by the client prior to regalloc.

Every register written by an instruction must either correspond to (be assigned to) an Operand of kind Def or Mod, or else must be a “clobber”.

This can be used to, for example, describe ABI-specified registers that are not preserved by a call instruction, or fixed physical registers written by an instruction but not used as a vreg output, or fixed physical registers used as temps within an instruction out of necessity.

Note that it is legal for a register to be both a clobber and an actual def (via pinned vreg or via operand constrained to the reg). This is for convenience: e.g., a call instruction might have a constant clobber set determined by the ABI, but some of those clobbered registers are sometimes return value(s).

Get the number of VReg in use in this function.

How many logical spill slots does the given regclass require? E.g., on a 64-bit machine, spill slots may nominally be 64-bit words, but a 128-bit vector value will require two slots. The regalloc will always align on this size.

(This trait method’s design and doc text derives from regalloc.rs’ trait of the same name.)

Provided methods

Determine whether an instruction requires all reference-typed values to be placed onto the stack. For these instructions, stackmaps will be provided.

This is usually associated with the concept of a “safepoint”, though strictly speaking, a safepoint could also support reference-typed values in registers if there were a way to denote their locations and if this were acceptable to the client. Usually garbage-collector implementations want to see roots on the stack, so we do that for now.

Get the VRegs that are pointer/reference types. This has the following effects for each such vreg:

  • At all safepoint instructions, the vreg will be in a SpillSlot, not in a register.
  • The vreg may not be used as a register operand on safepoint instructions: this is because a vreg can only live in one place at a time. The client should copy the value to an integer-typed vreg and use this to pass a pointer as an input to a safepoint instruction (such as a function call).
  • At all safepoint instructions, all live vregs’ locations will be included in a list in the Output below, so that pointer-inspecting/updating functionality (such as a moving garbage collector) may observe and edit their values.

Get the VRegs for which we should generate value-location metadata for debugging purposes. This can be used to generate e.g. DWARF with valid prgram-point ranges for each value expression in a way that is more efficient than a post-hoc analysis of the allocator’s output.

Each tuple is (vreg, inclusive_start, exclusive_end, label). In the Output there will be (label, inclusive_start, exclusive_end, alloc)` tuples. The ranges may not exactly match – specifically, the returned metadata may cover only a subset of the requested ranges – if the value is not live for the entire requested ranges.

The instruction indices imply a program point just before the instruction.

Precondition: we require this slice to be sorted by vreg.

Is the given vreg pinned to a preg? If so, every use of the vreg is automatically assigned to the preg, and live-ranges of the vreg allocate the preg exclusively (are not spilled elsewhere). The user must take care not to have too many live pinned vregs such that allocation is no longer possible; liverange computation will check that this is the case (that there are enough remaining allocatable pregs of every class to hold all Reg-constrained operands).

Pinned vregs are implicitly live-in to the function: that is, one can use a pinned vreg without having first defined it, and this will take the value that that physical register (to which the vreg is pinned) had at function entry.

When providing a spillslot number for a multi-slot spillslot, do we provide the first or the last? This is usually related to which direction the stack grows and different clients may have different preferences.

Allow a single instruction to define a vreg multiple times. If allowed, the semantics are as if the definition occurs only once, and all defs will get the same alloc. This flexibility is meant to allow the embedder to more easily aggregate operands together in macro/pseudoinstructions, or e.g. add additional clobbered vregs without taking care to deduplicate. This may be particularly useful when referring to physical registers via pinned vregs. It is optional functionality because a strict mode (at most one def per vreg) is also useful for finding bugs in other applications.

Implementors