Skip to main content

Assembler

Struct Assembler 

Source
pub struct Assembler { /* private fields */ }
Expand description

x86-64 assembler with label support.

Uses direct pointer writes to the pre-allocated buffer for emission, avoiding per-byte Vec::push overhead (capacity check + len update).

Implementations§

Source§

impl Assembler

Source

pub fn new() -> Self

Source

pub fn with_capacity(code_capacity: usize, label_capacity: usize) -> Self

Create with pre-allocated capacity for code and labels.

Source

pub fn set_jit_va_base(&mut self, va: u64)

Set the eventual load VA for the code buffer. Must be called before any RIP-relative emitter that targets a fixed VA (i.e. CTX accesses).

Source

pub fn ensure_capacity(&mut self, n: usize)

Check capacity and grow if needed. Inlined for the fast path (no grow).

Source

pub fn new_label(&mut self) -> Label

Allocate a new label.

Source

pub fn labels_len(&self) -> usize

Current number of labels allocated.

Source

pub fn bulk_create_labels(&mut self, count: usize)

Bulk-allocate count unbound labels. The labels Vec is already pre-sized via calloc (zero pages). This just advances the logical length counter.

Source

pub fn bind_label(&mut self, label: Label)

Bind a label to the current write position.

Source

pub fn offset(&self) -> usize

Current code offset (write position).

Source

pub fn patch_i32(&mut self, offset: usize, value: i32)

Patch an i32 value at a previously recorded offset.

Source

pub fn mov_rr(&mut self, dst: Reg, src: Reg)

mov r64, r64

Source

pub fn mov_ri64(&mut self, dst: Reg, imm: u64)

mov r64, imm64

Source

pub fn mov_ri32(&mut self, dst: Reg, imm: u32)

mov r32, imm32 (zero-extends to 64-bit)

Source

pub fn mov_load64(&mut self, dst: Reg, base: Reg, disp: i32)

mov r64, [base + disp]

Source

pub fn movsxd_load_sib4(&mut self, dst: Reg, base: Reg, index: Reg)

movsxd r64, dword [base + index*4] — sign-extending load with SIB scale=4

Source

pub fn mov_store32(&mut self, base: Reg, disp: i32, src: Reg)

mov dword [base + disp], r32 — 32-bit store

Source

pub fn mov_store64(&mut self, base: Reg, disp: i32, src: Reg)

mov [base + disp], r64

Source

pub fn add_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn sub_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn and_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn or_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn xor_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn cmp_rr(&mut self, a: Reg, b: Reg)

Source

pub fn test_rr(&mut self, a: Reg, b: Reg)

Source

pub fn test_rr32(&mut self, a: Reg, b: Reg)

test r32, r32 — sets ZF iff the low 32 bits are zero (ignores the high 32 bits). Used by the 32-bit divw/remw zero-divisor guard, which must test only the bits idivl/divl actually consume.

Source

pub fn add_rr32(&mut self, dst: Reg, src: Reg)

Source

pub fn sub_rr32(&mut self, dst: Reg, src: Reg)

Source

pub fn add_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn sub_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn and_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn or_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn xor_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn cmp_ri(&mut self, a: Reg, imm: i32)

Source

pub fn add_ri32(&mut self, dst: Reg, imm: i32)

Source

pub fn sub_ri32(&mut self, dst: Reg, imm: i32)

Source

pub fn cmp_ri32(&mut self, a: Reg, imm: i32)

Source

pub fn movzx_load8_at_index(&mut self, dst: Reg, idx: Reg)

movzx r64, byte [idx] — zero-extending u8 load

Source

pub fn movzx_load16_at_index(&mut self, dst: Reg, idx: Reg)

movzx r64, word [idx] — zero-extending u16 load

Source

pub fn mov_load32_at_index(&mut self, dst: Reg, idx: Reg)

mov r32, dword [idx] — zero-extending u32 load (writes EAX, clears upper 32)

Source

