jit_assembler/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3//! # Multi-Architecture JIT Assembler
4//!
5//! A multi-architecture JIT assembler library for runtime code generation.
6//!
7//! ## Features
8//!
9//! - **Multi-architecture support**: RISC-V, AArch64, x86-64 (planned)
10//! - **Host-independent**: Runs on any host architecture to generate target code
11//! - **No-std compatible**: Works in both `std` and `no_std` environments
12//! - **Macro-based DSL**: Convenient syntax for writing assembly
13//! - **JIT execution**: Direct execution of assembled code as functions (std-only)
14//!
15//! ## Supported Architectures
16//!
17//! - **RISC-V 64-bit** (`riscv` feature, enabled by default)
18//! - **AArch64** (`aarch64` feature, enabled by default) - Basic arithmetic and logical operations
19//! - **x86-64** (`x86_64` feature) - Coming soon
20//!
21//! ## Usage
22//!
23//! ```rust
24//! # #[cfg(feature = "riscv64")]
25//! # {
26//! use jit_assembler::riscv64::{reg, csr, Riscv64InstructionBuilder};
27//! use jit_assembler::common::InstructionBuilder;
28//!
29//! // Method chaining style (recommended)
30//! let mut builder = Riscv64InstructionBuilder::new();
31//! let instructions = builder
32//!     .csrrw(reg::RA, csr::MSTATUS, reg::SP)
33//!     .addi(reg::A0, reg::ZERO, 100)
34//!     .add(reg::A1, reg::A0, reg::SP)
35//!     .ret()
36//!     .instructions();
37//!
38//! // Macro style (concise and assembly-like)
39//! let instructions3 = jit_assembler::riscv64_asm! {
40//!     csrrw(reg::RA, csr::MSTATUS, reg::SP);
41//!     addi(reg::A0, reg::ZERO, 100);
42//!     add(reg::A1, reg::A0, reg::SP);
43//!     ret();
44//! };
45//!
46//! // Traditional style  
47//! let mut builder2 = Riscv64InstructionBuilder::new();
48//! builder2.csrrw(reg::RA, csr::MSTATUS, reg::SP);
49//! builder2.addi(reg::A0, reg::ZERO, 100);
50//! builder2.ret();
51//! let instructions2 = builder2.instructions();
52//! // InstructionCollection provides convenient methods
53//! let bytes = instructions.to_bytes();     // Convert all to bytes
54//! let size = instructions.total_size();    // Get total size
55//! let count = instructions.len();          // Get instruction count
56//!
57//! // Iterate over instructions
58//! for instr in instructions {
59//!     let bytes = instr.bytes();
60//!     // Write to executable memory...
61//! }
62//! # }
63//! ```
64//!
65//! ## AArch64 Usage
66//!
67//! ```rust
68//! # #[cfg(feature = "aarch64")]
69//! # {
70//! use jit_assembler::aarch64::{reg, Aarch64InstructionBuilder};
71//! use jit_assembler::common::InstructionBuilder;
72//!
73//! // Create an AArch64 function that adds two numbers
74//! let mut builder = Aarch64InstructionBuilder::new();
75//! let instructions = builder
76//!     .add(reg::X0, reg::X0, reg::X1)  // Add first two arguments (X0 + X1 -> X0)
77//!     .ret()                           // Return
78//!     .instructions();
79//!
80//! // Macro style (concise and assembly-like)
81//! let instructions3 = jit_assembler::aarch64_asm! {
82//!     add(reg::X0, reg::X0, reg::X1);  // Add first two arguments
83//!     mov_imm(reg::X1, 42);            // Load immediate 42 into X1
84//!     mul(reg::X0, reg::X0, reg::X1);  // Multiply X0 by 42
85//!     ret();                           // Return
86//! };
87//!
88//! // More complex AArch64 example with immediate values
89//! let mut builder2 = Aarch64InstructionBuilder::new();
90//! let instructions2 = builder2
91//!     .mov_imm(reg::X1, 42)            // Load immediate 42 into X1
92//!     .mul(reg::X0, reg::X0, reg::X1)  // Multiply X0 by 42
93//!     .addi(reg::X0, reg::X0, 100)     // Add 100 to result
94//!     .ret()                           // Return
95//!     .instructions();
96//! # }
97//! ```
98//!
99//! ## JIT Execution (std-only)
100//!
101//! ```rust,no_run
102//! # #[cfg(feature = "riscv64")]
103//! # {
104//! use jit_assembler::riscv64::{reg, Riscv64InstructionBuilder};
105//! use jit_assembler::common::InstructionBuilder;
106//! 
107//! // Create a JIT function that adds two numbers
108//! let add_func = unsafe {
109//!     Riscv64InstructionBuilder::new()
110//!         .add(reg::A0, reg::A0, reg::A1) // Add first two arguments
111//!         .ret()                          // Return result
112//!         .function::<fn(u64, u64) -> u64>()
113//! }.expect("Failed to create JIT function");
114//!
115//! // Call the JIT function naturally!
116//! let result = add_func.call(10, 20);
117//! assert_eq!(result, 30);
118//! # }
119//! ```
120
121#[cfg(not(feature = "std"))]
122extern crate alloc;
123
124// Common types and traits shared across architectures
125pub mod common;
126
127// Re-export JIT functionality when std is available
128#[cfg(feature = "std")]
129pub use common::jit::{CallableJitFunction, JitError};
130
131// Architecture-specific modules
132#[cfg(feature = "riscv64")]
133pub mod riscv64;
134
135#[cfg(feature = "x86_64")]
136pub mod x86_64;
137
138#[cfg(feature = "aarch64")]
139pub mod aarch64;
140
141// Re-export for convenience (default to RISC-V if available)
142#[cfg(feature = "riscv64")]
143pub use riscv64 as default_arch;
144
145/// Generic JIT assembler macro - Reference implementation
146///
147/// This is a reference implementation that can be used by each architecture.
148/// Each architecture can provide their own specialized version by specifying
149/// the appropriate InstructionBuilder type.
150///
151/// Usage pattern for architecture-specific implementations:
152/// ```rust
153/// #[macro_export]
154/// macro_rules! arch_asm {
155///     ($($method:ident($($args:expr),*);)*) => {{
156///         $crate::jit_asm_generic!(YourArchInstructionBuilder, $($method($($args),*);)*)
157///     }};
158/// }
159/// ```
160#[macro_export]
161macro_rules! jit_asm_generic {
162    ($builder_type:ty, $($method:ident($($args:expr),*);)*) => {{
163        let mut builder = <$builder_type>::new();
164        $(
165            builder.$method($($args),*);
166        )*
167        builder.instructions().to_vec()
168    }};
169}