use cranelift::prelude::*;
use cranelift_module::Module;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StructEncoding {
Map,
Positional,
}
pub struct JitCursor {
pub input_ptr: Value,
pub len: Value,
pub pos: Variable,
pub ptr_type: Type,
pub scratch_ptr: Value,
}
#[derive(Clone, Copy)]
pub struct JitStringValue {
pub ptr: Value,
pub len: Value,
pub cap: Value,
pub owned: Value,
}
#[repr(C)]
pub struct JitScratch {
pub error_code: i32,
pub error_pos: usize,
pub output_initialized: u8,
pub max_collection_elements: u64,
pub string_scratch_ptr: *mut u8,
pub string_scratch_len: usize,
pub string_scratch_cap: usize,
}
impl Default for JitScratch {
fn default() -> Self {
Self {
error_code: 0,
error_pos: 0,
output_initialized: 0,
max_collection_elements: u64::MAX,
string_scratch_ptr: std::ptr::null_mut(),
string_scratch_len: 0,
string_scratch_cap: 0,
}
}
}
impl Drop for JitScratch {
fn drop(&mut self) {
if !self.string_scratch_ptr.is_null() && self.string_scratch_cap > 0 {
unsafe {
let _ = Vec::from_raw_parts(
self.string_scratch_ptr,
self.string_scratch_len,
self.string_scratch_cap,
);
}
}
}
}
pub const JIT_SCRATCH_ERROR_CODE_OFFSET: i32 = std::mem::offset_of!(JitScratch, error_code) as i32;
pub const JIT_SCRATCH_ERROR_POS_OFFSET: i32 = std::mem::offset_of!(JitScratch, error_pos) as i32;
pub const JIT_SCRATCH_OUTPUT_INITIALIZED_OFFSET: i32 =
std::mem::offset_of!(JitScratch, output_initialized) as i32;
pub const JIT_SCRATCH_MAX_COLLECTION_ELEMENTS_OFFSET: i32 =
std::mem::offset_of!(JitScratch, max_collection_elements) as i32;
#[allow(dead_code)]
pub const JIT_SCRATCH_STRING_PTR_OFFSET: i32 =
std::mem::offset_of!(JitScratch, string_scratch_ptr) as i32;
#[allow(dead_code)]
pub const JIT_SCRATCH_STRING_LEN_OFFSET: i32 =
std::mem::offset_of!(JitScratch, string_scratch_len) as i32;
#[allow(dead_code)]
pub const JIT_SCRATCH_STRING_CAP_OFFSET: i32 =
std::mem::offset_of!(JitScratch, string_scratch_cap) as i32;
pub trait JitFormat: Default + Copy + 'static {
fn register_helpers(builder: &mut cranelift_jit::JITBuilder);
fn helper_seq_begin() -> Option<&'static str> {
None
}
fn helper_seq_is_end() -> Option<&'static str> {
None
}
fn helper_seq_next() -> Option<&'static str> {
None
}
fn helper_parse_bool() -> Option<&'static str> {
None
}
fn helper_parse_i64() -> Option<&'static str> {
None
}
fn helper_parse_u64() -> Option<&'static str> {
None
}
fn helper_parse_f64() -> Option<&'static str> {
None
}
fn helper_parse_string() -> Option<&'static str> {
None
}
const SEQ_STATE_SIZE: u32 = 0;
const SEQ_STATE_ALIGN: u32 = 1;
const PROVIDES_SEQ_COUNT: bool = false;
const MAP_STATE_SIZE: u32 = 0;
const MAP_STATE_ALIGN: u32 = 1;
const STRUCT_ENCODING: StructEncoding = StructEncoding::Map;
fn emit_skip_ws(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> Value;
fn emit_skip_value(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> Value;
fn emit_peek_null(&self, b: &mut FunctionBuilder, c: &mut JitCursor) -> (Value, Value);
fn emit_consume_null(&self, b: &mut FunctionBuilder, c: &mut JitCursor) -> Value;
fn emit_parse_bool(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (Value, Value);
fn emit_parse_u8(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (Value, Value);
fn emit_parse_i8(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (Value, Value) {
let (u8_val, err) = self.emit_parse_u8(_module, b, c);
(u8_val, err)
}
fn emit_parse_i64(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (Value, Value);
fn emit_parse_u64(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (Value, Value);
fn emit_parse_f32(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (Value, Value) {
let (f64_val, err) = self.emit_parse_f64(module, b, c);
let f32_val = b.ins().fdemote(types::F32, f64_val);
(f32_val, err)
}
fn emit_parse_f64(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (Value, Value);
fn emit_parse_string(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (JitStringValue, Value);
fn emit_seq_begin(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
state_ptr: Value,
) -> (Value, Value);
fn emit_seq_is_end(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
state_ptr: Value,
) -> (Value, Value);
fn emit_seq_next(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
state_ptr: Value,
) -> Value;
fn emit_seq_bulk_copy_u8(
&self,
_b: &mut FunctionBuilder,
_c: &mut JitCursor,
_count: Value,
_dest_ptr: Value,
) -> Option<Value> {
None
}
fn emit_try_empty_seq(
&self,
_b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> Option<(Value, Value)> {
None
}
fn emit_try_empty_map(
&self,
_b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> Option<(Value, Value)> {
None
}
fn emit_map_begin(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
state_ptr: Value,
) -> Value;
fn emit_map_is_end(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
state_ptr: Value,
) -> (Value, Value);
fn emit_map_read_key(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
state_ptr: Value,
) -> (JitStringValue, Value);
fn emit_map_kv_sep(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
state_ptr: Value,
) -> Value;
fn emit_map_next(
&self,
module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
state_ptr: Value,
) -> Value;
fn emit_key_normalize(&self, _b: &mut FunctionBuilder, _key: &mut JitStringValue) {}
}
#[derive(Default, Clone, Copy)]
pub struct NoFormatJit;
impl JitFormat for NoFormatJit {
fn register_helpers(_builder: &mut cranelift_jit::JITBuilder) {}
fn emit_skip_ws(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> Value {
b.ins().iconst(types::I32, -1)
}
fn emit_skip_value(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> Value {
b.ins().iconst(types::I32, -1)
}
fn emit_peek_null(&self, b: &mut FunctionBuilder, _c: &mut JitCursor) -> (Value, Value) {
let zero = b.ins().iconst(types::I8, 0);
let err = b.ins().iconst(types::I32, -1);
(zero, err)
}
fn emit_consume_null(&self, b: &mut FunctionBuilder, _c: &mut JitCursor) -> Value {
b.ins().iconst(types::I32, -1)
}
fn emit_parse_bool(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> (Value, Value) {
let zero = b.ins().iconst(types::I8, 0);
let err = b.ins().iconst(types::I32, -1);
(zero, err)
}
fn emit_parse_u8(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> (Value, Value) {
let zero = b.ins().iconst(types::I8, 0);
let err = b.ins().iconst(types::I32, -1);
(zero, err)
}
fn emit_parse_i64(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> (Value, Value) {
let zero = b.ins().iconst(types::I64, 0);
let err = b.ins().iconst(types::I32, -1);
(zero, err)
}
fn emit_parse_u64(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> (Value, Value) {
let zero = b.ins().iconst(types::I64, 0);
let err = b.ins().iconst(types::I32, -1);
(zero, err)
}
fn emit_parse_f64(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
) -> (Value, Value) {
let zero = b.ins().f64const(0.0);
let err = b.ins().iconst(types::I32, -1);
(zero, err)
}
fn emit_parse_string(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
) -> (JitStringValue, Value) {
let null = b.ins().iconst(c.ptr_type, 0);
let zero = b.ins().iconst(c.ptr_type, 0);
let err = b.ins().iconst(types::I32, -1);
(
JitStringValue {
ptr: null,
len: zero,
cap: zero,
owned: b.ins().iconst(types::I8, 0),
},
err,
)
}
fn emit_seq_begin(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
_state_ptr: Value,
) -> (Value, Value) {
let zero_count = b.ins().iconst(c.ptr_type, 0);
let err = b.ins().iconst(types::I32, -1);
(zero_count, err)
}
fn emit_seq_is_end(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
_state_ptr: Value,
) -> (Value, Value) {
let zero = b.ins().iconst(types::I8, 0);
let err = b.ins().iconst(types::I32, -1);
(zero, err)
}
fn emit_seq_next(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
_state_ptr: Value,
) -> Value {
b.ins().iconst(types::I32, -1)
}
fn emit_map_begin(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
_state_ptr: Value,
) -> Value {
b.ins().iconst(types::I32, -1)
}
fn emit_map_is_end(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
_state_ptr: Value,
) -> (Value, Value) {
let zero = b.ins().iconst(types::I8, 0);
let err = b.ins().iconst(types::I32, -1);
(zero, err)
}
fn emit_map_read_key(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
c: &mut JitCursor,
_state_ptr: Value,
) -> (JitStringValue, Value) {
let null = b.ins().iconst(c.ptr_type, 0);
let zero = b.ins().iconst(c.ptr_type, 0);
let err = b.ins().iconst(types::I32, -1);
(
JitStringValue {
ptr: null,
len: zero,
cap: zero,
owned: b.ins().iconst(types::I8, 0),
},
err,
)
}
fn emit_map_kv_sep(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
_state_ptr: Value,
) -> Value {
b.ins().iconst(types::I32, -1)
}
fn emit_map_next(
&self,
_module: &mut cranelift_jit::JITModule,
b: &mut FunctionBuilder,
_c: &mut JitCursor,
_state_ptr: Value,
) -> Value {
b.ins().iconst(types::I32, -1)
}
}
#[inline]
pub const fn c_call_conv() -> cranelift::codegen::isa::CallConv {
#[cfg(all(target_os = "windows", target_arch = "x86_64"))]
{
cranelift::codegen::isa::CallConv::WindowsFastcall
}
#[cfg(not(all(target_os = "windows", target_arch = "x86_64")))]
{
#[cfg(target_arch = "x86_64")]
{
cranelift::codegen::isa::CallConv::SystemV
}
#[cfg(target_arch = "aarch64")]
{
cranelift::codegen::isa::CallConv::AppleAarch64
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
{
cranelift::codegen::isa::CallConv::Fast
}
}
}
#[inline]
pub fn make_c_sig(module: &cranelift_jit::JITModule) -> cranelift::codegen::ir::Signature {
let mut sig = module.make_signature();
sig.call_conv = c_call_conv();
sig
}