Skip to main content

Crate asmkit

Crate asmkit 

Source
Expand description

§asmkit

§Overview

asmkit is a portable assembler toolkit built around an AsmJit-style instruction-database model. It is a small, efficient, no_std library for encoding machine code without being tied to a specific platform. Key features include:

  • Multi-Architecture Support: x86/x64, RISC-V, and AArch64. Each backend follows the same uniform model: a dense InstId enum backed by generated instdb tables, and a single checked raw emit entry point.
  • Generated emitter traits: per-mnemonic traits (e.g. MovEmitter) with impls for the sized register wrappers, so register constants and integer immediates are passed directly (asm.mov(RAX, 42) — no dereferencing).
  • Read/write effects: query_rw_info(&Inst) -> InstRwInfo per architecture, over the architecture-tagged Inst.
  • Deferred emission: Builder records instructions and label binds and replays them into any InstSink (implemented by every architecture’s Assembler).
  • Minimal Dependencies:
    • libc, intrusive-collections, errno - For JIT support.
    • paste, bitflags, cfgenius, num-traits - Utility crates that simplify repetitive arch-specific declarations.
    • smallvec - Avoids frequent heap allocation during code generation.
  • Code Relocations: Provides a CodeBuffer interface to handle relocations, allowing the insertion of symbols into the API seamlessly.
  • Portability: Built to run on any platform, with the architecture-specific parts of the library being independent of the platform on which asmkit is built.

§From assembly to execution

The API story mirrors AsmJit’s (CodeHolderJitAllocator), with CodeBuffer playing the CodeHolder role:

  1. Emit into a CodeBuffer through a backend Assembler.
  2. Finalize with CodeBuffer::finish, optionally combining several modules — Sections or plain buffers — into one image with Linker.
  3. Load with [CodeBufferFinalized::allocate] (no relocations), allocate_relocated, or allocate_resolved (external symbols resolved via ExternalName).
  4. Find entry points with CodeBufferFinalized::defined_symbol_offset / defined_symbol_str and call through rx() + offset.

External names are either string ExternalName::Symbols or Cranelift-style ExternalName::User namespace+index keys (extern_user / bind_symbol), so hosts that do not use string symbols can still link and resolve.

Void mnemonic methods retain the first emission error in the CodeBuffer. CodeBuffer::finish returns it, alongside finalization, linking, loading, and patching errors, as AsmError.

§Usage

To use the library simply import the module for the architecture you want to emit code for, e.g. use asmkit::x86::*;; this includes all the code required to generate code for that platform.

Example:

use asmkit::{Arch, CodeBuffer, Environment, JitAllocator};
use asmkit::x86::*;

let mut buf = CodeBuffer::new(Environment::new(Arch::X64));
{
let mut asm = Assembler::new(&mut buf);

// Typed sized registers and plain integer immediates.
asm.mov(RAX, 5);
asm.add(RAX, 37);
asm.ret();
}

let result = buf.finish().expect("assembly failed");
let mut jit = JitAllocator::new(Default::default());
// you can also use jit.alloc + jit.write manually.
let span = result
    .allocate(&mut jit)
    .expect("failed to allocate JIT-code");

// JIT Allocator uses dual-mapping: it allocates two pages which map to same physical space
// and you write to executable code through `span.rw()` pointer while you can execute `span.rx()`.
let f: extern "C" fn() -> u64 = unsafe { std::mem::transmute(span.rx()) };
#[cfg(all(unix, target_arch = "x86_64"))] // can run only on x64 and on SystemV platforms.
assert_eq!(f(), 42);

Modules§

aarch64
riscv
x86
X86 Assembler.

Structs§

AsmReloc
A relocation resulting from emitting assembly.
BaseMem
BaseReg
Builder
Records instructions and label-bind points for deferred emission.
CodeBuffer
A buffer of output to be produced, fixed up, and then emitted to a CodeSink in bulk.
CodeBufferFinalized
A CodeBuffer once emission is completed: holds generated code and records, without fixups. This allows the type to be independent of the backend.
Constant
A use of a constant by one or mroe assembly instructions.
CpuRwFlags
CPU read/write flags used by InstRwInfo.
Environment
FinalizedSection
A section whose buffer has been finalized, ready for linking.
Imm
Inst
A generic instruction: id + options + extra register + inline operand array.
InstOptions
InstRwFlags
Flags used by InstRwInfo.
InstRwInfo
Read/write information of an instruction.
Label
Linker
Links finalized sections and buffers into one in-memory image.
OpRwFlags
Operand read/write flags describe how the operand is accessed and additional features.
OpRwInfo
Read/write information related to a single operand, used by InstRwInfo.
Operand
Base struct representing an operand in asmkit.
OperandSignature
PatchBlock
PatchBlockId
PatchCatalog
PatchSite
PatchSiteId
Section
A named section: its own code buffer plus an alignment requirement.
Sym
UserExternalName
An external name in a user-defined symbol table.

Enums§

AArch64Feature
AArch64 architectural features present in the pinned AsmJit ISA metadata.
Arch
Instruction set architecture (ISA).
AsmError
Error type shared by all backends and the core code-management machinery.
CondCode
ConstantData
ExternalName
Name of an external (or exported) symbol.
ImmType
InstControlFlow
Instruction control flow.
InstSameRegHint
Hint used when two or more operands of an instruction are the same register.
LabelUse
LinkError
Context for an in-memory image-link failure.
Node
A node recorded by a Builder.
OperandType
Operand type used by Operand
RegGroup
RegType
Register type.
Reloc
Relocation kinds for every ISA
RelocDistance
RelocTarget
RiscVFeature
RISC-V extension identifiers from the pinned riscv-opcodes input files.
X86Error
Detailed x86/x64 encoding error, wrapped by AsmError::X86.
X86Feature
X86 CPU feature identifiers (port of AsmJit’s CpuFeatures::X86).

Constants§

INVALID_PHYS_ID
Physical register id used when an operand is not tied to any specific physical register.

Traits§

InstSink
Sink that consumes replayed nodes — implemented by each architecture’s Assembler.
OperandCast
A helper trait to help cast Operand to Architecture dependent operands and vice-versa.
RegTraits

Functions§

imm

Type Aliases§

Addend
Addend to add to the symbol value.
CodeOffset
Offset in bytes from the beginning of the function.
RegMask
Register mask is a convenience typedef that describes a mask where each bit describes a physical register id in the same RegGroup. At the moment 32 bits are enough as asmkit doesn’t support any architecture that would provide more than 32 registers for a register group.