pub fn mov_load64_at_index(&mut self, dst: Reg, idx: Reg)

mov r64, qword [idx]

Source

pub fn mov_store8_at_index(&mut self, idx: Reg, src: Reg)

mov byte [idx], r8

Source

pub fn mov_store16_at_index(&mut self, idx: Reg, src: Reg)

mov word [idx], r16

Source

pub fn mov_store32_at_index(&mut self, idx: Reg, src: Reg)

mov dword [idx], r32

Source

pub fn mov_store64_at_index(&mut self, idx: Reg, src: Reg)

mov qword [idx], r64

Source

pub fn mov_load32_rip_rel(&mut self, dst: Reg, target_va: u64)

mov r32, dword [rip+disp32] (zero-extends to 64-bit)

Source

pub fn mov_load64_rip_rel(&mut self, dst: Reg, target_va: u64)

mov r64, qword [rip+disp32]

Source

pub fn mov_store32_rip_rel(&mut self, target_va: u64, src: Reg)

mov dword [rip+disp32], r32

Source

pub fn mov_store64_rip_rel(&mut self, target_va: u64, src: Reg)

mov qword [rip+disp32], r64

Source

pub fn mov_store32_rip_rel_imm(&mut self, target_va: u64, imm: i32)

mov dword [rip+disp32], imm32 — the trailing imm32 means the “next-instruction RIP” is 4 bytes further than disp32 alone.

Source

pub fn add_r64_mem_rip_rel(&mut self, dst: Reg, target_va: u64)

add r64, qword [rip+disp32]

Source

pub fn cmp_r64_mem_rip_rel(&mut self, dst: Reg, target_va: u64)

cmp r64, qword [rip+disp32] — compare a register against a memory operand (used by the x3/x4 spill path’s branch, where a spilled source lives in JitContext.regs[13|14]).

Source

pub fn sub_r64_imm32_patchable(&mut self, dst: Reg, imm: i32)

sub r64, imm32 in the always-imm32 (7-byte) encoding. offset() - 4 after this call points at the imm32 field; callers patch it after emission for per-block gas metering.

Source

pub fn cmp_r64_imm32_patchable(&mut self, dst: Reg, imm: i32)

cmp r64, imm32 in the always-imm32 (7-byte) encoding — a non-mutating gate (sets flags, leaves dst unchanged). Mirrors Self::sub_r64_imm32_patchable but with reg-field = 7 (CMP). offset() - 4 after this call points at the imm32 field; callers patch it for the per-block check-before-charge gas gate.

Source

pub fn imul_rr(&mut self, dst: Reg, src: Reg)

imul r64, r64

Source

pub fn imul_rr32(&mut self, dst: Reg, src: Reg)

imul r32, r32

Source

pub fn mul_rdx_rax(&mut self, src: Reg)

mul r64 (unsigned RDX:RAX = RAX * src)

Source

pub fn imul_rdx_rax(&mut self, src: Reg)

imul r64 (signed RDX:RAX = RAX * src)

Source

pub fn div64(&mut self, src: Reg)

div r64 (unsigned RAX = RDX:RAX / src, RDX = remainder)

Source

pub fn idiv64(&mut self, src: Reg)

idiv r64 (signed)

Source

pub fn div32(&mut self, src: Reg)

div r32

Source

pub fn idiv32(&mut self, src: Reg)

idiv r32

Source

pub fn cqo(&mut self)

cqo (sign-extend RAX into RDX:RAX, 64-bit)

Source

pub fn cdq(&mut self)

cdq (sign-extend EAX into EDX:EAX, 32-bit)

Source

pub fn neg64(&mut self, dst: Reg)

neg r64

Source

pub fn not64(&mut self, dst: Reg)

not r64

Source

pub fn shift_cl64(&mut self, ext: u8, dst: Reg)

Source

pub fn shift_cl32(&mut self, ext: u8, dst: Reg)

Source

pub fn shl_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn shr_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn sar_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn shl_cl64(&mut self, dst: Reg)

