pub struct Builder<'a> { /* private fields */ }Expand description
A cursor that appends to the end of one block.
This is the shape lowering wants: it works on one block at a time, it appends, and it wants
the value back so it can use it in the next instruction. Everything here is a thin wrapper
over Func::create_inst and Func::append_inst, and anything the wrappers do not
cover is done with those two directly.
Implementations§
Source§impl<'a> Builder<'a>
impl<'a> Builder<'a>
Sourcepub fn new(func: &'a mut Func, block: Block) -> Self
pub fn new(func: &'a mut Func, block: Block) -> Self
A cursor appending to that block, with every instruction taking that source location.
Sourcepub fn at(self, span: Span) -> Self
pub fn at(self, span: Span) -> Self
The same cursor, with a source location for the instructions after this.
Sourcepub fn set_span(&mut self, span: Span)
pub fn set_span(&mut self, span: Span)
Sets the source location for the instructions after this.
Sourcepub fn inst(&mut self, data: InstData, results: &[Type]) -> Inst
pub fn inst(&mut self, data: InstData, results: &[Type]) -> Inst
Appends an instruction as it is, and gives back its results.
Sourcepub fn fconst(&mut self, ty: Type, bits: u128) -> Value
pub fn fconst(&mut self, ty: Type, bits: u128) -> Value
A floating point constant, given as the bits of its format.
Sourcepub fn binary(
&mut self,
opcode: Opcode,
lhs: Value,
rhs: Value,
flags: Flags,
) -> Value
pub fn binary( &mut self, opcode: Opcode, lhs: Value, rhs: Value, flags: Flags, ) -> Value
A two-operand instruction whose result has the type of its operands.
Sourcepub fn checked(
&mut self,
opcode: Opcode,
lhs: Value,
rhs: Value,
) -> (Value, Value)
pub fn checked( &mut self, opcode: Opcode, lhs: Value, rhs: Value, ) -> (Value, Value)
Arithmetic that answers with both the wrapped result and whether it wrapped.
The one shape in the IR whose result is two things, which is why it has a builder of its
own rather than going through Builder::value. The first result is the answer in the
type of the operands, the same as the ordinary form of the same arithmetic would give, and
the second is one i1 per lane saying whether the exact answer needed more bits than that
type has.
§Panics
Panics if the instruction did not produce exactly the two results it was created with,
which is the same promise Builder::value makes about its one.
Sourcepub fn unary(&mut self, opcode: Opcode, arg: Value, ty: Type) -> Value
pub fn unary(&mut self, opcode: Opcode, arg: Value, ty: Type) -> Value
A one-operand instruction whose result has the type given.
Sourcepub fn icmp(&mut self, pred: IntPred, lhs: Value, rhs: Value) -> Value
pub fn icmp(&mut self, pred: IntPred, lhs: Value, rhs: Value) -> Value
An integer comparison, which produces one i1 per lane.
Sourcepub fn select(&mut self, cond: Value, then: Value, other: Value) -> Value
pub fn select(&mut self, cond: Value, then: Value, other: Value) -> Value
One of two values, chosen by a bit, which is what a diamond becomes when it stops being one.
The type comes from the arms rather than from the bit, and the two arms have to agree, which the verifier checks. Both are evaluated, so the caller owes the argument that evaluating the one that is not chosen is harmless.
Sourcepub fn fcmp(
&mut self,
pred: FloatPred,
lhs: Value,
rhs: Value,
flags: Flags,
) -> Value
pub fn fcmp( &mut self, pred: FloatPred, lhs: Value, rhs: Value, flags: Flags, ) -> Value
A floating point comparison, which produces one i1 per lane.
Sourcepub fn mem_entry(&mut self) -> Value
pub fn mem_entry(&mut self) -> Value
Memory as the function found it, which is where a memory SSA chain starts.
It belongs at the top of the entry block and there is one of them in a function.
Sourcepub fn load(
&mut self,
ty: Type,
addr: Value,
info: MemInfo,
flags: Flags,
) -> Value
pub fn load( &mut self, ty: Type, addr: Value, info: MemInfo, flags: Flags, ) -> Value
A read of that type from that address.
Sourcepub fn store(
&mut self,
value: Value,
addr: Value,
info: MemInfo,
flags: Flags,
) -> Inst
pub fn store( &mut self, value: Value, addr: Value, info: MemInfo, flags: Flags, ) -> Inst
A write of a value to an address.
Sourcepub fn atomic_load(
&mut self,
ty: Type,
addr: Value,
info: MemInfo,
flags: Flags,
) -> Value
pub fn atomic_load( &mut self, ty: Type, addr: Value, info: MemInfo, flags: Flags, ) -> Value
The same read, ordered.
A separate opcode rather than an ordering on Builder::load, because the two are not the
same thing to anything that moves code: a plain load may be moved, duplicated and dropped,
and this one may not. The IR verifier is what keeps the pair honest, since it refuses an
ordering on a plain access and refuses an unordered one here, so no pass has to remember to
check the payload before deciding a load is free.
Sourcepub fn atomic_store(
&mut self,
value: Value,
addr: Value,
info: MemInfo,
flags: Flags,
) -> Inst
pub fn atomic_store( &mut self, value: Value, addr: Value, info: MemInfo, flags: Flags, ) -> Inst
The same write, ordered.
Sourcepub fn cmpxchg(
&mut self,
addr: Value,
expected: Value,
desired: Value,
info: MemInfo,
flags: Flags,
) -> (Value, Value)
pub fn cmpxchg( &mut self, addr: Value, expected: Value, desired: Value, info: MemInfo, flags: Flags, ) -> (Value, Value)
A compare and exchange, which answers what it found and whether that was what was expected.
Two values out of one instruction, in that order, because a caller that had to ask twice
would be asking about two different moments. The type of the first is the type of the value
expected, which is what says how wide the access is, and the type of the second is
Type::I1 whatever the width was.
Sourcepub fn atomic_rmw(
&mut self,
op: RmwOp,
addr: Value,
operand: Value,
info: MemInfo,
flags: Flags,
) -> Value
pub fn atomic_rmw( &mut self, op: RmwOp, addr: Value, operand: Value, info: MemInfo, flags: Flags, ) -> Value
A read, an operation on what was read, and a write back, with nothing able to get between them.
The value it answers is the one that was there before, which is the convention every machine and every language in this area uses, and a caller that wanted the value afterwards works it out from the two it already has rather than asking for a second flavour of the instruction. The type of that value is the type of the operand, which is what says how wide the access is.
Sourcepub fn fence(&mut self, order: MemOrder) -> Inst
pub fn fence(&mut self, order: MemOrder) -> Inst
A barrier, which touches no address and is its ordering and nothing else.
Sourcepub fn block_addr(&mut self, target: Block) -> Value
pub fn block_addr(&mut self, target: Block) -> Value
The address of a block, which is a value a later indirect_br can branch to.
The block is a target here in the same sense a branch’s is, so everything that asks an instruction which blocks it names finds this one, and a block whose address is taken is not mistaken for a block nothing mentions.
Sourcepub fn indirect_br(&mut self, addr: Value, targets: &[Block]) -> Inst
pub fn indirect_br(&mut self, addr: Value, targets: &[Block]) -> Inst
A branch to an address, which arrives at one of the blocks listed.
Every block the address can hold has to be there. The list is what the rest of the compiler reads, so a block left out of it is a block the branch is saying it never reaches, and none of it is checked against the addresses anybody took.
Sourcepub fn br_if(
&mut self,
cond: Value,
then_block: Block,
then_args: &[Value],
else_block: Block,
else_args: &[Value],
) -> Inst
pub fn br_if( &mut self, cond: Value, then_block: Block, then_args: &[Value], else_block: Block, else_args: &[Value], ) -> Inst
A two-way branch, taking the first target when the condition is one.
Sourcepub fn switch(
&mut self,
value: Value,
default: Block,
cases: &[(i128, Block)],
) -> Inst
pub fn switch( &mut self, value: Value, default: Block, cases: &[(i128, Block)], ) -> Inst
A branch on an integer, taking the target its value selects and the default when it selects none.
The cases are values and blocks rather than a table with the default in it, because the
order the side table wants, which is the default first, is not an order anybody building
a switch has their cases in.
Sourcepub fn unreachable(&mut self) -> Inst
pub fn unreachable(&mut self) -> Inst
A place control does not reach.
Sourcepub fn call(&mut self, callee: Symbol, signature: Sig, args: &[Value]) -> Inst
pub fn call(&mut self, callee: Symbol, signature: Sig, args: &[Value]) -> Inst
A direct call, with the results its signature says it produces.
Sourcepub fn call_varargs(
&mut self,
callee: Symbol,
signature: Sig,
args: &[Value],
varargs: &[Abi],
) -> Inst
pub fn call_varargs( &mut self, callee: Symbol, signature: Sig, args: &[Value], varargs: &[Abi], ) -> Inst
The same, saying how the arguments the signature does not name travel.
Empty says they all travel as the values in hand, which is what Builder::call passes
and is the usual case. Anything else has one entry for each argument past the ones the
signature names.
Sourcepub fn inline_asm(
&mut self,
info: AsmInfo,
args: &[Value],
results: &[Type],
flags: Flags,
) -> Inst
pub fn inline_asm( &mut self, info: AsmInfo, args: &[Value], results: &[Type], flags: Flags, ) -> Inst
Inline assembly, which is a terminator when the info carries targets.
The targets are built by the caller, because the frontend is the only thing that knows which block is the one control reaches when the assembly does not jump, and that block has to come first.