pub struct MachBuffer<I: VCodeInst> { /* private fields */ }
Expand description
A buffer of output to be produced, fixed up, and then emitted to a CodeSink in bulk.
This struct uses SmallVec
s to support small-ish function bodies without
any heap allocation. As such, it will be several kilobytes large. This is
likely fine as long as it is stack-allocated for function emission then
thrown away; but beware if many buffer objects are retained persistently.
Implementations§
source§impl<I: VCodeInst> MachBuffer<I>
impl<I: VCodeInst> MachBuffer<I>
sourcepub fn new() -> MachBuffer<I>
pub fn new() -> MachBuffer<I>
Create a new section, known to start at start_offset
and with a size limited to
length_limit
.
sourcepub fn cur_offset(&self) -> CodeOffset
pub fn cur_offset(&self) -> CodeOffset
Current offset from start of buffer.
sourcepub fn get_appended_space(&mut self, len: usize) -> &mut [u8] ⓘ
pub fn get_appended_space(&mut self, len: usize) -> &mut [u8] ⓘ
Reserve appended space and return a mutable slice referring to it.
sourcepub fn align_to(&mut self, align_to: CodeOffset)
pub fn align_to(&mut self, align_to: CodeOffset)
Align up to the given alignment.
sourcepub fn start_patchable(&mut self) -> OpenPatchRegion
pub fn start_patchable(&mut self) -> OpenPatchRegion
Begin a region of patchable code. There is one requirement for the
code that is emitted: It must not introduce any instructions that
could be chomped (branches are an example of this). In other words,
you must not call MachBuffer::add_cond_branch
or
MachBuffer::add_uncond_branch
between calls to this method and
MachBuffer::end_patchable
.
sourcepub fn end_patchable(&mut self, open: OpenPatchRegion) -> PatchRegion
pub fn end_patchable(&mut self, open: OpenPatchRegion) -> PatchRegion
End a region of patchable code, yielding a PatchRegion
value that
can be consumed later to produce a one-off mutable slice to the
associated region of the data buffer.
sourcepub fn get_label(&mut self) -> MachLabel
pub fn get_label(&mut self) -> MachLabel
Allocate a Label
to refer to some offset. May not be bound to a fixed
offset yet.
sourcepub fn reserve_labels_for_blocks(&mut self, blocks: usize)
pub fn reserve_labels_for_blocks(&mut self, blocks: usize)
Reserve the first N MachLabels for blocks.
sourcepub fn register_constants(&mut self, constants: &VCodeConstants)
pub fn register_constants(&mut self, constants: &VCodeConstants)
Registers metadata in this MachBuffer
about the constants
provided.
This will record the size/alignment of all constants which will prepare them for emission later on.
sourcepub fn register_constant(
&mut self,
constant: &VCodeConstant,
data: &VCodeConstantData,
)
pub fn register_constant( &mut self, constant: &VCodeConstant, data: &VCodeConstantData, )
Similar to MachBuffer::register_constants
but registers a
single constant metadata. This function is useful in
situations where not all constants are known at the time of
emission.
sourcepub fn get_label_for_constant(&mut self, constant: VCodeConstant) -> MachLabel
pub fn get_label_for_constant(&mut self, constant: VCodeConstant) -> MachLabel
Returns a label that can be used to refer to the constant
provided.
This will automatically defer a new constant to be emitted for
constant
if it has not been previously emitted. Note that this
function may return a different label for the same constant at
different points in time. The label is valid to use only from the
current location; the MachBuffer takes care to emit the same constant
multiple times if needed so the constant is always in range.
sourcepub fn bind_label(&mut self, label: MachLabel, ctrl_plane: &mut ControlPlane)
pub fn bind_label(&mut self, label: MachLabel, ctrl_plane: &mut ControlPlane)
Bind a label to the current offset. A label can only be bound once.
sourcepub fn use_label_at_offset(
&mut self,
offset: CodeOffset,
label: MachLabel,
kind: I::LabelUse,
)
pub fn use_label_at_offset( &mut self, offset: CodeOffset, label: MachLabel, kind: I::LabelUse, )
Emit a reference to the given label with the given reference type (i.e., branch-instruction format) at the current offset. This is like a relocation, but handled internally.
This can be called before the branch is actually emitted; fixups will not happen until an island is emitted or the buffer is finished.
sourcepub fn add_uncond_branch(
&mut self,
start: CodeOffset,
end: CodeOffset,
target: MachLabel,
)
pub fn add_uncond_branch( &mut self, start: CodeOffset, end: CodeOffset, target: MachLabel, )
Inform the buffer of an unconditional branch at the given offset,
targeting the given label. May be used to optimize branches.
The last added label-use must correspond to this branch.
This must be called when the current offset is equal to start
; i.e.,
before actually emitting the branch. This implies that for a branch that
uses a label and is eligible for optimizations by the MachBuffer, the
proper sequence is:
- Call
use_label_at_offset()
to emit the fixup record. - Call
add_uncond_branch()
to make note of the branch. - Emit the bytes for the branch’s machine code.
Additional requirement: no labels may be bound between start
and end
(exclusive on both ends).
sourcepub fn add_cond_branch(
&mut self,
start: CodeOffset,
end: CodeOffset,
target: MachLabel,
inverted: &[u8],
)
pub fn add_cond_branch( &mut self, start: CodeOffset, end: CodeOffset, target: MachLabel, inverted: &[u8], )
Inform the buffer of a conditional branch at the given offset, targeting the given label. May be used to optimize branches. The last added label-use must correspond to this branch.
Additional requirement: no labels may be bound between start
and end
(exclusive on both ends).
sourcepub fn optimize_branches(&mut self, ctrl_plane: &mut ControlPlane)
pub fn optimize_branches(&mut self, ctrl_plane: &mut ControlPlane)
Performs various optimizations on branches pointing at the current label.
sourcepub fn defer_trap(&mut self, code: TrapCode) -> MachLabel
pub fn defer_trap(&mut self, code: TrapCode) -> MachLabel
Emit a trap at some point in the future with the specified code and stack map.
This function returns a MachLabel
which will be the future address
of the trap. Jumps should refer to this label, likely by using the
MachBuffer::use_label_at_offset
method, to get a relocation
patched in once the address of the trap is known.
This will batch all traps into the end of the function.
sourcepub fn island_needed(&self, distance: CodeOffset) -> bool
pub fn island_needed(&self, distance: CodeOffset) -> bool
Is an island needed within the next N bytes?
sourcepub fn emit_island(
&mut self,
distance: CodeOffset,
ctrl_plane: &mut ControlPlane,
)
pub fn emit_island( &mut self, distance: CodeOffset, ctrl_plane: &mut ControlPlane, )
Emit all pending constants and required pending veneers.
Should only be called if island_needed()
returns true, i.e., if we
actually reach a deadline. It’s not necessarily a problem to do so
otherwise but it may result in unnecessary work during emission.
sourcepub fn finish(
self,
constants: &VCodeConstants,
ctrl_plane: &mut ControlPlane,
) -> MachBufferFinalized<Stencil>
pub fn finish( self, constants: &VCodeConstants, ctrl_plane: &mut ControlPlane, ) -> MachBufferFinalized<Stencil>
Finish any deferred emissions and/or fixups.
sourcepub fn add_reloc_at_offset<T: Into<RelocTarget> + Clone>(
&mut self,
offset: CodeOffset,
kind: Reloc,
target: &T,
addend: Addend,
)
pub fn add_reloc_at_offset<T: Into<RelocTarget> + Clone>( &mut self, offset: CodeOffset, kind: Reloc, target: &T, addend: Addend, )
Add an external relocation at the given offset from current offset.
sourcepub fn add_reloc<T: Into<RelocTarget> + Clone>(
&mut self,
kind: Reloc,
target: &T,
addend: Addend,
)
pub fn add_reloc<T: Into<RelocTarget> + Clone>( &mut self, kind: Reloc, target: &T, addend: Addend, )
Add an external relocation at the current offset.
sourcepub fn add_call_site(&mut self, opcode: Opcode)
pub fn add_call_site(&mut self, opcode: Opcode)
Add a call-site record at the current offset.
sourcepub fn add_unwind(&mut self, unwind: UnwindInst)
pub fn add_unwind(&mut self, unwind: UnwindInst)
Add an unwind record at the current offset.
sourcepub fn start_srcloc(&mut self, loc: RelSourceLoc) -> (CodeOffset, RelSourceLoc)
pub fn start_srcloc(&mut self, loc: RelSourceLoc) -> (CodeOffset, RelSourceLoc)
Set the SourceLoc
for code from this offset until the offset at the
next call to end_srcloc()
.
Returns the current CodeOffset and RelSourceLoc.
sourcepub fn end_srcloc(&mut self)
pub fn end_srcloc(&mut self)
Mark the end of the SourceLoc
segment started at the last
start_srcloc()
call.
sourcepub fn add_stack_map(&mut self, extent: StackMapExtent, stack_map: StackMap)
pub fn add_stack_map(&mut self, extent: StackMapExtent, stack_map: StackMap)
Add stack map metadata for this program point: a set of stack offsets (from SP upward) that contain live references.
sourcepub fn push_user_stack_map(
&mut self,
emit_state: &I::State,
return_addr: CodeOffset,
stack_map: UserStackMap,
)
pub fn push_user_stack_map( &mut self, emit_state: &I::State, return_addr: CodeOffset, stack_map: UserStackMap, )
Push a user stack map onto this buffer.
The stack map is associated with the given return_addr
code
offset. This must be the PC for the instruction just after this stack
map’s associated instruction. For example in the sequence call $foo; add r8, rax
, the return_addr
must be the offset of the start of the
add
instruction.
Stack maps must be pushed in sorted return_addr
order.