use wasm_encoder::{Function, Instruction, ValType};
pub(in crate::codegen::wasm_gc) fn emit_tcp_format_id(
string_type_idx: u32,
from_lm_fn: u32,
) -> Function {
use wasm_encoder::{BlockType, MemArg};
let _ = string_type_idx;
let mut f = Function::new(vec![(4u32, ValType::I32)]);
let l_n: u32 = 1;
let l_cursor: u32 = 2;
let l_i: u32 = 3;
let l_len: u32 = 4;
const SCRATCH_BASE: u32 = 16;
const SCRATCH_END: u32 = SCRATCH_BASE + 10;
let mem1 = |offset: u32| MemArg {
offset: u64::from(offset),
align: 0,
memory_index: 0,
};
let mem1_zero = MemArg {
offset: 0,
align: 0,
memory_index: 0,
};
let prefix: [u8; 4] = *b"tcp-";
for (i, byte) in prefix.iter().enumerate() {
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(i32::from(*byte)));
f.instruction(&Instruction::I32Store8(mem1(i as u32)));
}
f.instruction(&Instruction::LocalGet(0));
f.instruction(&Instruction::LocalSet(l_n));
f.instruction(&Instruction::I32Const(SCRATCH_END as i32));
f.instruction(&Instruction::LocalSet(l_cursor));
f.instruction(&Instruction::Block(BlockType::Empty));
f.instruction(&Instruction::Loop(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_cursor));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Sub);
f.instruction(&Instruction::LocalSet(l_cursor));
f.instruction(&Instruction::LocalGet(l_cursor));
f.instruction(&Instruction::LocalGet(l_n));
f.instruction(&Instruction::I32Const(10));
f.instruction(&Instruction::I32RemU);
f.instruction(&Instruction::I32Const(0x30));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Store8(mem1_zero));
f.instruction(&Instruction::LocalGet(l_n));
f.instruction(&Instruction::I32Const(10));
f.instruction(&Instruction::I32DivU);
f.instruction(&Instruction::LocalSet(l_n));
f.instruction(&Instruction::LocalGet(l_n));
f.instruction(&Instruction::BrIf(0));
f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::I32Const(SCRATCH_END as i32));
f.instruction(&Instruction::LocalGet(l_cursor));
f.instruction(&Instruction::I32Sub);
f.instruction(&Instruction::I32Const(4));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalSet(l_len));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalSet(l_i));
f.instruction(&Instruction::Block(BlockType::Empty));
f.instruction(&Instruction::Loop(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_i));
f.instruction(&Instruction::LocalGet(l_len));
f.instruction(&Instruction::I32Const(4));
f.instruction(&Instruction::I32Sub);
f.instruction(&Instruction::I32GeU);
f.instruction(&Instruction::BrIf(1));
f.instruction(&Instruction::I32Const(4));
f.instruction(&Instruction::LocalGet(l_i));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalGet(l_cursor));
f.instruction(&Instruction::LocalGet(l_i));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Load8U(mem1_zero));
f.instruction(&Instruction::I32Store8(mem1_zero));
f.instruction(&Instruction::LocalGet(l_i));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalSet(l_i));
f.instruction(&Instruction::Br(0));
f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_len));
f.instruction(&Instruction::Call(from_lm_fn));
f.instruction(&Instruction::End);
f
}
pub(in crate::codegen::wasm_gc) fn emit_tcp_parse_id(string_type_idx: u32) -> Function {
let mut f = Function::new(vec![(3u32, ValType::I32)]);
let l_acc: u32 = 1;
let l_i: u32 = 2;
let l_len: u32 = 3;
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalSet(l_acc));
f.instruction(&Instruction::I32Const(4));
f.instruction(&Instruction::LocalSet(l_i));
f.instruction(&Instruction::LocalGet(0));
f.instruction(&Instruction::ArrayLen);
f.instruction(&Instruction::LocalSet(l_len));
f.instruction(&Instruction::Block(wasm_encoder::BlockType::Empty));
f.instruction(&Instruction::Loop(wasm_encoder::BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_i));
f.instruction(&Instruction::LocalGet(l_len));
f.instruction(&Instruction::I32GeU);
f.instruction(&Instruction::BrIf(1));
f.instruction(&Instruction::LocalGet(l_acc));
f.instruction(&Instruction::I32Const(10));
f.instruction(&Instruction::I32Mul);
f.instruction(&Instruction::LocalGet(0));
f.instruction(&Instruction::LocalGet(l_i));
f.instruction(&Instruction::ArrayGetU(string_type_idx));
f.instruction(&Instruction::I32Const(0x30));
f.instruction(&Instruction::I32Sub);
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalSet(l_acc));
f.instruction(&Instruction::LocalGet(l_i));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalSet(l_i));
f.instruction(&Instruction::Br(0));
f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_acc));
f.instruction(&Instruction::End);
f
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_id_emit_compiles() {
let _f = emit_tcp_parse_id(1);
}
}