use wasm_encoder::{Function, Instruction, ValType};
use super::restore_bump;
pub(in crate::codegen::wasm_gc) struct TcpCloseIndices {
pub fn_type: u32,
pub fn_idx: u32,
pub tcp_connection_type_idx: u32,
pub tcp_slot_type_idx: u32,
pub tcp_pool_type_idx: u32,
pub string_type_idx: u32,
pub unknown_segment_idx: u32,
pub unknown_len: u32,
}
pub(in crate::codegen::wasm_gc) struct TcpCloseHelperFns {
pub parse_id_fn: u32,
pub cabi_realloc_fn: u32,
pub shutdown_fn: u32,
pub drop_input_stream_fn: u32,
pub drop_output_stream_fn: u32,
pub drop_tcp_socket_fn: u32,
pub result_ok_fn: u32,
pub result_err_fn: u32,
pub tcp_pool_global: u32,
pub bump_alloc_ptr_global: u32,
}
pub(in crate::codegen::wasm_gc) struct TcpSendIndices {
pub fn_type: u32,
pub fn_idx: u32,
pub string_type_idx: u32,
pub result_string_string_type_idx: u32,
pub dns_err_segment_idx: u32,
pub dns_err_len: u32,
pub no_addr_segment_idx: u32,
pub no_addr_len: u32,
pub sock_err_segment_idx: u32,
pub sock_err_len: u32,
pub conn_err_segment_idx: u32,
pub conn_err_len: u32,
pub port_err_segment_idx: u32,
pub port_err_len: u32,
pub write_err_segment_idx: u32,
pub write_err_len: u32,
pub stream_err_segment_idx: u32,
pub stream_err_len: u32,
pub size_err_segment_idx: u32,
pub size_err_len: u32,
}
pub(in crate::codegen::wasm_gc) struct TcpSendHelperFns {
pub instance_network_fn: u32,
pub network_handle_global: u32,
pub resolve_addresses_fn: u32,
pub resolve_next_address_fn: u32,
pub drop_resolve_stream_fn: u32,
pub stream_subscribe_fn: u32,
pub poll_fn: u32,
pub drop_pollable_fn: u32,
pub create_tcp_socket_fn: u32,
pub start_connect_fn: u32,
pub finish_connect_fn: u32,
pub socket_subscribe_fn: u32,
pub drop_tcp_socket_fn: u32,
pub drop_input_stream_fn: u32,
pub drop_output_stream_fn: u32,
pub str_to_lm_fn: u32,
pub cabi_realloc_fn: u32,
pub blocking_write_fn: u32,
pub blocking_read_fn: u32,
pub shutdown_fn: u32,
pub bump_alloc_ptr_global: u32,
pub result_string_string_err_fn: u32,
}
pub(in crate::codegen::wasm_gc) fn emit_tcp_send(
indices: &TcpSendIndices,
helpers: &TcpSendHelperFns,
) -> Function {
use wasm_encoder::{BlockType, HeapType, MemArg, RefType};
let s_ref = ValType::Ref(RefType {
nullable: true,
heap_type: HeapType::Concrete(indices.string_type_idx),
});
let mut f = Function::new(vec![(22u32, ValType::I32), (1u32, s_ref)]);
let l_saved_alloc: u32 = 3;
let l_host_len: u32 = 4;
let l_scratch: u32 = 5;
let l_resolve_strm: u32 = 6;
let l_pollable: u32 = 7;
let l_ipv4_a: u32 = 8;
let l_ipv4_b: u32 = 9;
let l_ipv4_c: u32 = 10;
let l_ipv4_d: u32 = 11;
let l_socket: u32 = 12;
let l_in_handle: u32 = 13;
let l_out_handle: u32 = 14;
let l_data_len: u32 = 15;
let l_off: u32 = 16;
let l_retptr: u32 = 17;
let l_buf_ptr: u32 = 18;
let l_buf_cap: u32 = 19;
let l_buf_len: u32 = 20;
let l_read_ptr: u32 = 21;
let l_read_len: u32 = 22;
let l_new_cap: u32 = 23;
let l_j: u32 = 24;
let l_arr: u32 = 25;
const SCRATCH_BLOCK_SIZE: i32 = 64;
const SCRATCH_OFFSET_RESOLVE: u32 = 0;
const SCRATCH_OFFSET_NEXT: u32 = 16;
const SCRATCH_OFFSET_POLL: u32 = 48;
const SCRATCH_OFFSET_POLLABLE_IN: u32 = 56;
let mem4_resolve = MemArg {
offset: u64::from(SCRATCH_OFFSET_RESOLVE),
align: 2,
memory_index: 0,
};
let mem4_resolve_off4 = MemArg {
offset: u64::from(SCRATCH_OFFSET_RESOLVE + 4),
align: 2,
memory_index: 0,
};
let mem4_resolve_off8 = MemArg {
offset: u64::from(SCRATCH_OFFSET_RESOLVE + 8),
align: 2,
memory_index: 0,
};
let mem1_resolve = MemArg {
offset: u64::from(SCRATCH_OFFSET_RESOLVE),
align: 0,
memory_index: 0,
};
let mem1_resolve_off4 = MemArg {
offset: u64::from(SCRATCH_OFFSET_RESOLVE + 4),
align: 0,
memory_index: 0,
};
let mem1_next_outer = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT),
align: 0,
memory_index: 0,
};
let mem1_next_option = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 2),
align: 0,
memory_index: 0,
};
let mem1_next_variant = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 4),
align: 0,
memory_index: 0,
};
let mem1_next_octet_a = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 6),
align: 0,
memory_index: 0,
};
let mem1_next_octet_b = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 7),
align: 0,
memory_index: 0,
};
let mem1_next_octet_c = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 8),
align: 0,
memory_index: 0,
};
let mem1_next_octet_d = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 9),
align: 0,
memory_index: 0,
};
let mem4_pollable_in = MemArg {
offset: u64::from(SCRATCH_OFFSET_POLLABLE_IN),
align: 2,
memory_index: 0,
};
let mem1 = MemArg {
offset: 0,
align: 0,
memory_index: 0,
};
let mem4_o4 = MemArg {
offset: 4,
align: 2,
memory_index: 0,
};
let mem4_o8 = MemArg {
offset: 8,
align: 2,
memory_index: 0,
};
let string_type_idx = indices.string_type_idx;
let result_err_fn = helpers.result_string_string_err_fn;
let bump_alloc_ptr_global = helpers.bump_alloc_ptr_global;
let emit_err_with_segment = |f: &mut Function, seg: u32, len: u32| {
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(len as i32));
f.instruction(&Instruction::ArrayNewData {
array_type_index: string_type_idx,
array_data_index: seg,
});
f.instruction(&Instruction::Call(result_err_fn));
restore_bump(f, l_saved_alloc, bump_alloc_ptr_global);
f.instruction(&Instruction::Return);
};
f.instruction(&Instruction::GlobalGet(helpers.bump_alloc_ptr_global));
f.instruction(&Instruction::LocalSet(l_saved_alloc));
f.instruction(&Instruction::LocalGet(1));
f.instruction(&Instruction::I64Const(0));
f.instruction(&Instruction::I64LtS);
f.instruction(&Instruction::LocalGet(1));
f.instruction(&Instruction::I64Const(65535));
f.instruction(&Instruction::I64GtS);
f.instruction(&Instruction::I32Or);
f.instruction(&Instruction::If(BlockType::Empty));
emit_err_with_segment(&mut f, indices.port_err_segment_idx, indices.port_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::GlobalGet(helpers.network_handle_global));
f.instruction(&Instruction::I32Const(-1));
f.instruction(&Instruction::I32Eq);
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::Call(helpers.instance_network_fn));
f.instruction(&Instruction::GlobalSet(helpers.network_handle_global));
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(0));
f.instruction(&Instruction::Call(helpers.str_to_lm_fn));
f.instruction(&Instruction::LocalSet(l_host_len));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(4));
f.instruction(&Instruction::I32Const(SCRATCH_BLOCK_SIZE));
f.instruction(&Instruction::Call(helpers.cabi_realloc_fn));
f.instruction(&Instruction::LocalSet(l_scratch));
f.instruction(&Instruction::GlobalGet(helpers.network_handle_global));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalGet(l_host_len));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::Call(helpers.resolve_addresses_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_resolve));
f.instruction(&Instruction::If(BlockType::Empty));
emit_err_with_segment(&mut f, indices.dns_err_segment_idx, indices.dns_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load(mem4_resolve_off4));
f.instruction(&Instruction::LocalSet(l_resolve_strm));
let _ = mem4_resolve;
f.instruction(&Instruction::Block(BlockType::Empty));
f.instruction(&Instruction::Loop(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::Call(helpers.stream_subscribe_fn));
f.instruction(&Instruction::LocalSet(l_pollable));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::LocalGet(l_pollable));
f.instruction(&Instruction::I32Store(mem4_pollable_in));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_POLLABLE_IN as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_POLL as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::Call(helpers.poll_fn));
f.instruction(&Instruction::LocalGet(l_pollable));
f.instruction(&Instruction::Call(helpers.drop_pollable_fn));
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_NEXT as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::Call(helpers.resolve_next_address_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_outer));
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::Call(helpers.drop_resolve_stream_fn));
emit_err_with_segment(&mut f, indices.no_addr_segment_idx, indices.no_addr_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_option));
f.instruction(&Instruction::I32Eqz);
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::Call(helpers.drop_resolve_stream_fn));
emit_err_with_segment(&mut f, indices.no_addr_segment_idx, indices.no_addr_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_variant));
f.instruction(&Instruction::BrIf(0));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_octet_a));
f.instruction(&Instruction::LocalSet(l_ipv4_a));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_octet_b));
f.instruction(&Instruction::LocalSet(l_ipv4_b));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_octet_c));
f.instruction(&Instruction::LocalSet(l_ipv4_c));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_octet_d));
f.instruction(&Instruction::LocalSet(l_ipv4_d));
f.instruction(&Instruction::Br(1));
f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::Call(helpers.drop_resolve_stream_fn));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::Call(helpers.create_tcp_socket_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_resolve));
f.instruction(&Instruction::If(BlockType::Empty));
emit_err_with_segment(&mut f, indices.sock_err_segment_idx, indices.sock_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load(mem4_resolve_off4));
f.instruction(&Instruction::LocalSet(l_socket));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::GlobalGet(helpers.network_handle_global));
f.instruction(&Instruction::I32Const(0)); f.instruction(&Instruction::LocalGet(1));
f.instruction(&Instruction::I32WrapI64);
f.instruction(&Instruction::LocalGet(l_ipv4_a));
f.instruction(&Instruction::LocalGet(l_ipv4_b));
f.instruction(&Instruction::LocalGet(l_ipv4_c));
f.instruction(&Instruction::LocalGet(l_ipv4_d));
for _ in 0..6 {
f.instruction(&Instruction::I32Const(0));
}
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::Call(helpers.start_connect_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_resolve));
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(helpers.drop_tcp_socket_fn));
emit_err_with_segment(&mut f, indices.conn_err_segment_idx, indices.conn_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(helpers.socket_subscribe_fn));
f.instruction(&Instruction::LocalSet(l_pollable));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::LocalGet(l_pollable));
f.instruction(&Instruction::I32Store(mem4_pollable_in));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_POLLABLE_IN as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_POLL as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::Call(helpers.poll_fn));
f.instruction(&Instruction::LocalGet(l_pollable));
f.instruction(&Instruction::Call(helpers.drop_pollable_fn));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::Call(helpers.finish_connect_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_resolve));
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(helpers.drop_tcp_socket_fn));
emit_err_with_segment(&mut f, indices.conn_err_segment_idx, indices.conn_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load(mem4_resolve_off4));
f.instruction(&Instruction::LocalSet(l_in_handle));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load(mem4_resolve_off8));
f.instruction(&Instruction::LocalSet(l_out_handle));
let _ = mem1_resolve_off4;
f.instruction(&Instruction::LocalGet(2));
f.instruction(&Instruction::Call(helpers.str_to_lm_fn));
f.instruction(&Instruction::LocalSet(l_data_len));
f.instruction(&Instruction::LocalGet(l_data_len));
f.instruction(&Instruction::I32Const(15));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Const(-16));
f.instruction(&Instruction::I32And);
f.instruction(&Instruction::GlobalGet(helpers.bump_alloc_ptr_global));
f.instruction(&Instruction::I32GtU);
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_data_len));
f.instruction(&Instruction::I32Const(15));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Const(-16));
f.instruction(&Instruction::I32And);
f.instruction(&Instruction::GlobalSet(helpers.bump_alloc_ptr_global));
f.instruction(&Instruction::End);
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(4));
f.instruction(&Instruction::I32Const(12));
f.instruction(&Instruction::Call(helpers.cabi_realloc_fn));
f.instruction(&Instruction::LocalSet(l_retptr));
let drop_input_stream_fn = helpers.drop_input_stream_fn;
let drop_output_stream_fn = helpers.drop_output_stream_fn;
let drop_tcp_socket_fn = helpers.drop_tcp_socket_fn;
let write_err_segment_idx = indices.write_err_segment_idx;
let write_err_len = indices.write_err_len;
let emit_drop_then_write_err = |f: &mut Function| {
f.instruction(&Instruction::LocalGet(l_in_handle));
f.instruction(&Instruction::Call(drop_input_stream_fn));
f.instruction(&Instruction::LocalGet(l_out_handle));
f.instruction(&Instruction::Call(drop_output_stream_fn));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(drop_tcp_socket_fn));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(write_err_len as i32));
f.instruction(&Instruction::ArrayNewData {
array_type_index: string_type_idx,
array_data_index: write_err_segment_idx,
});
f.instruction(&Instruction::Call(result_err_fn));
restore_bump(f, l_saved_alloc, bump_alloc_ptr_global);
f.instruction(&Instruction::Return);
};
let stream_err_segment_idx = indices.stream_err_segment_idx;
let stream_err_len = indices.stream_err_len;
let emit_drop_then_stream_err = |f: &mut Function| {
f.instruction(&Instruction::LocalGet(l_in_handle));
f.instruction(&Instruction::Call(drop_input_stream_fn));
f.instruction(&Instruction::LocalGet(l_out_handle));
f.instruction(&Instruction::Call(drop_output_stream_fn));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(drop_tcp_socket_fn));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(stream_err_len as i32));
f.instruction(&Instruction::ArrayNewData {
array_type_index: string_type_idx,
array_data_index: stream_err_segment_idx,
});
f.instruction(&Instruction::Call(result_err_fn));
restore_bump(f, l_saved_alloc, bump_alloc_ptr_global);
f.instruction(&Instruction::Return);
};
let size_err_segment_idx = indices.size_err_segment_idx;
let size_err_len = indices.size_err_len;
let emit_drop_then_size_err = |f: &mut Function| {
f.instruction(&Instruction::LocalGet(l_in_handle));
f.instruction(&Instruction::Call(drop_input_stream_fn));
f.instruction(&Instruction::LocalGet(l_out_handle));
f.instruction(&Instruction::Call(drop_output_stream_fn));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(drop_tcp_socket_fn));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(size_err_len as i32));
f.instruction(&Instruction::ArrayNewData {
array_type_index: string_type_idx,
array_data_index: size_err_segment_idx,
});
f.instruction(&Instruction::Call(result_err_fn));
restore_bump(f, l_saved_alloc, bump_alloc_ptr_global);
f.instruction(&Instruction::Return);
};
let blocking_write_fn = helpers.blocking_write_fn;
super::super::wasip2_helpers::emit_chunked_blocking_write(
&mut f,
l_data_len,
l_off,
blocking_write_fn,
&|f| {
f.instruction(&Instruction::LocalGet(l_out_handle));
},
&|f| {
f.instruction(&Instruction::LocalGet(l_retptr));
},
Some(&emit_drop_then_write_err),
);
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::I32Const(1)); f.instruction(&Instruction::LocalGet(l_retptr));
f.instruction(&Instruction::Call(helpers.shutdown_fn));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Const(4096));
f.instruction(&Instruction::Call(helpers.cabi_realloc_fn));
f.instruction(&Instruction::LocalSet(l_buf_ptr));
f.instruction(&Instruction::I32Const(4096));
f.instruction(&Instruction::LocalSet(l_buf_cap));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalSet(l_buf_len));
f.instruction(&Instruction::Block(BlockType::Empty));
f.instruction(&Instruction::Loop(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_in_handle));
f.instruction(&Instruction::I64Const(4096));
f.instruction(&Instruction::LocalGet(l_retptr));
f.instruction(&Instruction::Call(helpers.blocking_read_fn));
f.instruction(&Instruction::LocalGet(l_retptr));
f.instruction(&Instruction::I32Load8U(mem1));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Eq);
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_retptr));
f.instruction(&Instruction::I32Load8U(MemArg {
offset: 4,
align: 0,
memory_index: 0,
}));
f.instruction(&Instruction::I32Eqz);
f.instruction(&Instruction::If(BlockType::Empty));
emit_drop_then_stream_err(&mut f);
f.instruction(&Instruction::End);
f.instruction(&Instruction::Br(2));
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_retptr));
f.instruction(&Instruction::I32Load(mem4_o4));
f.instruction(&Instruction::LocalSet(l_read_ptr));
f.instruction(&Instruction::LocalGet(l_retptr));
f.instruction(&Instruction::I32Load(mem4_o8));
f.instruction(&Instruction::LocalSet(l_read_len));
f.instruction(&Instruction::LocalGet(l_read_len));
f.instruction(&Instruction::I32Eqz);
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::Br(2));
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_buf_len));
f.instruction(&Instruction::LocalGet(l_read_len));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Const(10 * 1024 * 1024));
f.instruction(&Instruction::I32GtU);
f.instruction(&Instruction::If(BlockType::Empty));
emit_drop_then_size_err(&mut f);
f.instruction(&Instruction::End);
f.instruction(&Instruction::Block(BlockType::Empty));
f.instruction(&Instruction::Loop(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_buf_len));
f.instruction(&Instruction::LocalGet(l_read_len));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalGet(l_buf_cap));
f.instruction(&Instruction::I32LeU);
f.instruction(&Instruction::BrIf(1));
f.instruction(&Instruction::LocalGet(l_buf_cap));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Shl);
f.instruction(&Instruction::LocalSet(l_new_cap));
f.instruction(&Instruction::LocalGet(l_buf_ptr));
f.instruction(&Instruction::LocalGet(l_buf_cap));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::LocalGet(l_new_cap));
f.instruction(&Instruction::Call(helpers.cabi_realloc_fn));
f.instruction(&Instruction::LocalSet(l_buf_ptr));
f.instruction(&Instruction::LocalGet(l_new_cap));
f.instruction(&Instruction::LocalSet(l_buf_cap));
f.instruction(&Instruction::Br(0));
f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_buf_ptr));
f.instruction(&Instruction::LocalGet(l_buf_len));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalGet(l_read_ptr));
f.instruction(&Instruction::LocalGet(l_read_len));
f.instruction(&Instruction::MemoryCopy {
src_mem: 0,
dst_mem: 0,
});
f.instruction(&Instruction::LocalGet(l_buf_len));
f.instruction(&Instruction::LocalGet(l_read_len));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalSet(l_buf_len));
f.instruction(&Instruction::Br(0));
f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_in_handle));
f.instruction(&Instruction::Call(helpers.drop_input_stream_fn));
f.instruction(&Instruction::LocalGet(l_out_handle));
f.instruction(&Instruction::Call(helpers.drop_output_stream_fn));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(helpers.drop_tcp_socket_fn));
f.instruction(&Instruction::LocalGet(l_buf_len));
f.instruction(&Instruction::ArrayNewDefault(indices.string_type_idx));
f.instruction(&Instruction::LocalSet(l_arr));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalSet(l_j));
f.instruction(&Instruction::Block(BlockType::Empty));
f.instruction(&Instruction::Loop(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_j));
f.instruction(&Instruction::LocalGet(l_buf_len));
f.instruction(&Instruction::I32GeU);
f.instruction(&Instruction::BrIf(1));
f.instruction(&Instruction::LocalGet(l_arr));
f.instruction(&Instruction::LocalGet(l_j));
f.instruction(&Instruction::LocalGet(l_buf_ptr));
f.instruction(&Instruction::LocalGet(l_j));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Load8U(mem1));
f.instruction(&Instruction::ArraySet(indices.string_type_idx));
f.instruction(&Instruction::LocalGet(l_j));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalSet(l_j));
f.instruction(&Instruction::Br(0));
f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::I32Const(1)); f.instruction(&Instruction::LocalGet(l_arr));
f.instruction(&Instruction::RefNull(HeapType::Concrete(
indices.string_type_idx,
)));
f.instruction(&Instruction::StructNew(
indices.result_string_string_type_idx,
));
restore_bump(&mut f, l_saved_alloc, helpers.bump_alloc_ptr_global);
f.instruction(&Instruction::End);
f
}
pub(in crate::codegen::wasm_gc) struct TcpPingIndices {
pub fn_type: u32,
pub fn_idx: u32,
pub string_type_idx: u32,
pub dns_err_segment_idx: u32,
pub dns_err_len: u32,
pub no_addr_segment_idx: u32,
pub no_addr_len: u32,
pub sock_err_segment_idx: u32,
pub sock_err_len: u32,
pub conn_err_segment_idx: u32,
pub conn_err_len: u32,
pub port_err_segment_idx: u32,
pub port_err_len: u32,
}
pub(in crate::codegen::wasm_gc) struct TcpPingHelperFns {
pub instance_network_fn: u32,
pub network_handle_global: u32,
pub resolve_addresses_fn: u32,
pub resolve_next_address_fn: u32,
pub drop_resolve_stream_fn: u32,
pub stream_subscribe_fn: u32,
pub poll_fn: u32,
pub drop_pollable_fn: u32,
pub create_tcp_socket_fn: u32,
pub start_connect_fn: u32,
pub finish_connect_fn: u32,
pub socket_subscribe_fn: u32,
pub drop_tcp_socket_fn: u32,
pub drop_input_stream_fn: u32,
pub drop_output_stream_fn: u32,
pub str_to_lm_fn: u32,
pub cabi_realloc_fn: u32,
pub bump_alloc_ptr_global: u32,
pub result_unit_string_ok_fn: u32,
pub result_unit_string_err_fn: u32,
}
pub(in crate::codegen::wasm_gc) fn emit_tcp_ping(
indices: &TcpPingIndices,
helpers: &TcpPingHelperFns,
) -> Function {
use wasm_encoder::{BlockType, MemArg};
let mut f = Function::new(vec![(10u32, ValType::I32)]);
let l_saved_alloc: u32 = 2;
let l_host_len: u32 = 3;
let l_scratch: u32 = 4;
let l_resolve_strm: u32 = 5;
let l_pollable: u32 = 6;
let l_ipv4_a: u32 = 7;
let l_ipv4_b: u32 = 8;
let l_ipv4_c: u32 = 9;
let l_ipv4_d: u32 = 10;
let l_socket: u32 = 11;
const SCRATCH_BLOCK_SIZE: i32 = 64;
const SCRATCH_OFFSET_RESOLVE: u32 = 0;
const SCRATCH_OFFSET_NEXT: u32 = 16;
const SCRATCH_OFFSET_POLL: u32 = 48;
const SCRATCH_OFFSET_POLLABLE_IN: u32 = 56;
let mem4_resolve_off4 = MemArg {
offset: u64::from(SCRATCH_OFFSET_RESOLVE + 4),
align: 2,
memory_index: 0,
};
let mem4_resolve_off8 = MemArg {
offset: u64::from(SCRATCH_OFFSET_RESOLVE + 8),
align: 2,
memory_index: 0,
};
let mem1_resolve = MemArg {
offset: u64::from(SCRATCH_OFFSET_RESOLVE),
align: 0,
memory_index: 0,
};
let mem1_next_outer = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT),
align: 0,
memory_index: 0,
};
let mem1_next_option = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 2),
align: 0,
memory_index: 0,
};
let mem1_next_variant = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 4),
align: 0,
memory_index: 0,
};
let mem1_next_octet_a = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 6),
align: 0,
memory_index: 0,
};
let mem1_next_octet_b = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 7),
align: 0,
memory_index: 0,
};
let mem1_next_octet_c = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 8),
align: 0,
memory_index: 0,
};
let mem1_next_octet_d = MemArg {
offset: u64::from(SCRATCH_OFFSET_NEXT + 9),
align: 0,
memory_index: 0,
};
let mem4_pollable_in = MemArg {
offset: u64::from(SCRATCH_OFFSET_POLLABLE_IN),
align: 2,
memory_index: 0,
};
let string_type_idx = indices.string_type_idx;
let result_err_fn = helpers.result_unit_string_err_fn;
let bump_alloc_ptr_global = helpers.bump_alloc_ptr_global;
let emit_err_with_segment = |f: &mut Function, seg: u32, len: u32| {
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(len as i32));
f.instruction(&Instruction::ArrayNewData {
array_type_index: string_type_idx,
array_data_index: seg,
});
f.instruction(&Instruction::Call(result_err_fn));
restore_bump(f, l_saved_alloc, bump_alloc_ptr_global);
f.instruction(&Instruction::Return);
};
f.instruction(&Instruction::GlobalGet(helpers.bump_alloc_ptr_global));
f.instruction(&Instruction::LocalSet(l_saved_alloc));
f.instruction(&Instruction::LocalGet(1));
f.instruction(&Instruction::I64Const(0));
f.instruction(&Instruction::I64LtS);
f.instruction(&Instruction::LocalGet(1));
f.instruction(&Instruction::I64Const(65535));
f.instruction(&Instruction::I64GtS);
f.instruction(&Instruction::I32Or);
f.instruction(&Instruction::If(BlockType::Empty));
emit_err_with_segment(&mut f, indices.port_err_segment_idx, indices.port_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::GlobalGet(helpers.network_handle_global));
f.instruction(&Instruction::I32Const(-1));
f.instruction(&Instruction::I32Eq);
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::Call(helpers.instance_network_fn));
f.instruction(&Instruction::GlobalSet(helpers.network_handle_global));
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(0));
f.instruction(&Instruction::Call(helpers.str_to_lm_fn));
f.instruction(&Instruction::LocalSet(l_host_len));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(4));
f.instruction(&Instruction::I32Const(SCRATCH_BLOCK_SIZE));
f.instruction(&Instruction::Call(helpers.cabi_realloc_fn));
f.instruction(&Instruction::LocalSet(l_scratch));
f.instruction(&Instruction::GlobalGet(helpers.network_handle_global));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalGet(l_host_len));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::Call(helpers.resolve_addresses_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_resolve));
f.instruction(&Instruction::If(BlockType::Empty));
emit_err_with_segment(&mut f, indices.dns_err_segment_idx, indices.dns_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load(mem4_resolve_off4));
f.instruction(&Instruction::LocalSet(l_resolve_strm));
f.instruction(&Instruction::Block(BlockType::Empty));
f.instruction(&Instruction::Loop(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::Call(helpers.stream_subscribe_fn));
f.instruction(&Instruction::LocalSet(l_pollable));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::LocalGet(l_pollable));
f.instruction(&Instruction::I32Store(mem4_pollable_in));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_POLLABLE_IN as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_POLL as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::Call(helpers.poll_fn));
f.instruction(&Instruction::LocalGet(l_pollable));
f.instruction(&Instruction::Call(helpers.drop_pollable_fn));
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_NEXT as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::Call(helpers.resolve_next_address_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_outer));
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::Call(helpers.drop_resolve_stream_fn));
emit_err_with_segment(&mut f, indices.no_addr_segment_idx, indices.no_addr_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_option));
f.instruction(&Instruction::I32Eqz);
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::Call(helpers.drop_resolve_stream_fn));
emit_err_with_segment(&mut f, indices.no_addr_segment_idx, indices.no_addr_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_variant));
f.instruction(&Instruction::BrIf(0));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_octet_a));
f.instruction(&Instruction::LocalSet(l_ipv4_a));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_octet_b));
f.instruction(&Instruction::LocalSet(l_ipv4_b));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_octet_c));
f.instruction(&Instruction::LocalSet(l_ipv4_c));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_next_octet_d));
f.instruction(&Instruction::LocalSet(l_ipv4_d));
f.instruction(&Instruction::Br(1));
f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_resolve_strm));
f.instruction(&Instruction::Call(helpers.drop_resolve_stream_fn));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::Call(helpers.create_tcp_socket_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_resolve));
f.instruction(&Instruction::If(BlockType::Empty));
emit_err_with_segment(&mut f, indices.sock_err_segment_idx, indices.sock_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load(mem4_resolve_off4));
f.instruction(&Instruction::LocalSet(l_socket));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::GlobalGet(helpers.network_handle_global));
f.instruction(&Instruction::I32Const(0)); f.instruction(&Instruction::LocalGet(1));
f.instruction(&Instruction::I32WrapI64);
f.instruction(&Instruction::LocalGet(l_ipv4_a));
f.instruction(&Instruction::LocalGet(l_ipv4_b));
f.instruction(&Instruction::LocalGet(l_ipv4_c));
f.instruction(&Instruction::LocalGet(l_ipv4_d));
for _ in 0..6 {
f.instruction(&Instruction::I32Const(0));
}
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::Call(helpers.start_connect_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_resolve));
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(helpers.drop_tcp_socket_fn));
emit_err_with_segment(&mut f, indices.conn_err_segment_idx, indices.conn_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(helpers.socket_subscribe_fn));
f.instruction(&Instruction::LocalSet(l_pollable));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::LocalGet(l_pollable));
f.instruction(&Instruction::I32Store(mem4_pollable_in));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_POLLABLE_IN as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Const(SCRATCH_OFFSET_POLL as i32));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::Call(helpers.poll_fn));
f.instruction(&Instruction::LocalGet(l_pollable));
f.instruction(&Instruction::Call(helpers.drop_pollable_fn));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::Call(helpers.finish_connect_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load8U(mem1_resolve));
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(helpers.drop_tcp_socket_fn));
emit_err_with_segment(&mut f, indices.conn_err_segment_idx, indices.conn_err_len);
f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load(mem4_resolve_off4));
f.instruction(&Instruction::Call(helpers.drop_input_stream_fn));
f.instruction(&Instruction::LocalGet(l_scratch));
f.instruction(&Instruction::I32Load(mem4_resolve_off8));
f.instruction(&Instruction::Call(helpers.drop_output_stream_fn));
f.instruction(&Instruction::LocalGet(l_socket));
f.instruction(&Instruction::Call(helpers.drop_tcp_socket_fn));
f.instruction(&Instruction::Call(helpers.result_unit_string_ok_fn));
restore_bump(&mut f, l_saved_alloc, helpers.bump_alloc_ptr_global);
f.instruction(&Instruction::End);
f
}
pub(in crate::codegen::wasm_gc) fn emit_tcp_close(
indices: &TcpCloseIndices,
helpers: &TcpCloseHelperFns,
) -> Function {
use wasm_encoder::BlockType;
let slot_ref = ValType::Ref(wasm_encoder::RefType {
nullable: true,
heap_type: wasm_encoder::HeapType::Concrete(indices.tcp_slot_type_idx),
});
let mut f = Function::new(vec![
(2u32, ValType::I32),
(1u32, slot_ref),
(2u32, ValType::I32),
]);
let l_parsed_id: u32 = 1;
let l_slot_idx: u32 = 2;
let l_slot: u32 = 3;
let l_retptr: u32 = 4;
let l_saved_alloc: u32 = 5;
f.instruction(&Instruction::GlobalGet(helpers.bump_alloc_ptr_global));
f.instruction(&Instruction::LocalSet(l_saved_alloc));
let unknown_segment_idx = indices.unknown_segment_idx;
let unknown_len = indices.unknown_len;
let string_type_idx = indices.string_type_idx;
let result_err_fn = helpers.result_err_fn;
let bump_alloc_ptr_global = helpers.bump_alloc_ptr_global;
let emit_unknown_err = |f: &mut Function| {
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(unknown_len as i32));
f.instruction(&Instruction::ArrayNewData {
array_type_index: string_type_idx,
array_data_index: unknown_segment_idx,
});
f.instruction(&Instruction::Call(result_err_fn));
restore_bump(f, l_saved_alloc, bump_alloc_ptr_global);
f.instruction(&Instruction::Return);
};
f.instruction(&Instruction::LocalGet(0));
f.instruction(&Instruction::StructGet {
struct_type_index: indices.tcp_connection_type_idx,
field_index: 0, });
f.instruction(&Instruction::Call(helpers.parse_id_fn));
f.instruction(&Instruction::LocalSet(l_parsed_id));
f.instruction(&Instruction::GlobalGet(helpers.tcp_pool_global));
f.instruction(&Instruction::RefIsNull);
f.instruction(&Instruction::If(BlockType::Empty));
emit_unknown_err(&mut f);
f.instruction(&Instruction::End);
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::LocalSet(l_slot_idx));
f.instruction(&Instruction::Block(BlockType::Empty)); f.instruction(&Instruction::Loop(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_slot_idx));
f.instruction(&Instruction::I32Const(256));
f.instruction(&Instruction::I32GeU);
f.instruction(&Instruction::If(BlockType::Empty));
emit_unknown_err(&mut f);
f.instruction(&Instruction::End);
f.instruction(&Instruction::GlobalGet(helpers.tcp_pool_global));
f.instruction(&Instruction::LocalGet(l_slot_idx));
f.instruction(&Instruction::ArrayGet(indices.tcp_pool_type_idx));
f.instruction(&Instruction::LocalSet(l_slot));
f.instruction(&Instruction::LocalGet(l_slot));
f.instruction(&Instruction::RefIsNull);
f.instruction(&Instruction::I32Eqz);
f.instruction(&Instruction::If(BlockType::Empty));
f.instruction(&Instruction::LocalGet(l_slot));
f.instruction(&Instruction::StructGet {
struct_type_index: indices.tcp_slot_type_idx,
field_index: 4, });
f.instruction(&Instruction::LocalGet(l_parsed_id));
f.instruction(&Instruction::I32Eq);
f.instruction(&Instruction::LocalGet(l_slot));
f.instruction(&Instruction::StructGet {
struct_type_index: indices.tcp_slot_type_idx,
field_index: 3, });
f.instruction(&Instruction::I32And);
f.instruction(&Instruction::BrIf(2)); f.instruction(&Instruction::End); f.instruction(&Instruction::LocalGet(l_slot_idx));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::LocalSet(l_slot_idx));
f.instruction(&Instruction::Br(0)); f.instruction(&Instruction::End); f.instruction(&Instruction::End);
f.instruction(&Instruction::LocalGet(l_slot));
f.instruction(&Instruction::StructGet {
struct_type_index: indices.tcp_slot_type_idx,
field_index: 1, });
f.instruction(&Instruction::Call(helpers.drop_input_stream_fn));
f.instruction(&Instruction::LocalGet(l_slot));
f.instruction(&Instruction::StructGet {
struct_type_index: indices.tcp_slot_type_idx,
field_index: 2, });
f.instruction(&Instruction::Call(helpers.drop_output_stream_fn));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::I32Const(1));
f.instruction(&Instruction::I32Const(2));
f.instruction(&Instruction::Call(helpers.cabi_realloc_fn));
f.instruction(&Instruction::LocalSet(l_retptr));
f.instruction(&Instruction::LocalGet(l_slot));
f.instruction(&Instruction::StructGet {
struct_type_index: indices.tcp_slot_type_idx,
field_index: 0, });
f.instruction(&Instruction::I32Const(2)); f.instruction(&Instruction::LocalGet(l_retptr));
f.instruction(&Instruction::Call(helpers.shutdown_fn));
f.instruction(&Instruction::LocalGet(l_slot));
f.instruction(&Instruction::StructGet {
struct_type_index: indices.tcp_slot_type_idx,
field_index: 0,
});
f.instruction(&Instruction::Call(helpers.drop_tcp_socket_fn));
f.instruction(&Instruction::LocalGet(l_slot));
f.instruction(&Instruction::I32Const(0));
f.instruction(&Instruction::StructSet {
struct_type_index: indices.tcp_slot_type_idx,
field_index: 3,
});
f.instruction(&Instruction::Call(helpers.result_ok_fn));
restore_bump(&mut f, l_saved_alloc, helpers.bump_alloc_ptr_global);
f.instruction(&Instruction::End);
f
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn close_emit_compiles() {
let indices = TcpCloseIndices {
fn_type: 0,
fn_idx: 0,
tcp_connection_type_idx: 1,
tcp_slot_type_idx: 2,
tcp_pool_type_idx: 3,
string_type_idx: 4,
unknown_segment_idx: 0,
unknown_len: b"tcp: unknown connection".len() as u32,
};
let helpers = TcpCloseHelperFns {
parse_id_fn: 4,
cabi_realloc_fn: 5,
shutdown_fn: 6,
drop_input_stream_fn: 7,
drop_output_stream_fn: 8,
drop_tcp_socket_fn: 9,
result_ok_fn: 10,
result_err_fn: 11,
tcp_pool_global: 0,
bump_alloc_ptr_global: 1,
};
let _f = emit_tcp_close(&indices, &helpers);
}
}