use super::*;
use wasm_encoder::{BlockType, Ieee64};
pub(super) struct HostImport {
pub(super) module: &'static str,
pub(super) name: &'static str,
pub(super) arity: usize,
}
pub(super) const HOST_IMPORTS: &[HostImport] = &[
HostImport {
module: "math",
name: "pow",
arity: 2,
},
HostImport {
module: "math",
name: "sin",
arity: 1,
},
HostImport {
module: "math",
name: "cos",
arity: 1,
},
HostImport {
module: "io",
name: "log_value",
arity: 1,
},
HostImport {
module: "io",
name: "log_str",
arity: 1,
},
HostImport {
module: "io",
name: "read_file_str",
arity: 1,
},
HostImport {
module: "io",
name: "file_exists",
arity: 1,
},
HostImport {
module: "io",
name: "parse_json",
arity: 1,
},
HostImport {
module: "io",
name: "current_time",
arity: 0,
},
HostImport {
module: "io",
name: "get_env",
arity: 1,
},
];
pub(super) const MAX_CANONICAL_ARITY: u32 = 8;
pub(super) fn build_wasm_module(
fns: &[CompiledFn],
heap_start: i32,
string_data: &[u8],
atom_initial_values: &[f64],
runtime_fn_count: u32,
) -> Result<Vec<u8>, String> {
let mut module = Module::new();
let num_imports = HOST_IMPORTS.len() as u32;
let user_fn_count = fns.len() as u32 - runtime_fn_count;
let mut types = TypeSection::new();
for arity in 0..MAX_CANONICAL_ARITY {
types.ty().function(vec![ValType::F64; arity as usize], vec![ValType::F64]);
}
for imp in HOST_IMPORTS {
let params: Vec<ValType> = vec![ValType::F64; imp.arity];
types.ty().function(params, vec![ValType::F64]);
}
for f in fns {
types.ty().function(f.params.clone(), f.results.clone());
}
module.section(&types);
let mut imports = wasm_encoder::ImportSection::new();
for (i, imp) in HOST_IMPORTS.iter().enumerate() {
imports.import(
imp.module,
imp.name,
wasm_encoder::EntityType::Function(MAX_CANONICAL_ARITY + i as u32),
);
}
module.section(&imports);
let mut functions = FunctionSection::new();
for (i, _) in fns.iter().enumerate() {
functions.function(MAX_CANONICAL_ARITY + num_imports + i as u32);
}
module.section(&functions);
let mut tables = TableSection::new();
tables.table(TableType {
element_type: RefType::FUNCREF,
minimum: user_fn_count as u64,
maximum: Some(user_fn_count as u64),
table64: false,
shared: false,
});
module.section(&tables);
let mut memories = MemorySection::new();
memories.memory(MemoryType {
minimum: 100,
maximum: None,
memory64: false,
shared: false,
page_size_log2: None,
});
module.section(&memories);
let mut globals = GlobalSection::new();
globals.global(
GlobalType {
val_type: ValType::I32,
mutable: true,
shared: false,
},
&ConstExpr::i32_const(heap_start),
);
for &init_val in atom_initial_values {
globals.global(
GlobalType {
val_type: ValType::F64,
mutable: true,
shared: false,
},
&ConstExpr::f64_const(init_val.into()),
);
}
module.section(&globals);
let mut exports = ExportSection::new();
exports.export("memory", ExportKind::Memory, 0);
exports.export("__heap_ptr", ExportKind::Global, HEAP_PTR_GLOBAL);
for (i, f) in fns.iter().enumerate() {
if let Some(export_name) = &f.export_name {
exports.export(export_name, ExportKind::Func, num_imports + i as u32);
}
}
module.section(&exports);
if user_fn_count > 0 {
let fn_indices: Vec<u32> = (0..user_fn_count).map(|i| num_imports + runtime_fn_count + i).collect();
let mut elements = ElementSection::new();
elements.active(Some(0), &ConstExpr::i32_const(0), Elements::Functions(fn_indices.as_slice().into()));
module.section(&elements);
}
let mut codes = CodeSection::new();
for f in fns {
let locals: Vec<(u32, ValType)> = if f.locals.is_empty() {
vec![]
} else {
let mut groups = Vec::new();
let mut count = 1u32;
let mut prev = f.locals[0];
for &t in &f.locals[1..] {
if t == prev {
count += 1;
} else {
groups.push((count, prev));
prev = t;
count = 1;
}
}
groups.push((count, prev));
groups
};
let mut func = Function::new(locals);
for instr in &f.instructions {
func.instruction(instr);
}
func.instruction(&Instruction::End);
codes.function(&func);
}
module.section(&codes);
if !string_data.is_empty() {
let mut data = wasm_encoder::DataSection::new();
data.active(0, &ConstExpr::i32_const(HEAP_BASE), string_data.iter().copied());
module.section(&data);
}
Ok(module.finish())
}
pub(super) fn build_runtime_fns(
base_index: u32,
map_tag: i32,
list_tag: i32,
string_tag: i32,
) -> (Vec<CompiledFn>, HashMap<String, u32>) {
let mut fn_index = HashMap::new();
let mut fns = Vec::new();
let copy_name = String::from("__rt_copy_f64_slots");
fn_index.insert(copy_name.clone(), base_index + fns.len() as u32);
let i_local = 3u32;
let copy_instructions = vec![
Instruction::I32Const(0),
Instruction::LocalSet(i_local),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(i_local),
Instruction::LocalGet(2),
Instruction::I32GeU,
Instruction::BrIf(1),
Instruction::LocalGet(0),
Instruction::LocalGet(i_local),
Instruction::I32Const(8),
Instruction::I32Mul,
Instruction::I32Add,
Instruction::LocalGet(1),
Instruction::LocalGet(i_local),
Instruction::I32Const(8),
Instruction::I32Mul,
Instruction::I32Add,
Instruction::F64Load(mem_arg_f64(0)),
Instruction::F64Store(mem_arg_f64(0)),
Instruction::LocalGet(i_local),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(i_local),
Instruction::Br(0),
Instruction::End,
Instruction::End,
];
fns.push(CompiledFn {
export_name: None,
params: vec![ValType::I32, ValType::I32, ValType::I32],
results: vec![],
locals: vec![ValType::I32],
instructions: copy_instructions,
});
let map_flat_pairs_name = String::from("__rt_map_flat_pairs");
fn_index.insert(map_flat_pairs_name, base_index + fns.len() as u32);
let map_flat_pairs_instructions = vec![
Instruction::LocalGet(0),
Instruction::F64Load(mem_arg_f64(8)),
Instruction::I32TruncF64U,
];
fns.push(CompiledFn {
export_name: None,
params: vec![ValType::I32],
results: vec![ValType::I32],
locals: vec![],
instructions: map_flat_pairs_instructions,
});
let map_find_key_name = String::from("__rt_map_find_key");
fn_index.insert(map_find_key_name, base_index + fns.len() as u32);
let map_find_key_instructions = vec![
Instruction::LocalGet(0),
Instruction::F64Load(mem_arg_f64(8)),
Instruction::I32TruncF64U,
Instruction::LocalSet(5),
Instruction::LocalGet(5),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(2),
Instruction::I32Const(-1),
Instruction::LocalSet(4),
Instruction::I32Const(0),
Instruction::LocalSet(3),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(3),
Instruction::LocalGet(2),
Instruction::I32GeU,
Instruction::BrIf(1),
Instruction::LocalGet(5),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalGet(3),
Instruction::I32Const(16),
Instruction::I32Mul,
Instruction::I32Add,
Instruction::F64Load(mem_arg_f64(0)),
Instruction::LocalGet(1),
Instruction::F64Eq,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(3),
Instruction::LocalSet(4),
Instruction::Br(2),
Instruction::End,
Instruction::LocalGet(3),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(3),
Instruction::Br(0),
Instruction::End,
Instruction::End,
Instruction::LocalGet(4),
];
fns.push(CompiledFn {
export_name: None,
params: vec![ValType::I32, ValType::F64],
results: vec![ValType::I32],
locals: vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
instructions: map_find_key_instructions,
});
let map_find_value_name = String::from("__rt_map_find_value");
fn_index.insert(map_find_value_name, base_index + fns.len() as u32);
let map_find_value_instructions = vec![
Instruction::LocalGet(0),
Instruction::F64Load(mem_arg_f64(8)),
Instruction::I32TruncF64U,
Instruction::LocalSet(5),
Instruction::LocalGet(5),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(2),
Instruction::I32Const(-1),
Instruction::LocalSet(4),
Instruction::I32Const(0),
Instruction::LocalSet(3),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(3),
Instruction::LocalGet(2),
Instruction::I32GeU,
Instruction::BrIf(1),
Instruction::LocalGet(5),
Instruction::I32Const(16),
Instruction::I32Add,
Instruction::LocalGet(3),
Instruction::I32Const(16),
Instruction::I32Mul,
Instruction::I32Add,
Instruction::F64Load(mem_arg_f64(0)),
Instruction::LocalGet(1),
Instruction::F64Eq,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(3),
Instruction::LocalSet(4),
Instruction::Br(2),
Instruction::End,
Instruction::LocalGet(3),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(3),
Instruction::Br(0),
Instruction::End,
Instruction::End,
Instruction::LocalGet(4),
];
fns.push(CompiledFn {
export_name: None,
params: vec![ValType::I32, ValType::F64],
results: vec![ValType::I32],
locals: vec![ValType::I32, ValType::I32, ValType::I32, ValType::I32],
instructions: map_find_value_instructions,
});
let set_find_name = String::from("__rt_set_find_elem");
fn_index.insert(set_find_name, base_index + fns.len() as u32);
let set_find_instructions = vec![
Instruction::LocalGet(0),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(2),
Instruction::I32Const(-1),
Instruction::LocalSet(4),
Instruction::I32Const(0),
Instruction::LocalSet(3),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(3),
Instruction::LocalGet(2),
Instruction::I32GeU,
Instruction::BrIf(1),
Instruction::LocalGet(0),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalGet(3),
Instruction::I32Const(8),
Instruction::I32Mul,
Instruction::I32Add,
Instruction::F64Load(mem_arg_f64(0)),
Instruction::LocalGet(1),
Instruction::F64Eq,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(3),
Instruction::LocalSet(4),
Instruction::Br(2),
Instruction::End,
Instruction::LocalGet(3),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(3),
Instruction::Br(0),
Instruction::End,
Instruction::End,
Instruction::LocalGet(4),
];
fns.push(CompiledFn {
export_name: None,
params: vec![ValType::I32, ValType::F64],
results: vec![ValType::I32],
locals: vec![ValType::I32, ValType::I32, ValType::I32],
instructions: set_find_instructions,
});
let hash_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_hash_f64"), hash_idx);
fns.push(build_rt_hash_f64());
let hash_list_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_hash_list_or_set"), hash_list_idx);
fns.push(build_rt_hash_list_or_set(hash_idx));
let map_root_assoc_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_root_assoc"), map_root_assoc_idx);
fns.push(build_rt_map_root_assoc(*fn_index.get("__rt_copy_f64_slots").expect("copy helper")));
let map_root_lookup_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_root_lookup"), map_root_lookup_idx);
fns.push(build_rt_map_root_lookup());
let map_root_contains_value_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_root_contains_value"), map_root_contains_value_idx);
fns.push(build_rt_map_root_contains_value());
let map_root_write_pairs_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_root_write_pairs"), map_root_write_pairs_idx);
fns.push(build_rt_map_root_write_pairs());
let map_make_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_make"), map_make_idx);
fns.push(build_rt_map_make(map_tag));
let map_from_flat_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_from_flat"), map_from_flat_idx);
fns.push(build_rt_map_from_flat(hash_idx, map_root_assoc_idx, map_make_idx));
let map_root_from_flat_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_root_from_flat"), map_root_from_flat_idx);
fns.push(build_rt_map_root_from_flat(hash_idx, map_root_assoc_idx));
let map_linearize_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_linearize"), map_linearize_idx);
fns.push(build_rt_map_linearize(map_root_write_pairs_idx, list_tag));
let map_assoc_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_assoc"), map_assoc_idx);
fns.push(build_rt_map_assoc(hash_idx, map_root_assoc_idx, map_make_idx));
let map_get_value_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_get_value"), map_get_value_idx);
fns.push(build_rt_map_get_value(hash_idx, map_root_lookup_idx));
let map_contains_key_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_contains_key"), map_contains_key_idx);
fns.push(build_rt_map_contains_key(hash_idx, map_root_lookup_idx));
let map_contains_value_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_contains_value"), map_contains_value_idx);
fns.push(build_rt_map_contains_value(map_root_contains_value_idx));
let map_dissoc_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_dissoc"), map_dissoc_idx);
fns.push(build_rt_map_dissoc(
*fn_index.get("__rt_copy_f64_slots").expect("copy helper"),
map_linearize_idx,
map_from_flat_idx,
));
let str_compare_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_str_compare"), str_compare_idx);
fns.push(build_rt_str_compare());
let str_find_index_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_str_find_index"), str_find_index_idx);
fns.push(build_rt_str_find_index());
let str_starts_with_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_str_starts_with"), str_starts_with_idx);
fns.push(build_rt_str_starts_with());
let str_ends_with_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_str_ends_with"), str_ends_with_idx);
fns.push(build_rt_str_ends_with());
let f64_to_str_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_f64_to_str"), f64_to_str_idx);
fns.push(build_rt_f64_to_str(string_tag));
let display_by_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_display_by"), display_by_idx);
fns.push(build_rt_display_by(string_tag));
let trim_ws_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_trim_ws"), trim_ws_idx);
fns.push(build_rt_trim_ws(string_tag));
let trim_char_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_trim_char"), trim_char_idx);
fns.push(build_rt_trim_char(string_tag));
let blank_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_blank"), blank_idx);
fns.push(build_rt_blank());
let parse_float_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_parse_float"), parse_float_idx);
fns.push(build_rt_parse_float());
let char_from_code_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_char_from_code"), char_from_code_idx);
fns.push(build_rt_char_from_code(string_tag));
let str_replace_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_str_replace"), str_replace_idx);
fns.push(build_rt_str_replace(string_tag));
let str_escape_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_str_escape"), str_escape_idx);
fns.push(build_rt_str_escape(string_tag));
let map_equal_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_map_equal"), map_equal_idx);
fns.push(build_rt_map_equal(map_linearize_idx, map_get_value_idx));
let str_find_from_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_str_find_from"), str_find_from_idx);
fns.push(build_rt_str_find_from());
let utf8_char_len_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_utf8_char_len"), utf8_char_len_idx);
fns.push(build_rt_utf8_char_len());
let str_split_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_str_split"), str_split_idx);
fns.push(build_rt_str_split(string_tag, list_tag, str_find_from_idx, utf8_char_len_idx));
let value_equal_idx = base_index + fns.len() as u32;
fn_index.insert(String::from("__rt_value_equal"), value_equal_idx);
fns.push(build_rt_value_equal(string_tag, list_tag, str_compare_idx, value_equal_idx));
(fns, fn_index)
}
const RT_MAP_TABLE_KIND: f64 = 0.0;
const RT_MAP_BUCKET_KIND: f64 = 1.0;
const RT_MAP_TABLE_CHILDREN: i32 = 32;
const RT_MAP_TABLE_SLOTS: i32 = 33; const RT_MAP_TABLE_BYTES: i32 = RT_MAP_TABLE_SLOTS * 8;
struct RuntimeFnBuilder {
locals: Vec<ValType>,
next_local: u32,
instructions: Vec<Instruction<'static>>,
}
impl RuntimeFnBuilder {
fn new(param_count: u32) -> Self {
Self {
locals: Vec::new(),
next_local: param_count,
instructions: Vec::new(),
}
}
fn alloc_i32(&mut self) -> u32 {
let idx = self.next_local;
self.next_local += 1;
self.locals.push(ValType::I32);
idx
}
fn alloc_f64(&mut self) -> u32 {
let idx = self.next_local;
self.next_local += 1;
self.locals.push(ValType::F64);
idx
}
fn emit(&mut self, instr: Instruction<'static>) {
self.instructions.push(instr);
}
fn finish(self, params: Vec<ValType>, results: Vec<ValType>) -> CompiledFn {
CompiledFn {
export_name: None,
params,
results,
locals: self.locals,
instructions: self.instructions,
}
}
}
fn rt_emit_alloc_const(builder: &mut RuntimeFnBuilder, byte_size: i32, dst_local: u32, type_tag: i32) {
let raw = builder.alloc_i32();
builder.emit(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
builder.emit(Instruction::LocalTee(raw));
builder.emit(Instruction::I32Const(HEAP_MAGIC));
builder.emit(Instruction::I32Store(mem_arg_i32(0)));
builder.emit(Instruction::LocalGet(raw));
builder.emit(Instruction::I32Const(4));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::I32Const(type_tag));
builder.emit(Instruction::I32Store(mem_arg_i32(0)));
builder.emit(Instruction::LocalGet(raw));
builder.emit(Instruction::I32Const(8));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::LocalSet(dst_local));
builder.emit(Instruction::LocalGet(raw));
builder.emit(Instruction::I32Const(byte_size + 8));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
}
fn rt_emit_alloc_dynamic(builder: &mut RuntimeFnBuilder, size_local: u32, dst_local: u32, type_tag: i32) {
let raw = builder.alloc_i32();
builder.emit(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
builder.emit(Instruction::LocalTee(raw));
builder.emit(Instruction::I32Const(HEAP_MAGIC));
builder.emit(Instruction::I32Store(mem_arg_i32(0)));
builder.emit(Instruction::LocalGet(raw));
builder.emit(Instruction::I32Const(4));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::I32Const(type_tag));
builder.emit(Instruction::I32Store(mem_arg_i32(0)));
builder.emit(Instruction::LocalGet(raw));
builder.emit(Instruction::I32Const(8));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::LocalSet(dst_local));
builder.emit(Instruction::LocalGet(raw));
builder.emit(Instruction::I32Const(8));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::LocalGet(size_local));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
}
fn rt_emit_table_child_addr(builder: &mut RuntimeFnBuilder, table_local: u32, child_idx_local: u32, dst_local: u32) {
builder.emit(Instruction::LocalGet(table_local));
builder.emit(Instruction::I32Const(8));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::LocalGet(child_idx_local));
builder.emit(Instruction::I32Const(8));
builder.emit(Instruction::I32Mul);
builder.emit(Instruction::I32Add);
builder.emit(Instruction::LocalSet(dst_local));
}
fn rt_emit_load_table_child(builder: &mut RuntimeFnBuilder, table_local: u32, child_idx_local: u32, dst_local: u32) {
builder.emit(Instruction::LocalGet(table_local));
builder.emit(Instruction::I32Const(8));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::LocalGet(child_idx_local));
builder.emit(Instruction::I32Const(8));
builder.emit(Instruction::I32Mul);
builder.emit(Instruction::I32Add);
builder.emit(Instruction::F64Load(mem_arg_f64(0)));
builder.emit(Instruction::I32TruncF64U);
builder.emit(Instruction::LocalSet(dst_local));
}
fn rt_emit_alloc_empty_table(builder: &mut RuntimeFnBuilder, dst_local: u32) {
rt_emit_alloc_const(builder, RT_MAP_TABLE_BYTES, dst_local, 0);
builder.emit(Instruction::LocalGet(dst_local));
builder.emit(f64_const(RT_MAP_TABLE_KIND));
builder.emit(Instruction::F64Store(mem_arg_f64(0)));
let i = builder.alloc_i32();
let addr = builder.alloc_i32();
builder.emit(Instruction::I32Const(0));
builder.emit(Instruction::LocalSet(i));
builder.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
builder.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
builder.emit(Instruction::LocalGet(i));
builder.emit(Instruction::I32Const(RT_MAP_TABLE_CHILDREN));
builder.emit(Instruction::I32GeU);
builder.emit(Instruction::BrIf(1));
rt_emit_table_child_addr(builder, dst_local, i, addr);
builder.emit(Instruction::LocalGet(addr));
builder.emit(f64_const(0.0));
builder.emit(Instruction::F64Store(mem_arg_f64(0)));
builder.emit(Instruction::LocalGet(i));
builder.emit(Instruction::I32Const(1));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::LocalSet(i));
builder.emit(Instruction::Br(0));
builder.emit(Instruction::End);
builder.emit(Instruction::End);
}
fn rt_emit_alloc_bucket(builder: &mut RuntimeFnBuilder, count_local: u32, dst_local: u32) {
let slots = builder.alloc_i32();
let size = builder.alloc_i32();
builder.emit(Instruction::LocalGet(count_local));
builder.emit(Instruction::I32Const(2));
builder.emit(Instruction::I32Mul);
builder.emit(Instruction::I32Const(2));
builder.emit(Instruction::I32Add);
builder.emit(Instruction::LocalSet(slots));
builder.emit(Instruction::LocalGet(slots));
builder.emit(Instruction::I32Const(8));
builder.emit(Instruction::I32Mul);
builder.emit(Instruction::LocalSet(size));
rt_emit_alloc_dynamic(builder, size, dst_local, 0);
builder.emit(Instruction::LocalGet(dst_local));
builder.emit(f64_const(RT_MAP_BUCKET_KIND));
builder.emit(Instruction::F64Store(mem_arg_f64(0)));
builder.emit(Instruction::LocalGet(dst_local));
builder.emit(Instruction::LocalGet(count_local));
builder.emit(Instruction::F64ConvertI32U);
builder.emit(Instruction::F64Store(mem_arg_f64(8)));
}
fn rt_emit_copy_slots(builder: &mut RuntimeFnBuilder, copy_fn_idx: u32, dst_local: u32, src_local: u32, count_local: u32) {
builder.emit(Instruction::LocalGet(dst_local));
builder.emit(Instruction::LocalGet(src_local));
builder.emit(Instruction::LocalGet(count_local));
builder.emit(Instruction::Call(copy_fn_idx));
}
fn build_rt_hash_list_or_set(hash_f64_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(1); let count = b.alloc_i32();
let i = b.alloc_i32();
let acc = b.alloc_i32();
let elem_addr = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(acc));
b.emit(Instruction::Block(BlockType::Empty));
b.emit(Instruction::Loop(BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1)); b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(3)); b.emit(Instruction::I32Shl);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(elem_addr));
b.emit(Instruction::LocalGet(acc));
b.emit(Instruction::LocalGet(elem_addr));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::Call(hash_f64_idx));
b.emit(Instruction::I32Xor);
b.emit(Instruction::LocalSet(acc));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0)); b.emit(Instruction::End); b.emit(Instruction::End); b.emit(Instruction::LocalGet(acc));
b.finish(vec![ValType::I32], vec![ValType::I32])
}
fn build_rt_hash_f64() -> CompiledFn {
let mut b = RuntimeFnBuilder::new(1);
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I64ReinterpretF64);
b.emit(Instruction::I64Const(32));
b.emit(Instruction::I64ShrU);
b.emit(Instruction::I32WrapI64);
b.emit(Instruction::I32Const(0x9e37_79b9u32 as i32));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Rotl);
b.finish(vec![ValType::F64], vec![ValType::I32])
}
fn build_rt_map_make(map_tag: i32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2);
let dst = b.alloc_i32();
rt_emit_alloc_const(&mut b, 16, dst, map_tag);
b.emit(Instruction::LocalGet(dst));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(dst));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(8)));
b.emit(Instruction::LocalGet(dst));
b.finish(vec![ValType::I32, ValType::I32], vec![ValType::I32])
}
fn build_rt_map_root_assoc(copy_fn_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(4); let idx0 = b.alloc_i32();
let idx1 = b.alloc_i32();
let table1 = b.alloc_i32();
let bucket = b.alloc_i32();
let new_root = b.alloc_i32();
let new_table1 = b.alloc_i32();
let new_bucket = b.alloc_i32();
let bucket_count = b.alloc_i32();
let found_idx = b.alloc_i32();
let i = b.alloc_i32();
let slots = b.alloc_i32();
let addr = b.alloc_i32();
let added = b.alloc_i32();
let key_addr = b.alloc_i32();
b.emit(Instruction::LocalGet(3));
b.emit(Instruction::I32Const(31));
b.emit(Instruction::I32And);
b.emit(Instruction::LocalSet(idx0));
b.emit(Instruction::LocalGet(3));
b.emit(Instruction::I32Const(5));
b.emit(Instruction::I32ShrU);
b.emit(Instruction::I32Const(31));
b.emit(Instruction::I32And);
b.emit(Instruction::LocalSet(idx1));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
rt_emit_alloc_empty_table(&mut b, new_root);
rt_emit_alloc_empty_table(&mut b, new_table1);
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(bucket_count));
rt_emit_alloc_bucket(&mut b, bucket_count, new_bucket);
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Store(mem_arg_f64(16)));
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::F64Store(mem_arg_f64(24)));
rt_emit_table_child_addr(&mut b, new_table1, idx1, addr);
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
rt_emit_table_child_addr(&mut b, new_root, idx0, addr);
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(new_table1));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(added));
b.emit(Instruction::Else);
rt_emit_load_table_child(&mut b, 0, idx0, table1);
b.emit(Instruction::LocalGet(table1));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
rt_emit_alloc_const(&mut b, RT_MAP_TABLE_BYTES, new_root, 0);
b.emit(Instruction::I32Const(RT_MAP_TABLE_SLOTS));
b.emit(Instruction::LocalSet(slots));
rt_emit_copy_slots(&mut b, copy_fn_idx, new_root, 0, slots);
rt_emit_alloc_empty_table(&mut b, new_table1);
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(bucket_count));
rt_emit_alloc_bucket(&mut b, bucket_count, new_bucket);
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Store(mem_arg_f64(16)));
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::F64Store(mem_arg_f64(24)));
rt_emit_table_child_addr(&mut b, new_table1, idx1, addr);
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
rt_emit_table_child_addr(&mut b, new_root, idx0, addr);
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(new_table1));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(added));
b.emit(Instruction::Else);
rt_emit_load_table_child(&mut b, table1, idx1, bucket);
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
rt_emit_alloc_const(&mut b, RT_MAP_TABLE_BYTES, new_root, 0);
b.emit(Instruction::I32Const(RT_MAP_TABLE_SLOTS));
b.emit(Instruction::LocalSet(slots));
rt_emit_copy_slots(&mut b, copy_fn_idx, new_root, 0, slots);
rt_emit_alloc_const(&mut b, RT_MAP_TABLE_BYTES, new_table1, 0);
b.emit(Instruction::I32Const(RT_MAP_TABLE_SLOTS));
b.emit(Instruction::LocalSet(slots));
rt_emit_copy_slots(&mut b, copy_fn_idx, new_table1, table1, slots);
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(bucket_count));
rt_emit_alloc_bucket(&mut b, bucket_count, new_bucket);
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Store(mem_arg_f64(16)));
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::F64Store(mem_arg_f64(24)));
rt_emit_table_child_addr(&mut b, new_table1, idx1, addr);
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
rt_emit_table_child_addr(&mut b, new_root, idx0, addr);
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(new_table1));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(added));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(bucket_count));
b.emit(Instruction::I32Const(-1));
b.emit(Instruction::LocalSet(found_idx));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(bucket_count));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalTee(key_addr));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalSet(found_idx));
b.emit(Instruction::Br(2));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(found_idx));
b.emit(Instruction::I32Const(-1));
b.emit(Instruction::I32Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(bucket_count));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(slots));
rt_emit_alloc_bucket(&mut b, slots, new_bucket);
b.emit(Instruction::LocalGet(bucket_count));
b.emit(Instruction::I32Const(2));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Const(2));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(slots));
rt_emit_copy_slots(&mut b, copy_fn_idx, new_bucket, bucket, slots);
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::LocalGet(bucket_count));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(8)));
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(bucket_count));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalTee(addr));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::F64Store(mem_arg_f64(8)));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(added));
b.emit(Instruction::Else);
rt_emit_alloc_bucket(&mut b, bucket_count, new_bucket);
b.emit(Instruction::LocalGet(bucket_count));
b.emit(Instruction::I32Const(2));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Const(2));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(slots));
rt_emit_copy_slots(&mut b, copy_fn_idx, new_bucket, bucket, slots);
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::I32Const(24));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(found_idx));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(added));
b.emit(Instruction::End);
rt_emit_alloc_const(&mut b, RT_MAP_TABLE_BYTES, new_root, 0);
b.emit(Instruction::I32Const(RT_MAP_TABLE_SLOTS));
b.emit(Instruction::LocalSet(slots));
rt_emit_copy_slots(&mut b, copy_fn_idx, new_root, 0, slots);
rt_emit_alloc_const(&mut b, RT_MAP_TABLE_BYTES, new_table1, 0);
b.emit(Instruction::I32Const(RT_MAP_TABLE_SLOTS));
b.emit(Instruction::LocalSet(slots));
rt_emit_copy_slots(&mut b, copy_fn_idx, new_table1, table1, slots);
rt_emit_table_child_addr(&mut b, new_table1, idx1, addr);
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(new_bucket));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
rt_emit_table_child_addr(&mut b, new_root, idx0, addr);
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(new_table1));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(new_root));
b.emit(Instruction::LocalGet(added));
b.finish(
vec![ValType::I32, ValType::F64, ValType::F64, ValType::I32],
vec![ValType::I32, ValType::I32],
)
}
fn build_rt_map_root_lookup() -> CompiledFn {
let mut b = RuntimeFnBuilder::new(3); let idx0 = b.alloc_i32();
let idx1 = b.alloc_i32();
let table1 = b.alloc_i32();
let bucket = b.alloc_i32();
let count = b.alloc_i32();
let i = b.alloc_i32();
let found = b.alloc_i32();
let value = b.alloc_f64();
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(found));
b.emit(f64_const(0.0));
b.emit(Instruction::LocalSet(value));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::I32Const(31));
b.emit(Instruction::I32And);
b.emit(Instruction::LocalSet(idx0));
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::I32Const(5));
b.emit(Instruction::I32ShrU);
b.emit(Instruction::I32Const(31));
b.emit(Instruction::I32And);
b.emit(Instruction::LocalSet(idx1));
rt_emit_load_table_child(&mut b, 0, idx0, table1);
b.emit(Instruction::LocalGet(table1));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
rt_emit_load_table_child(&mut b, table1, idx1, bucket);
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(found));
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Const(24));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(value));
b.emit(Instruction::Br(2));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(found));
b.emit(Instruction::LocalGet(value));
b.finish(vec![ValType::I32, ValType::F64, ValType::I32], vec![ValType::I32, ValType::F64])
}
fn build_rt_map_root_contains_value() -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2); let i0 = b.alloc_i32();
let i1 = b.alloc_i32();
let table1 = b.alloc_i32();
let bucket = b.alloc_i32();
let count = b.alloc_i32();
let bi = b.alloc_i32();
let found = b.alloc_i32();
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(found));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i0));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i0));
b.emit(Instruction::I32Const(RT_MAP_TABLE_CHILDREN));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
rt_emit_load_table_child(&mut b, 0, i0, table1);
b.emit(Instruction::LocalGet(table1));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i1));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i1));
b.emit(Instruction::I32Const(RT_MAP_TABLE_CHILDREN));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
rt_emit_load_table_child(&mut b, table1, i1, bucket);
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(bi));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(bi));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Const(24));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(bi));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(found));
b.emit(Instruction::Br(6));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(bi));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(bi));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i1));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i1));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i0));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i0));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(found));
b.finish(vec![ValType::I32, ValType::F64], vec![ValType::I32])
}
fn build_rt_map_root_write_pairs() -> CompiledFn {
let mut b = RuntimeFnBuilder::new(3); let i0 = b.alloc_i32();
let i1 = b.alloc_i32();
let table1 = b.alloc_i32();
let bucket = b.alloc_i32();
let count = b.alloc_i32();
let bi = b.alloc_i32();
let out = b.alloc_i32();
let addr = b.alloc_i32();
let tmp = b.alloc_f64();
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::LocalSet(out));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i0));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i0));
b.emit(Instruction::I32Const(RT_MAP_TABLE_CHILDREN));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
rt_emit_load_table_child(&mut b, 0, i0, table1);
b.emit(Instruction::LocalGet(table1));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i1));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i1));
b.emit(Instruction::I32Const(RT_MAP_TABLE_CHILDREN));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
rt_emit_load_table_child(&mut b, table1, i1, bucket);
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(bi));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(bi));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::LocalGet(out));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(addr));
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(bi));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(tmp));
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(tmp));
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(bucket));
b.emit(Instruction::I32Const(24));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(bi));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(tmp));
b.emit(Instruction::LocalGet(addr));
b.emit(Instruction::LocalGet(tmp));
b.emit(Instruction::F64Store(mem_arg_f64(8)));
b.emit(Instruction::LocalGet(out));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(out));
b.emit(Instruction::LocalGet(bi));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(bi));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i1));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i1));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i0));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i0));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(out));
b.finish(vec![ValType::I32, ValType::I32, ValType::I32], vec![ValType::I32])
}
fn build_rt_map_from_flat(hash_idx: u32, root_assoc_idx: u32, map_make_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(1);
let count = b.alloc_i32();
let i = b.alloc_i32();
let root = b.alloc_i32();
let actual = b.alloc_i32();
let key = b.alloc_f64();
let val = b.alloc_f64();
let hash = b.alloc_i32();
let added = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(actual));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(key));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(val));
b.emit(Instruction::LocalGet(key));
b.emit(Instruction::Call(hash_idx));
b.emit(Instruction::LocalSet(hash));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::LocalGet(key));
b.emit(Instruction::LocalGet(val));
b.emit(Instruction::LocalGet(hash));
b.emit(Instruction::Call(root_assoc_idx));
b.emit(Instruction::LocalSet(added));
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::LocalGet(actual));
b.emit(Instruction::LocalGet(added));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(actual));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(actual));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::Call(map_make_idx));
b.finish(vec![ValType::I32], vec![ValType::I32])
}
fn build_rt_map_root_from_flat(hash_idx: u32, root_assoc_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(1);
let count = b.alloc_i32();
let i = b.alloc_i32();
let root = b.alloc_i32();
let key = b.alloc_f64();
let val = b.alloc_f64();
let hash = b.alloc_i32();
let added = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(key));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(val));
b.emit(Instruction::LocalGet(key));
b.emit(Instruction::Call(hash_idx));
b.emit(Instruction::LocalSet(hash));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::LocalGet(key));
b.emit(Instruction::LocalGet(val));
b.emit(Instruction::LocalGet(hash));
b.emit(Instruction::Call(root_assoc_idx));
b.emit(Instruction::LocalSet(added));
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(root));
b.finish(vec![ValType::I32], vec![ValType::I32])
}
fn build_rt_map_linearize(root_write_pairs_idx: u32, list_tag: i32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(1);
let count = b.alloc_i32();
let root = b.alloc_i32();
let slots = b.alloc_i32();
let size = b.alloc_i32();
let dst = b.alloc_i32();
let base = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32Const(2));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(slots));
b.emit(Instruction::LocalGet(slots));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Mul);
b.emit(Instruction::LocalSet(size));
rt_emit_alloc_dynamic(&mut b, size, dst, list_tag);
b.emit(Instruction::LocalGet(dst));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(dst));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(base));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::LocalGet(base));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::Call(root_write_pairs_idx));
b.emit(Instruction::Drop);
b.emit(Instruction::LocalGet(dst));
b.finish(vec![ValType::I32], vec![ValType::I32])
}
fn build_rt_map_assoc(hash_idx: u32, root_assoc_idx: u32, map_make_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(3);
let count = b.alloc_i32();
let root = b.alloc_i32();
let hash = b.alloc_i32();
let added = b.alloc_i32();
let new_count = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::Call(hash_idx));
b.emit(Instruction::LocalSet(hash));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::LocalGet(hash));
b.emit(Instruction::Call(root_assoc_idx));
b.emit(Instruction::LocalSet(added));
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::LocalGet(added));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(new_count));
b.emit(Instruction::LocalGet(new_count));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::Call(map_make_idx));
b.finish(vec![ValType::I32, ValType::F64, ValType::F64], vec![ValType::I32])
}
fn build_rt_map_get_value(hash_idx: u32, root_lookup_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2);
let root = b.alloc_i32();
let hash = b.alloc_i32();
let found = b.alloc_i32();
let value = b.alloc_f64();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::Call(hash_idx));
b.emit(Instruction::LocalSet(hash));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::LocalGet(hash));
b.emit(Instruction::Call(root_lookup_idx));
b.emit(Instruction::LocalSet(value));
b.emit(Instruction::LocalSet(found));
b.emit(Instruction::LocalGet(value));
b.finish(vec![ValType::I32, ValType::F64], vec![ValType::F64])
}
fn build_rt_map_contains_key(hash_idx: u32, root_lookup_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2);
let root = b.alloc_i32();
let hash = b.alloc_i32();
let found = b.alloc_i32();
let value = b.alloc_f64();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::Call(hash_idx));
b.emit(Instruction::LocalSet(hash));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::LocalGet(hash));
b.emit(Instruction::Call(root_lookup_idx));
b.emit(Instruction::LocalSet(value));
b.emit(Instruction::LocalSet(found));
b.emit(Instruction::LocalGet(found));
b.finish(vec![ValType::I32, ValType::F64], vec![ValType::I32])
}
fn build_rt_map_contains_value(root_contains_value_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2);
let root = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(root));
b.emit(Instruction::LocalGet(root));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::Call(root_contains_value_idx));
b.finish(vec![ValType::I32, ValType::F64], vec![ValType::I32])
}
fn build_rt_map_dissoc(copy_fn_idx: u32, map_linearize_idx: u32, map_from_flat_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2);
let count = b.alloc_i32();
let flat = b.alloc_i32();
let found = b.alloc_i32();
let found_idx = b.alloc_i32();
let i = b.alloc_i32();
let new_count = b.alloc_i32();
let slots = b.alloc_i32();
let size = b.alloc_i32();
let dst = b.alloc_i32();
let before_slots = b.alloc_i32();
let after_slots = b.alloc_i32();
let dst_base = b.alloc_i32();
let src_base = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::Call(map_linearize_idx));
b.emit(Instruction::LocalSet(flat));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(found));
b.emit(Instruction::I32Const(-1));
b.emit(Instruction::LocalSet(found_idx));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(flat));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(found));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalSet(found_idx));
b.emit(Instruction::Br(2));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(found));
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Sub);
b.emit(Instruction::LocalSet(new_count));
b.emit(Instruction::LocalGet(new_count));
b.emit(Instruction::I32Const(2));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(slots));
b.emit(Instruction::LocalGet(slots));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Mul);
b.emit(Instruction::LocalSet(size));
rt_emit_alloc_dynamic(&mut b, size, dst, 0);
b.emit(Instruction::LocalGet(dst));
b.emit(Instruction::LocalGet(new_count));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(found_idx));
b.emit(Instruction::I32Const(2));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(before_slots));
b.emit(Instruction::LocalGet(dst));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(dst_base));
b.emit(Instruction::LocalGet(flat));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(src_base));
rt_emit_copy_slots(&mut b, copy_fn_idx, dst_base, src_base, before_slots);
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::LocalGet(found_idx));
b.emit(Instruction::I32Sub);
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Sub);
b.emit(Instruction::I32Const(2));
b.emit(Instruction::I32Mul);
b.emit(Instruction::LocalSet(after_slots));
b.emit(Instruction::LocalGet(dst));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(found_idx));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(dst_base));
b.emit(Instruction::LocalGet(flat));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(found_idx));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(src_base));
rt_emit_copy_slots(&mut b, copy_fn_idx, dst_base, src_base, after_slots);
b.emit(Instruction::LocalGet(dst));
b.emit(Instruction::Call(map_from_flat_idx));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.finish(vec![ValType::I32, ValType::F64], vec![ValType::I32])
}
fn build_rt_str_compare() -> CompiledFn {
let instructions = vec![
Instruction::LocalGet(0),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(2),
Instruction::LocalGet(1),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(3),
Instruction::LocalGet(2),
Instruction::LocalGet(3),
Instruction::I32LtU,
Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)),
Instruction::LocalGet(2),
Instruction::Else,
Instruction::LocalGet(3),
Instruction::End,
Instruction::LocalSet(4),
Instruction::I32Const(0),
Instruction::LocalSet(5),
Instruction::Block(wasm_encoder::BlockType::Result(ValType::F64)),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(5),
Instruction::LocalGet(4),
Instruction::I32GeU,
Instruction::BrIf(1),
Instruction::LocalGet(0),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalGet(5),
Instruction::I32Add,
Instruction::I32Load8U(mem_arg_byte(0)),
Instruction::LocalSet(6),
Instruction::LocalGet(1),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalGet(5),
Instruction::I32Add,
Instruction::I32Load8U(mem_arg_byte(0)),
Instruction::LocalSet(7),
Instruction::LocalGet(6),
Instruction::LocalGet(7),
Instruction::I32LtU,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(-1.0f64)),
Instruction::Br(3),
Instruction::End,
Instruction::LocalGet(6),
Instruction::LocalGet(7),
Instruction::I32GtU,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(1.0f64)),
Instruction::Br(3),
Instruction::End,
Instruction::LocalGet(5),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(5),
Instruction::Br(0),
Instruction::End, Instruction::End, Instruction::LocalGet(2),
Instruction::LocalGet(3),
Instruction::I32LtU,
Instruction::If(wasm_encoder::BlockType::Result(ValType::F64)),
Instruction::F64Const(Ieee64::from(-1.0f64)),
Instruction::Else,
Instruction::LocalGet(2),
Instruction::LocalGet(3),
Instruction::I32GtU,
Instruction::If(wasm_encoder::BlockType::Result(ValType::F64)),
Instruction::F64Const(Ieee64::from(1.0f64)),
Instruction::Else,
Instruction::F64Const(Ieee64::from(0.0f64)),
Instruction::End,
Instruction::End,
Instruction::End, ];
CompiledFn {
export_name: None,
params: vec![ValType::I32, ValType::I32],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions,
}
}
fn build_rt_str_find_index() -> CompiledFn {
let instructions = vec![
Instruction::LocalGet(0),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(2),
Instruction::LocalGet(1),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(3),
Instruction::LocalGet(0),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalSet(4),
Instruction::LocalGet(1),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalSet(5),
Instruction::Block(wasm_encoder::BlockType::Result(ValType::F64)),
Instruction::LocalGet(3),
Instruction::I32Eqz,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(0.0f64)),
Instruction::Br(1), Instruction::End,
Instruction::LocalGet(3),
Instruction::LocalGet(2),
Instruction::I32GtU,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(-1.0f64)),
Instruction::Br(1), Instruction::End,
Instruction::LocalGet(2),
Instruction::LocalGet(3),
Instruction::I32Sub,
Instruction::LocalSet(8),
Instruction::I32Const(0),
Instruction::LocalSet(6),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(6),
Instruction::LocalGet(8),
Instruction::I32GtU,
Instruction::BrIf(1), Instruction::I32Const(0),
Instruction::LocalSet(7),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(7),
Instruction::LocalGet(3),
Instruction::I32GeU,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(6),
Instruction::F64ConvertI32U,
Instruction::Br(5),
Instruction::End,
Instruction::LocalGet(4),
Instruction::LocalGet(6),
Instruction::I32Add,
Instruction::LocalGet(7),
Instruction::I32Add,
Instruction::I32Load8U(mem_arg_byte(0)),
Instruction::LocalSet(9),
Instruction::LocalGet(5),
Instruction::LocalGet(7),
Instruction::I32Add,
Instruction::I32Load8U(mem_arg_byte(0)),
Instruction::LocalSet(10),
Instruction::LocalGet(9),
Instruction::LocalGet(10),
Instruction::I32Ne,
Instruction::BrIf(1), Instruction::LocalGet(7),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(7),
Instruction::Br(0), Instruction::End, Instruction::End, Instruction::LocalGet(6),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(6),
Instruction::Br(0), Instruction::End, Instruction::End, Instruction::F64Const(Ieee64::from(-1.0f64)),
Instruction::End, ];
CompiledFn {
export_name: None,
params: vec![ValType::I32, ValType::I32],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions,
}
}
fn build_rt_str_starts_with() -> CompiledFn {
let instructions = vec![
Instruction::LocalGet(0),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(2),
Instruction::LocalGet(1),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(3),
Instruction::LocalGet(0),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalSet(4),
Instruction::LocalGet(1),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalSet(5),
Instruction::Block(wasm_encoder::BlockType::Result(ValType::F64)),
Instruction::LocalGet(3),
Instruction::I32Eqz,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(1.0f64)),
Instruction::Br(1), Instruction::End,
Instruction::LocalGet(3),
Instruction::LocalGet(2),
Instruction::I32GtU,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(0.0f64)),
Instruction::Br(1), Instruction::End,
Instruction::I32Const(0),
Instruction::LocalSet(6),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(6),
Instruction::LocalGet(3),
Instruction::I32GeU,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(1.0f64)),
Instruction::Br(3),
Instruction::End,
Instruction::LocalGet(4),
Instruction::LocalGet(6),
Instruction::I32Add,
Instruction::I32Load8U(mem_arg_byte(0)),
Instruction::LocalSet(7),
Instruction::LocalGet(5),
Instruction::LocalGet(6),
Instruction::I32Add,
Instruction::I32Load8U(mem_arg_byte(0)),
Instruction::LocalSet(8),
Instruction::LocalGet(7),
Instruction::LocalGet(8),
Instruction::I32Ne,
Instruction::BrIf(1), Instruction::LocalGet(6),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(6),
Instruction::Br(0), Instruction::End, Instruction::End, Instruction::F64Const(Ieee64::from(0.0f64)),
Instruction::End, ];
CompiledFn {
export_name: None,
params: vec![ValType::I32, ValType::I32],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions,
}
}
fn build_rt_str_ends_with() -> CompiledFn {
let instructions = vec![
Instruction::LocalGet(0),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(2),
Instruction::LocalGet(1),
Instruction::F64Load(mem_arg_f64(0)),
Instruction::I32TruncF64U,
Instruction::LocalSet(3),
Instruction::LocalGet(0),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalSet(4),
Instruction::LocalGet(1),
Instruction::I32Const(8),
Instruction::I32Add,
Instruction::LocalSet(5),
Instruction::Block(wasm_encoder::BlockType::Result(ValType::F64)),
Instruction::LocalGet(3),
Instruction::I32Eqz,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(1.0f64)),
Instruction::Br(1),
Instruction::End,
Instruction::LocalGet(3),
Instruction::LocalGet(2),
Instruction::I32GtU,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(0.0f64)),
Instruction::Br(1),
Instruction::End,
Instruction::LocalGet(2),
Instruction::LocalGet(3),
Instruction::I32Sub,
Instruction::LocalSet(6),
Instruction::I32Const(0),
Instruction::LocalSet(7),
Instruction::Block(wasm_encoder::BlockType::Empty),
Instruction::Loop(wasm_encoder::BlockType::Empty),
Instruction::LocalGet(7),
Instruction::LocalGet(3),
Instruction::I32GeU,
Instruction::If(wasm_encoder::BlockType::Empty),
Instruction::F64Const(Ieee64::from(1.0f64)),
Instruction::Br(3),
Instruction::End,
Instruction::LocalGet(4),
Instruction::LocalGet(6),
Instruction::I32Add,
Instruction::LocalGet(7),
Instruction::I32Add,
Instruction::I32Load8U(mem_arg_byte(0)),
Instruction::LocalSet(8),
Instruction::LocalGet(5),
Instruction::LocalGet(7),
Instruction::I32Add,
Instruction::I32Load8U(mem_arg_byte(0)),
Instruction::LocalSet(9),
Instruction::LocalGet(8),
Instruction::LocalGet(9),
Instruction::I32Ne,
Instruction::BrIf(1),
Instruction::LocalGet(7),
Instruction::I32Const(1),
Instruction::I32Add,
Instruction::LocalSet(7),
Instruction::Br(0), Instruction::End, Instruction::End, Instruction::F64Const(Ieee64::from(0.0f64)),
Instruction::End, ];
CompiledFn {
export_name: None,
params: vec![ValType::I32, ValType::I32],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions,
}
}
fn build_rt_f64_to_str(string_tag: i32) -> CompiledFn {
let mut b = vec![Instruction::LocalGet(0)];
b.push(Instruction::F64Floor);
b.push(Instruction::LocalGet(0));
b.push(Instruction::F64Eq);
b.push(Instruction::If(wasm_encoder::BlockType::Result(wasm_encoder::ValType::F64)));
b.push(Instruction::LocalGet(0));
b.push(Instruction::F64Const(Ieee64::from(0.0f64)));
b.push(Instruction::F64Lt);
b.push(Instruction::LocalSet(2));
b.push(Instruction::LocalGet(0));
b.push(Instruction::I64TruncF64S);
b.push(Instruction::LocalSet(1));
b.push(Instruction::LocalGet(2));
b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::I64Const(0));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I64Sub);
b.push(Instruction::LocalSet(3));
b.push(Instruction::Else);
b.push(Instruction::LocalGet(1));
b.push(Instruction::LocalSet(3));
b.push(Instruction::End);
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(4)); b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalSet(5));
b.push(Instruction::Block(wasm_encoder::BlockType::Empty));
b.push(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I64Const(10));
b.push(Instruction::I64DivU);
b.push(Instruction::LocalSet(5));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I64Eqz);
b.push(Instruction::BrIf(1));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(4)); b.push(Instruction::LocalGet(2)); b.push(Instruction::I32Add);
b.push(Instruction::I32Const(7));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-8i32));
b.push(Instruction::I32And);
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add); b.push(Instruction::LocalSet(6));
b.push(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalTee(11)); b.push(Instruction::I32Const(HEAP_MAGIC));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Const(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(string_tag));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(7)); b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(8)); b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Add);
b.push(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalGet(7));
b.push(Instruction::LocalGet(4)); b.push(Instruction::LocalGet(2)); b.push(Instruction::I32Add); b.push(Instruction::F64ConvertI32U);
b.push(Instruction::F64Store(mem_arg_f64(0)));
b.push(Instruction::LocalGet(2));
b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(8)); b.push(Instruction::I32Const(b'-' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::End);
b.push(Instruction::LocalGet(2)); b.push(Instruction::LocalGet(4)); b.push(Instruction::I32Add);
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(9));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalSet(5));
b.push(Instruction::Block(wasm_encoder::BlockType::Empty));
b.push(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I64Const(10));
b.push(Instruction::I64RemU);
b.push(Instruction::I32WrapI64);
b.push(Instruction::LocalSet(10)); b.push(Instruction::LocalGet(8)); b.push(Instruction::LocalGet(9)); b.push(Instruction::I32Add); b.push(Instruction::LocalGet(10)); b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32Add);
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(9));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(9));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I64Const(10));
b.push(Instruction::I64DivU);
b.push(Instruction::LocalSet(5));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I64Eqz);
b.push(Instruction::BrIf(1));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(7));
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::Else);
b.push(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalTee(11));
b.push(Instruction::I32Const(HEAP_MAGIC));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Const(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(string_tag));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(7)); b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Const(24)); b.push(Instruction::I32Add);
b.push(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalGet(7));
b.push(Instruction::F64Const(Ieee64::from(6.0f64)));
b.push(Instruction::F64Store(mem_arg_f64(0)));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(8));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(b'n' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(b'u' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(1)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(b'm' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(2)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(b'b' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(3)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(b'e' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(4)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(b'r' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(5)));
b.push(Instruction::LocalGet(7));
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::End);
CompiledFn {
export_name: None,
params: vec![ValType::F64],
results: vec![ValType::F64],
locals: vec![
ValType::I64, ValType::I32, ValType::I64, ValType::I32, ValType::I64, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions: b,
}
}
#[allow(clippy::vec_init_then_push)]
fn build_rt_display_by(string_tag: i32) -> CompiledFn {
let mut b: Vec<Instruction> = Vec::new();
b.push(Instruction::LocalGet(1)); b.push(Instruction::I64TruncF64S);
b.push(Instruction::LocalSet(2));
b.push(Instruction::LocalGet(0));
b.push(Instruction::F64Const(Ieee64::from(0.0f64)));
b.push(Instruction::F64Lt);
b.push(Instruction::LocalSet(3));
b.push(Instruction::LocalGet(0));
b.push(Instruction::I64TruncF64S);
b.push(Instruction::LocalSet(5)); b.push(Instruction::LocalGet(3));
b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::I64Const(0));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I64Sub);
b.push(Instruction::LocalSet(4)); b.push(Instruction::Else);
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalSet(4));
b.push(Instruction::End);
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(6)); b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalSet(5));
b.push(Instruction::Block(wasm_encoder::BlockType::Empty));
b.push(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(6)); b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(2)); b.push(Instruction::I64DivU);
b.push(Instruction::LocalSet(5)); b.push(Instruction::LocalGet(5));
b.push(Instruction::I64Eqz);
b.push(Instruction::BrIf(1)); b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(7)); b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Const(Ieee64::from(2.0f64)));
b.push(Instruction::F64Eq);
b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Const(Ieee64::from(8.0f64)));
b.push(Instruction::F64Eq);
b.push(Instruction::I32Or);
b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Const(Ieee64::from(16.0f64)));
b.push(Instruction::F64Eq);
b.push(Instruction::I32Or);
b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::I32Const(2));
b.push(Instruction::LocalSet(7)); b.push(Instruction::End);
b.push(Instruction::LocalGet(3)); b.push(Instruction::LocalGet(7)); b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(6)); b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(8));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(7));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-8i32));
b.push(Instruction::I32And);
b.push(Instruction::LocalSet(9));
b.push(Instruction::I32Const(8));
b.push(Instruction::LocalGet(9));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(16));
b.push(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalTee(14)); b.push(Instruction::I32Const(HEAP_MAGIC));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(14));
b.push(Instruction::I32Const(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(string_tag));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(14));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(10)); b.push(Instruction::LocalGet(10));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(11)); b.push(Instruction::LocalGet(14));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(16));
b.push(Instruction::I32Add);
b.push(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalGet(10));
b.push(Instruction::LocalGet(8)); b.push(Instruction::F64ConvertI32U);
b.push(Instruction::F64Store(mem_arg_f64(0)));
b.push(Instruction::LocalGet(3)); b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Const(b'-' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::End);
b.push(Instruction::LocalGet(3)); b.push(Instruction::LocalSet(12));
b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Const(Ieee64::from(2.0f64)));
b.push(Instruction::F64Eq);
b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(11));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(11));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(b'b' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(2));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(12));
b.push(Instruction::End);
b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Const(Ieee64::from(8.0f64)));
b.push(Instruction::F64Eq);
b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(11));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(11));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(b'o' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(2));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(12));
b.push(Instruction::End);
b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Const(Ieee64::from(16.0f64)));
b.push(Instruction::F64Eq);
b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(11));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(11));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(b'x' as i32));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(2));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(12));
b.push(Instruction::End);
b.push(Instruction::LocalGet(12)); b.push(Instruction::LocalGet(6)); b.push(Instruction::I32Add);
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(12));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalSet(5));
b.push(Instruction::Block(wasm_encoder::BlockType::Empty));
b.push(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(2)); b.push(Instruction::I64RemU);
b.push(Instruction::I32WrapI64);
b.push(Instruction::LocalSet(13)); b.push(Instruction::LocalGet(13));
b.push(Instruction::I32Const(10));
b.push(Instruction::I32LtU);
b.push(Instruction::If(wasm_encoder::BlockType::Empty));
b.push(Instruction::LocalGet(13));
b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(15)); b.push(Instruction::Else);
b.push(Instruction::LocalGet(13));
b.push(Instruction::I32Const(b'a' as i32 - 10));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(15)); b.push(Instruction::End);
b.push(Instruction::LocalGet(11));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(15));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(12));
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I64DivU);
b.push(Instruction::LocalSet(5));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I64Eqz);
b.push(Instruction::BrIf(1));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(10));
b.push(Instruction::F64ConvertI32U);
CompiledFn {
export_name: None,
params: vec![ValType::F64, ValType::F64],
results: vec![ValType::F64],
locals: vec![
ValType::I64, ValType::I32, ValType::I64, ValType::I64, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions: b,
}
}
fn emit_is_ws_check(b: &mut Vec<Instruction<'static>>, loc: u32) {
b.push(Instruction::LocalGet(loc));
b.push(Instruction::I32Const(0x09));
b.push(Instruction::I32Eq);
b.push(Instruction::LocalGet(loc));
b.push(Instruction::I32Const(0x0A));
b.push(Instruction::I32Eq);
b.push(Instruction::I32Or);
b.push(Instruction::LocalGet(loc));
b.push(Instruction::I32Const(0x0D));
b.push(Instruction::I32Eq);
b.push(Instruction::I32Or);
b.push(Instruction::LocalGet(loc));
b.push(Instruction::I32Const(0x20));
b.push(Instruction::I32Eq);
b.push(Instruction::I32Or);
}
#[allow(clippy::vec_init_then_push)]
fn build_rt_trim_ws(str_tag: i32) -> CompiledFn {
let mut b: Vec<Instruction> = Vec::new();
b.push(Instruction::LocalGet(0));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(1));
b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Load(mem_arg_f64(0)));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(2));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(3));
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(4));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32GeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(10));
emit_is_ws_check(&mut b, 10);
b.push(Instruction::I32Eqz);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(2));
b.push(Instruction::LocalSet(5));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32LeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-1i32));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(10));
emit_is_ws_check(&mut b, 10);
b.push(Instruction::I32Eqz);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(5));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(6));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(7));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-8i32));
b.push(Instruction::I32And);
b.push(Instruction::LocalSet(9));
b.push(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalTee(7)); b.push(Instruction::I32Const(HEAP_MAGIC));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Const(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(str_tag));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(8));
b.push(Instruction::LocalGet(8));
b.push(Instruction::LocalGet(6));
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::F64Store(mem_arg_f64(0)));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Const(16));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(9));
b.push(Instruction::I32Add);
b.push(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(6));
b.push(Instruction::MemoryCopy { dst_mem: 0, src_mem: 0 });
b.push(Instruction::LocalGet(8));
b.push(Instruction::F64ConvertI32U);
CompiledFn {
export_name: None,
params: vec![ValType::F64],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions: b,
}
}
#[allow(clippy::vec_init_then_push)]
fn build_rt_trim_char(str_tag: i32) -> CompiledFn {
let mut b: Vec<Instruction> = Vec::new();
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(11));
b.push(Instruction::LocalGet(0));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(2));
b.push(Instruction::LocalGet(2));
b.push(Instruction::F64Load(mem_arg_f64(0)));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(3));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(5));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32GeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(12));
b.push(Instruction::LocalGet(12));
b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Ne);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(5));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalSet(6));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(6));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I32LeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-1i32));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(12));
b.push(Instruction::LocalGet(12));
b.push(Instruction::LocalGet(11));
b.push(Instruction::I32Ne);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(6));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(6));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(7));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Const(7));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-8i32));
b.push(Instruction::I32And);
b.push(Instruction::LocalSet(10));
b.push(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalTee(8));
b.push(Instruction::I32Const(HEAP_MAGIC));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(str_tag));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(9));
b.push(Instruction::LocalGet(9));
b.push(Instruction::LocalGet(7));
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::F64Store(mem_arg_f64(0)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::I32Const(16));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(10));
b.push(Instruction::I32Add);
b.push(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalGet(9));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(5));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(7));
b.push(Instruction::MemoryCopy { dst_mem: 0, src_mem: 0 });
b.push(Instruction::LocalGet(9));
b.push(Instruction::F64ConvertI32U);
CompiledFn {
export_name: None,
params: vec![ValType::F64, ValType::F64],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions: b,
}
}
#[allow(clippy::vec_init_then_push)]
fn build_rt_blank() -> CompiledFn {
let mut b: Vec<Instruction> = Vec::new();
b.push(Instruction::LocalGet(0));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(1));
b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Load(mem_arg_f64(0)));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(2));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(3));
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(4));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32GeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(5));
emit_is_ws_check(&mut b, 5);
b.push(Instruction::I32Eqz);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::F64Const(Ieee64::from(0.0f64)));
b.push(Instruction::Return);
b.push(Instruction::End);
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::F64Const(Ieee64::from(1.0f64)));
CompiledFn {
export_name: None,
params: vec![ValType::F64],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions: b,
}
}
#[allow(clippy::vec_init_then_push)]
fn build_rt_parse_float() -> CompiledFn {
let mut b: Vec<Instruction> = Vec::new();
b.push(Instruction::LocalGet(0));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(1));
b.push(Instruction::LocalGet(1));
b.push(Instruction::F64Load(mem_arg_f64(0)));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(2));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(3));
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(4));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32GeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(6));
emit_is_ws_check(&mut b, 6);
b.push(Instruction::I32Eqz);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(5));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32LtU);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(6));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(b'-' as i32));
b.push(Instruction::I32Eq);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::I32Const(1));
b.push(Instruction::LocalSet(5));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::Else);
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(b'+' as i32));
b.push(Instruction::I32Eq);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::F64Const(Ieee64::from(0.0f64)));
b.push(Instruction::LocalSet(7));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32GeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(6));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32LtU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(b'9' as i32));
b.push(Instruction::I32GtU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(7));
b.push(Instruction::F64Const(Ieee64::from(10.0f64)));
b.push(Instruction::F64Mul);
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32Sub);
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::F64Add);
b.push(Instruction::LocalSet(7));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32LtU);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::I32Const(b'.' as i32));
b.push(Instruction::I32Eq);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::F64Const(Ieee64::from(0.1f64)));
b.push(Instruction::LocalSet(8));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32GeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalSet(6));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32LtU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(b'9' as i32));
b.push(Instruction::I32GtU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(7));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(b'0' as i32));
b.push(Instruction::I32Sub);
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::LocalGet(8));
b.push(Instruction::F64Mul);
b.push(Instruction::F64Add);
b.push(Instruction::LocalSet(7));
b.push(Instruction::LocalGet(8));
b.push(Instruction::F64Const(Ieee64::from(0.1f64)));
b.push(Instruction::F64Mul);
b.push(Instruction::LocalSet(8));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(4));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::End); b.push(Instruction::End);
b.push(Instruction::LocalGet(5));
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::F64Const(Ieee64::from(0.0f64)));
b.push(Instruction::LocalGet(7));
b.push(Instruction::F64Sub);
b.push(Instruction::LocalSet(7));
b.push(Instruction::End);
b.push(Instruction::LocalGet(7));
CompiledFn {
export_name: None,
params: vec![ValType::F64],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::F64, ValType::F64, ],
instructions: b,
}
}
#[allow(clippy::vec_init_then_push)]
fn build_rt_char_from_code(str_tag: i32) -> CompiledFn {
let mut b: Vec<Instruction> = Vec::new();
b.push(Instruction::LocalGet(0));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(1));
b.push(Instruction::I32Const(1));
b.push(Instruction::LocalSet(4));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(0x80));
b.push(Instruction::I32GeU);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::I32Const(2));
b.push(Instruction::LocalSet(4));
b.push(Instruction::End);
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(0x800));
b.push(Instruction::I32GeU);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::I32Const(3));
b.push(Instruction::LocalSet(4));
b.push(Instruction::End);
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(0x10000));
b.push(Instruction::I32GeU);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::I32Const(4));
b.push(Instruction::LocalSet(4));
b.push(Instruction::End);
b.push(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalTee(2)); b.push(Instruction::I32Const(HEAP_MAGIC));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32Const(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(str_tag));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(3));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(4));
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::F64Store(mem_arg_f64(0)));
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32Const(16));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(7));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-8i32));
b.push(Instruction::I32And);
b.push(Instruction::I32Add);
b.push(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Eq);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(3));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Store8(mem_arg_byte(8)));
b.push(Instruction::End);
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(2));
b.push(Instruction::I32Eq);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0xC0));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(6));
b.push(Instruction::I32ShrU);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(8)));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0x80));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(0x3F));
b.push(Instruction::I32And);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(9)));
b.push(Instruction::End);
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(3));
b.push(Instruction::I32Eq);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0xE0));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(12));
b.push(Instruction::I32ShrU);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(8)));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0x80));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(6));
b.push(Instruction::I32ShrU);
b.push(Instruction::I32Const(0x3F));
b.push(Instruction::I32And);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(9)));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0x80));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(0x3F));
b.push(Instruction::I32And);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(10)));
b.push(Instruction::End);
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(4));
b.push(Instruction::I32Eq);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0xF0));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(18));
b.push(Instruction::I32ShrU);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(8)));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0x80));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(12));
b.push(Instruction::I32ShrU);
b.push(Instruction::I32Const(0x3F));
b.push(Instruction::I32And);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(9)));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0x80));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(6));
b.push(Instruction::I32ShrU);
b.push(Instruction::I32Const(0x3F));
b.push(Instruction::I32And);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(10)));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(0x80));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32Const(0x3F));
b.push(Instruction::I32And);
b.push(Instruction::I32Or);
b.push(Instruction::I32Store8(mem_arg_byte(11)));
b.push(Instruction::End);
b.push(Instruction::LocalGet(3));
b.push(Instruction::F64ConvertI32U);
CompiledFn {
export_name: None,
params: vec![ValType::F64],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions: b,
}
}
#[allow(clippy::vec_init_then_push)]
fn build_rt_str_replace(str_tag: i32) -> CompiledFn {
let mut b: Vec<Instruction> = Vec::new();
b.push(Instruction::LocalGet(0));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(3));
b.push(Instruction::LocalGet(3));
b.push(Instruction::F64Load(mem_arg_f64(0)));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(4));
b.push(Instruction::LocalGet(3));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(5));
b.push(Instruction::LocalGet(1));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(6));
b.push(Instruction::LocalGet(6));
b.push(Instruction::F64Load(mem_arg_f64(0)));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(7));
b.push(Instruction::LocalGet(6));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(8));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Eqz);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(3));
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::Return);
b.push(Instruction::End);
b.push(Instruction::LocalGet(2));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(9));
b.push(Instruction::LocalGet(9));
b.push(Instruction::F64Load(mem_arg_f64(0)));
b.push(Instruction::I32TruncF64U);
b.push(Instruction::LocalSet(10));
b.push(Instruction::LocalGet(9));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(11));
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(10));
b.push(Instruction::I32Mul);
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(20));
b.push(Instruction::GlobalGet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalSet(12));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(16));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(13));
b.push(Instruction::LocalGet(20));
b.push(Instruction::I32Const(7));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-8i32));
b.push(Instruction::I32And);
b.push(Instruction::LocalSet(19));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(16));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(19));
b.push(Instruction::I32Add);
b.push(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(14));
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(15));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(15));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(4));
b.push(Instruction::I32GtU);
b.push(Instruction::BrIf(1));
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(16));
b.push(Instruction::I32Const(1));
b.push(Instruction::LocalSet(17));
b.push(Instruction::Block(BlockType::Empty));
b.push(Instruction::Loop(BlockType::Empty));
b.push(Instruction::LocalGet(16));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32GeU);
b.push(Instruction::BrIf(1));
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(15));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(16));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::LocalGet(8));
b.push(Instruction::LocalGet(16));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::I32Ne);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::I32Const(0));
b.push(Instruction::LocalSet(17)); b.push(Instruction::Br(2)); b.push(Instruction::End);
b.push(Instruction::LocalGet(16));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(16));
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(17));
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(13));
b.push(Instruction::LocalGet(14));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(11));
b.push(Instruction::LocalGet(10));
b.push(Instruction::MemoryCopy { dst_mem: 0, src_mem: 0 });
b.push(Instruction::LocalGet(14));
b.push(Instruction::LocalGet(10));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(14)); b.push(Instruction::LocalGet(15));
b.push(Instruction::LocalGet(7));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(15)); b.push(Instruction::Else);
b.push(Instruction::LocalGet(13));
b.push(Instruction::LocalGet(14));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(15));
b.push(Instruction::I32Add);
b.push(Instruction::I32Load8U(mem_arg_byte(0)));
b.push(Instruction::I32Store8(mem_arg_byte(0)));
b.push(Instruction::LocalGet(14));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(14));
b.push(Instruction::LocalGet(15));
b.push(Instruction::I32Const(1));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(15));
b.push(Instruction::End);
b.push(Instruction::Br(0));
b.push(Instruction::End);
b.push(Instruction::End);
b.push(Instruction::LocalGet(4));
b.push(Instruction::LocalGet(15));
b.push(Instruction::I32Sub);
b.push(Instruction::LocalSet(21)); b.push(Instruction::LocalGet(21));
b.push(Instruction::I32Const(0));
b.push(Instruction::I32GtU);
b.push(Instruction::If(BlockType::Empty));
b.push(Instruction::LocalGet(13));
b.push(Instruction::LocalGet(14));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(5));
b.push(Instruction::LocalGet(15));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(21));
b.push(Instruction::MemoryCopy { dst_mem: 0, src_mem: 0 });
b.push(Instruction::LocalGet(14));
b.push(Instruction::LocalGet(21));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(14));
b.push(Instruction::End);
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(HEAP_MAGIC));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(4));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(str_tag));
b.push(Instruction::I32Store(mem_arg_i32(0)));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(8));
b.push(Instruction::I32Add);
b.push(Instruction::LocalSet(18));
b.push(Instruction::LocalGet(18));
b.push(Instruction::LocalGet(14));
b.push(Instruction::F64ConvertI32U);
b.push(Instruction::F64Store(mem_arg_f64(0)));
b.push(Instruction::LocalGet(14));
b.push(Instruction::I32Const(7));
b.push(Instruction::I32Add);
b.push(Instruction::I32Const(-8i32));
b.push(Instruction::I32And);
b.push(Instruction::LocalSet(19));
b.push(Instruction::LocalGet(12));
b.push(Instruction::I32Const(16));
b.push(Instruction::I32Add);
b.push(Instruction::LocalGet(19));
b.push(Instruction::I32Add);
b.push(Instruction::GlobalSet(HEAP_PTR_GLOBAL));
b.push(Instruction::LocalGet(18));
b.push(Instruction::F64ConvertI32U);
CompiledFn {
export_name: None,
params: vec![ValType::F64, ValType::F64, ValType::F64],
results: vec![ValType::F64],
locals: vec![
ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ValType::I32, ],
instructions: b,
}
}
#[allow(clippy::vec_init_then_push)]
fn build_rt_str_escape(_str_tag: i32) -> CompiledFn {
let mut b: Vec<Instruction> = Vec::new();
b.push(Instruction::LocalGet(0));
CompiledFn {
export_name: None,
params: vec![ValType::F64],
results: vec![ValType::F64],
locals: vec![],
instructions: b,
}
}
fn build_rt_map_equal(map_linearize_idx: u32, map_get_value_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2); let count_a = b.alloc_i32();
let count_b = b.alloc_i32();
let flat = b.alloc_i32();
let i = b.alloc_i32();
let key = b.alloc_f64();
let val_a = b.alloc_f64();
let val_b = b.alloc_f64();
let all_eq = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count_a));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(count_b));
b.emit(Instruction::LocalGet(count_a));
b.emit(Instruction::LocalGet(count_b));
b.emit(Instruction::I32Ne);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(count_a));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::Call(map_linearize_idx));
b.emit(Instruction::LocalSet(flat));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(all_eq));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(count_a));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(flat));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(key));
b.emit(Instruction::LocalGet(flat));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(16));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(8)));
b.emit(Instruction::LocalSet(val_a));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::LocalGet(key));
b.emit(Instruction::Call(map_get_value_idx));
b.emit(Instruction::LocalSet(val_b));
b.emit(Instruction::LocalGet(val_a));
b.emit(Instruction::LocalGet(val_b));
b.emit(Instruction::F64Eq);
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(all_eq));
b.emit(Instruction::Br(2)); b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0));
b.emit(Instruction::End); b.emit(Instruction::End);
b.emit(Instruction::LocalGet(all_eq));
b.emit(Instruction::End); b.emit(Instruction::End);
b.finish(vec![ValType::I32, ValType::I32], vec![ValType::I32])
}
fn build_rt_str_find_from() -> CompiledFn {
let mut b = RuntimeFnBuilder::new(3); let h_len = b.alloc_i32();
let p_len = b.alloc_i32();
let h_base = b.alloc_i32();
let p_base = b.alloc_i32();
let i = b.alloc_i32();
let j = b.alloc_i32();
let limit = b.alloc_i32();
let bh = b.alloc_i32();
let bp = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(h_len));
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(p_len));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(h_base));
b.emit(Instruction::LocalGet(2));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(p_base));
b.emit(Instruction::Block(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::LocalGet(p_len));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::Br(1));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::LocalGet(p_len));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(h_len));
b.emit(Instruction::I32GtU);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(-1));
b.emit(Instruction::Br(1));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(h_len));
b.emit(Instruction::LocalGet(p_len));
b.emit(Instruction::I32Sub);
b.emit(Instruction::LocalSet(limit));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty)); b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty)); b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(limit));
b.emit(Instruction::I32GtU);
b.emit(Instruction::BrIf(1)); b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(j));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty)); b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty)); b.emit(Instruction::LocalGet(j));
b.emit(Instruction::LocalGet(p_len));
b.emit(Instruction::I32GeU);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::Br(5));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(h_base));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(j));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Load8U(mem_arg_byte(0)));
b.emit(Instruction::LocalSet(bh));
b.emit(Instruction::LocalGet(p_base));
b.emit(Instruction::LocalGet(j));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Load8U(mem_arg_byte(0)));
b.emit(Instruction::LocalSet(bp));
b.emit(Instruction::LocalGet(bh));
b.emit(Instruction::LocalGet(bp));
b.emit(Instruction::I32Ne);
b.emit(Instruction::BrIf(1)); b.emit(Instruction::LocalGet(j));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(j));
b.emit(Instruction::Br(0)); b.emit(Instruction::End); b.emit(Instruction::End); b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0)); b.emit(Instruction::End); b.emit(Instruction::End); b.emit(Instruction::I32Const(-1));
b.emit(Instruction::End);
b.finish(vec![ValType::I32, ValType::I32, ValType::I32], vec![ValType::I32])
}
fn build_rt_utf8_char_len() -> CompiledFn {
let mut b = RuntimeFnBuilder::new(1);
b.emit(Instruction::Block(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(0x80));
b.emit(Instruction::I32LtU);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::Br(1));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(0xE0));
b.emit(Instruction::I32LtU);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(2));
b.emit(Instruction::Br(1));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(0xF0));
b.emit(Instruction::I32LtU);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(3));
b.emit(Instruction::Br(1));
b.emit(Instruction::End);
b.emit(Instruction::I32Const(4));
b.emit(Instruction::End);
b.finish(vec![ValType::I32], vec![ValType::I32])
}
fn build_rt_str_split(string_tag: i32, list_tag: i32, find_from_idx: u32, utf8_char_len_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2); let s_len = b.alloc_i32();
let p_len = b.alloc_i32();
let s_cont = b.alloc_i32();
let count = b.alloc_i32();
let i = b.alloc_i32();
let prev = b.alloc_i32();
let list_ptr = b.alloc_i32();
let li = b.alloc_i32();
let idx = b.alloc_i32();
let piece_len = b.alloc_i32();
let str_ptr = b.alloc_i32();
let str_cont = b.alloc_i32();
let char_len = b.alloc_i32();
let padded = b.alloc_i32();
let size = b.alloc_i32();
let ki = b.alloc_i32();
let list_size = b.alloc_i32();
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(s_len));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(p_len));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(s_cont));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::LocalGet(p_len));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(s_len));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(s_cont));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Load8U(mem_arg_byte(0)));
b.emit(Instruction::Call(utf8_char_len_idx));
b.emit(Instruction::LocalSet(char_len));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(char_len));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::Else);
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(prev));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::LocalGet(prev));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::Call(find_from_idx));
b.emit(Instruction::LocalSet(idx));
b.emit(Instruction::LocalGet(idx));
b.emit(Instruction::I32Const(-1));
b.emit(Instruction::I32Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(s_len));
b.emit(Instruction::LocalGet(prev));
b.emit(Instruction::I32Sub);
b.emit(Instruction::LocalSet(piece_len));
b.emit(Instruction::LocalGet(piece_len));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::I32GtU);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::End);
b.emit(Instruction::Br(2)); b.emit(Instruction::End);
b.emit(Instruction::LocalGet(idx));
b.emit(Instruction::LocalGet(prev));
b.emit(Instruction::I32Sub);
b.emit(Instruction::LocalSet(piece_len));
b.emit(Instruction::LocalGet(piece_len));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::I32GtU);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(count));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(idx));
b.emit(Instruction::LocalGet(p_len));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(prev));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(list_size));
rt_emit_alloc_dynamic(&mut b, list_size, list_ptr, list_tag);
b.emit(Instruction::LocalGet(list_ptr));
b.emit(Instruction::LocalGet(count));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(li));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(prev));
b.emit(Instruction::LocalGet(p_len));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(s_len));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(s_cont));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Load8U(mem_arg_byte(0)));
b.emit(Instruction::Call(utf8_char_len_idx));
b.emit(Instruction::LocalSet(char_len));
b.emit(Instruction::LocalGet(char_len));
b.emit(Instruction::I32Const(7));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Const(-8));
b.emit(Instruction::I32And);
b.emit(Instruction::LocalSet(padded));
b.emit(Instruction::LocalGet(padded));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(size));
rt_emit_alloc_dynamic(&mut b, size, str_ptr, string_tag);
b.emit(Instruction::LocalGet(str_ptr));
b.emit(Instruction::LocalGet(char_len));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(str_ptr));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(str_cont));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(ki));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(ki));
b.emit(Instruction::LocalGet(char_len));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(str_cont));
b.emit(Instruction::LocalGet(ki));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(s_cont));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(ki));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Load8U(mem_arg_byte(0)));
b.emit(Instruction::I32Store8(mem_arg_byte(0)));
b.emit(Instruction::LocalGet(ki));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(ki));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(list_ptr));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(li));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(str_ptr));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(li));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(li));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(char_len));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::Else);
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::LocalGet(prev));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::Call(find_from_idx));
b.emit(Instruction::LocalSet(idx));
b.emit(Instruction::LocalGet(idx));
b.emit(Instruction::I32Const(-1));
b.emit(Instruction::I32Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(s_len));
b.emit(Instruction::LocalGet(prev));
b.emit(Instruction::I32Sub);
b.emit(Instruction::LocalSet(piece_len));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(idx));
b.emit(Instruction::LocalGet(prev));
b.emit(Instruction::I32Sub);
b.emit(Instruction::LocalSet(piece_len));
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(piece_len));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::I32GtU);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(piece_len));
b.emit(Instruction::I32Const(7));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Const(-8));
b.emit(Instruction::I32And);
b.emit(Instruction::LocalSet(padded));
b.emit(Instruction::LocalGet(padded));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(size));
rt_emit_alloc_dynamic(&mut b, size, str_ptr, string_tag);
b.emit(Instruction::LocalGet(str_ptr));
b.emit(Instruction::LocalGet(piece_len));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(str_ptr));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(str_cont));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(ki));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(ki));
b.emit(Instruction::LocalGet(piece_len));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1));
b.emit(Instruction::LocalGet(str_cont));
b.emit(Instruction::LocalGet(ki));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(s_cont));
b.emit(Instruction::LocalGet(prev));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(ki));
b.emit(Instruction::I32Add);
b.emit(Instruction::I32Load8U(mem_arg_byte(0)));
b.emit(Instruction::I32Store8(mem_arg_byte(0)));
b.emit(Instruction::LocalGet(ki));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(ki));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(list_ptr));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(li));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(str_ptr));
b.emit(Instruction::F64ConvertI32U);
b.emit(Instruction::F64Store(mem_arg_f64(0)));
b.emit(Instruction::LocalGet(li));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(li));
b.emit(Instruction::End); b.emit(Instruction::LocalGet(idx));
b.emit(Instruction::I32Const(-1));
b.emit(Instruction::I32Eq);
b.emit(Instruction::BrIf(1)); b.emit(Instruction::LocalGet(idx));
b.emit(Instruction::LocalGet(p_len));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(prev));
b.emit(Instruction::Br(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::End);
b.emit(Instruction::LocalGet(list_ptr));
b.finish(vec![ValType::I32, ValType::I32], vec![ValType::I32])
}
fn build_rt_value_equal(string_tag: i32, list_tag: i32, str_compare_idx: u32, self_idx: u32) -> CompiledFn {
let mut b = RuntimeFnBuilder::new(2);
let result = b.alloc_i32(); let ptr_a = b.alloc_i32();
let ptr_b = b.alloc_i32();
let tag_a = b.alloc_i32();
let tag_b = b.alloc_i32();
let cnt = b.alloc_i32();
let i = b.alloc_i32();
let elem_a = b.alloc_f64();
let elem_b = b.alloc_f64();
let heap_min = (HEAP_BASE + 8) as f64;
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::F64Const(Ieee64::from(heap_min)));
b.emit(Instruction::F64Ge);
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::F64Const(Ieee64::from(heap_min)));
b.emit(Instruction::F64Ge);
b.emit(Instruction::I32And);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::LocalGet(0));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(ptr_a));
b.emit(Instruction::LocalGet(1));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(ptr_b));
b.emit(Instruction::LocalGet(ptr_a));
b.emit(Instruction::I32Const(4));
b.emit(Instruction::I32Sub);
b.emit(Instruction::I32Load(mem_arg_i32(0)));
b.emit(Instruction::LocalSet(tag_a));
b.emit(Instruction::LocalGet(ptr_b));
b.emit(Instruction::I32Const(4));
b.emit(Instruction::I32Sub);
b.emit(Instruction::I32Load(mem_arg_i32(0)));
b.emit(Instruction::LocalSet(tag_b));
b.emit(Instruction::LocalGet(tag_a));
b.emit(Instruction::LocalGet(tag_b));
b.emit(Instruction::I32Ne);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(tag_a));
b.emit(Instruction::I32Const(string_tag));
b.emit(Instruction::I32Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::LocalGet(ptr_a));
b.emit(Instruction::LocalGet(ptr_b));
b.emit(Instruction::Call(str_compare_idx));
b.emit(Instruction::F64Const(Ieee64::from(0.0f64)));
b.emit(Instruction::F64Eq);
b.emit(Instruction::Else);
b.emit(Instruction::LocalGet(tag_a));
b.emit(Instruction::I32Const(list_tag));
b.emit(Instruction::I32Eq);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
{
b.emit(Instruction::LocalGet(ptr_a));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalSet(cnt));
b.emit(Instruction::LocalGet(ptr_b));
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::I32TruncF64U);
b.emit(Instruction::LocalGet(cnt));
b.emit(Instruction::I32Ne);
b.emit(Instruction::If(wasm_encoder::BlockType::Result(ValType::I32)));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::Else);
b.emit(Instruction::I32Const(1));
b.emit(Instruction::LocalSet(result));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Block(wasm_encoder::BlockType::Empty));
b.emit(Instruction::Loop(wasm_encoder::BlockType::Empty));
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::LocalGet(cnt));
b.emit(Instruction::I32GeU);
b.emit(Instruction::BrIf(1)); b.emit(Instruction::LocalGet(ptr_a));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(elem_a));
b.emit(Instruction::LocalGet(ptr_b));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(8));
b.emit(Instruction::I32Mul);
b.emit(Instruction::I32Add);
b.emit(Instruction::F64Load(mem_arg_f64(0)));
b.emit(Instruction::LocalSet(elem_b));
b.emit(Instruction::LocalGet(elem_a));
b.emit(Instruction::LocalGet(elem_b));
b.emit(Instruction::Call(self_idx));
b.emit(Instruction::I32Eqz);
b.emit(Instruction::If(wasm_encoder::BlockType::Empty));
b.emit(Instruction::I32Const(0));
b.emit(Instruction::LocalSet(result));
b.emit(Instruction::Br(2)); b.emit(Instruction::End);
b.emit(Instruction::LocalGet(i));
b.emit(Instruction::I32Const(1));
b.emit(Instruction::I32Add);
b.emit(Instruction::LocalSet(i));
b.emit(Instruction::Br(0)); b.emit(Instruction::End); b.emit(Instruction::End); b.emit(Instruction::LocalGet(result));
b.emit(Instruction::End); }
b.emit(Instruction::Else);
b.emit(Instruction::I32Const(0));
b.emit(Instruction::End);
b.emit(Instruction::End); b.emit(Instruction::End); b.emit(Instruction::Else);
b.emit(Instruction::I32Const(0));
b.emit(Instruction::End);
b.emit(Instruction::End);
b.finish(vec![ValType::F64, ValType::F64], vec![ValType::I32])
}