Source

pub fn ror_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn shl_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn shr_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn sar_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn ror_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn movsxd(&mut self, dst: Reg, src: Reg)

movsxd r64, r32 (sign-extend 32→64)

Source

pub fn movsx_8_64(&mut self, dst: Reg, src: Reg)

movsx r64, r8 (sign-extend 8→64)

Source

pub fn movsx_16_64(&mut self, dst: Reg, src: Reg)

movsx r64, r16 (sign-extend 16→64)

Source

pub fn movzx_16_64(&mut self, dst: Reg, src: Reg)

movzx r32, r16 (zero-extends to 64 due to 32-bit operation)

Source

pub fn movzx_32_64(&mut self, dst: Reg, src: Reg)

Zero-extend 32→64: mov r32, r32 (implicit zero-extend)

Source

pub fn setcc(&mut self, cc: Cc, dst: Reg)

setcc r8 (sets low byte, need to movzx after)

Source

pub fn cmovcc(&mut self, cc: Cc, dst: Reg, src: Reg)

cmovcc r64, r64

Source

pub fn popcnt64(&mut self, dst: Reg, src: Reg)

popcnt r64, r64

Source

pub fn lzcnt64(&mut self, dst: Reg, src: Reg)

lzcnt r64, r64

Source

pub fn tzcnt64(&mut self, dst: Reg, src: Reg)

tzcnt r64, r64

Source

pub fn popcnt32(&mut self, dst: Reg, src: Reg)

popcnt r32, r32 (result zero-extended to 64 bits)

Source

pub fn lzcnt32(&mut self, dst: Reg, src: Reg)

lzcnt r32, r32 (result zero-extended to 64 bits)

Source

pub fn tzcnt32(&mut self, dst: Reg, src: Reg)

tzcnt r32, r32 (result zero-extended to 64 bits)

Source

pub fn bswap64(&mut self, dst: Reg)

bswap r64

Source

pub fn push(&mut self, reg: Reg)

Source

pub fn pop(&mut self, reg: Reg)

Source

pub fn jmp_label(&mut self, label: Label)

jmp to label — uses rel8 for backward jumps within ±127 bytes.

Source

pub fn jcc_label(&mut self, cc: Cc, label: Label)

jcc to label — uses rel8 for backward jumps within ±127 bytes.

Source

pub fn jmp_reg(&mut self, reg: Reg)

jmp r64 (indirect)

Source

pub fn ret(&mut self)

ret

Source

pub fn lea(&mut self, dst: Reg, base: Reg, disp: i32)

lea r64, [base + disp]

Source

pub fn lea_32(&mut self, dst: Reg, base: Reg, disp: i32)

lea r32, [base + disp] — 32-bit result, zero-extends to 64-bit.

Source

pub fn lea_sib_scaled_32( &mut self, dst: Reg, base: Reg, index: Reg, scale_log2: u8, )

lea r32, [base32 + index32 * (1 << scale_log2)] scale_log2: 0=*1, 1=*2, 2=*4, 3=*8

Source

pub fn nop(&mut self)

nop

Source

pub fn label_offset(&self, label: Label) -> Option<usize>

Get the resolved native offset for a label (only valid after bind_label).

Source

pub fn fixups_len(&self) -> usize

Current number of pending fixups. Capture this before emitting a label-referencing instruction so the caller can later redirect_fixup the entry that the emission appends. Forward references push exactly one fixup; backward references push none (resolved immediately).

Source

pub fn redirect_fixup(&mut self, idx: usize, new_label: Label)

Rewrite the target label of an existing fixup. Used by RV streaming compile to redirect forward branches whose target is determined to be invalid only after the streaming pass completes.

Source

pub fn finalize(&mut self) -> Vec<u8>

Resolve fixups and return the code as a Vec<u8>.

Trait Implementations§

Source§

impl Default for Assembler

Source§

fn default() -> Self

Returns the “default value” for a type. 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> 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, 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.