use wasm_encoder::Instruction;
use crate::ast::{Expr, Spanned};
use super::super::WasmGcError;
use super::emit::emit_expr;
use super::{EmitCtx, SlotTable};
pub(super) fn emit_console_print_wasip2(
func: &mut wasm_encoder::Function,
method: &str,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation(
"emit_console_print_wasip2 invoked without wasip2 lowering ctx".into(),
)
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Console.{method} on `--target wasip2` expects 1 arg (the String), got {}",
args.len()
)));
}
let scratch = slots.console_print_wasip2_scratch.ok_or_else(|| {
WasmGcError::Validation(
"Console.* on wasip2: [len, offset] scratch slots were not allocated by \
SlotTable — `fn_needs_console_print_wasip2_scratch` did not flag this fn"
.into(),
)
})?;
let len_local = scratch[0];
let off_local = scratch[1];
let (handle_global, get_fn) = match method {
"print" => (
lowering.stdout_handle_global.ok_or_else(|| {
WasmGcError::Validation(
"Console.print on wasip2: stdout_handle global missing — \
wasip2_imports did not register CliGetStdout"
.into(),
)
})?,
lowering.get_stdout_fn_idx.ok_or_else(|| {
WasmGcError::Validation("Console.print on wasip2: get_stdout fn idx missing".into())
})?,
),
"error" | "warn" => (
lowering.stderr_handle_global.ok_or_else(|| {
WasmGcError::Validation(
"Console.error/warn on wasip2: stderr_handle global missing".into(),
)
})?,
lowering.get_stderr_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Console.error/warn on wasip2: get_stderr fn idx missing".into(),
)
})?,
),
_ => {
return Err(WasmGcError::Validation(format!(
"Console.{method} is not lowered on `--target wasip2`"
)));
}
};
func.instruction(&Instruction::GlobalGet(handle_global));
func.instruction(&Instruction::I32Const(-1));
func.instruction(&Instruction::I32Eq);
func.instruction(&Instruction::If(wasm_encoder::BlockType::Empty));
func.instruction(&Instruction::Call(get_fn));
func.instruction(&Instruction::GlobalSet(handle_global));
func.instruction(&Instruction::End);
let str_to_lm = lowering.str_to_lm_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Console.* on wasip2: __rt_string_to_lm fn idx missing — bridge not allocated".into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?;
func.instruction(&Instruction::Call(str_to_lm));
func.instruction(&Instruction::LocalSet(len_local));
func.instruction(&Instruction::I32Const(1));
func.instruction(&Instruction::MemoryGrow(0));
func.instruction(&Instruction::Drop);
let write_fn = lowering.blocking_write_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Console.* on wasip2: blocking-write-and-flush fn idx missing".into(),
)
})?;
super::super::wasip2_helpers::emit_chunked_blocking_write(
func,
len_local,
off_local,
write_fn,
&|f| {
f.instruction(&Instruction::GlobalGet(handle_global));
},
&|f| {
f.instruction(&Instruction::LocalGet(len_local));
f.instruction(&Instruction::I32Const(15));
f.instruction(&Instruction::I32Add);
f.instruction(&Instruction::I32Const(-16));
f.instruction(&Instruction::I32And);
},
None,
);
Ok(())
}
pub(super) fn emit_args_get_wasip2(
func: &mut wasm_encoder::Function,
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Args.get on wasip2: lowering ctx missing".into())
})?;
let cabi_realloc = lowering.cabi_realloc_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Args.get on wasip2: cabi_realloc fn idx missing — wasip2_imports must register \
at least one slot for cabi_realloc to be allocated"
.into(),
)
})?;
let get_arguments = lowering.get_arguments_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Args.get on wasip2: wasi:cli/environment.get-arguments fn idx missing".into(),
)
})?;
let decoder = lowering.decode_list_string_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Args.get on wasip2: __rt_canonical_decode_list_string fn idx missing".into(),
)
})?;
let retptr_local = slots.args_get_wasip2_retptr_scratch.ok_or_else(|| {
WasmGcError::Validation(
"Args.get on wasip2: i32 retptr scratch slot missing — \
SlotTable should have allocated via fn_needs_args_get_scratch"
.into(),
)
})?;
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Const(4));
func.instruction(&Instruction::I32Const(8));
func.instruction(&Instruction::Call(cabi_realloc));
func.instruction(&Instruction::LocalSet(retptr_local));
func.instruction(&Instruction::LocalGet(retptr_local));
func.instruction(&Instruction::Call(get_arguments));
func.instruction(&Instruction::LocalGet(retptr_local));
func.instruction(&Instruction::Call(decoder));
Ok(())
}
pub(super) fn emit_env_get_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx
.wasip2_lowering
.ok_or_else(|| WasmGcError::Validation("Env.get on wasip2: lowering ctx missing".into()))?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Env.get on `--target wasip2` expects 1 arg (the key String), got {}",
args.len()
)));
}
let str_to_lm = lowering.str_to_lm_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Env.get on wasip2: __rt_string_to_lm fn idx missing — bridge not allocated".into(),
)
})?;
let cabi_realloc = lowering.cabi_realloc_fn_idx.ok_or_else(|| {
WasmGcError::Validation("Env.get on wasip2: cabi_realloc fn idx missing".into())
})?;
let get_environment = lowering.get_environment_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Env.get on wasip2: wasi:cli/environment.get-environment fn idx missing".into(),
)
})?;
let lookup = lowering.env_get_lookup_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Env.get on wasip2: __rt_canonical_env_lookup fn idx missing".into(),
)
})?;
let scratch = slots.env_get_wasip2_scratch.ok_or_else(|| {
WasmGcError::Validation(
"Env.get on wasip2: [retptr, key_len] scratch pair missing — \
SlotTable should have allocated via fn_needs_env_get_wasip2_scratch"
.into(),
)
})?;
let retptr_local = scratch[0];
let key_len_local = scratch[1];
emit_expr(func, &args[0], slots, ctx)?;
func.instruction(&Instruction::Call(str_to_lm));
func.instruction(&Instruction::LocalSet(key_len_local));
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Const(4));
func.instruction(&Instruction::I32Const(8));
func.instruction(&Instruction::Call(cabi_realloc));
func.instruction(&Instruction::LocalSet(retptr_local));
func.instruction(&Instruction::LocalGet(retptr_local));
func.instruction(&Instruction::Call(get_environment));
func.instruction(&Instruction::LocalGet(retptr_local));
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::LocalGet(key_len_local));
func.instruction(&Instruction::Call(lookup));
Ok(())
}
pub(super) fn emit_time_unix_ms_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Time.unixMs on wasip2: lowering ctx missing".into())
})?;
if !args.is_empty() {
return Err(WasmGcError::Validation(format!(
"Time.unixMs on `--target wasip2` expects 0 args, got {}",
args.len()
)));
}
let now_fn = lowering.clocks_now_fn_idx.ok_or_else(|| {
WasmGcError::Validation("Time.unixMs on wasip2: clocks-now fn idx missing".into())
})?;
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::Call(now_fn));
let mem_arg = wasm_encoder::MemArg {
offset: 0,
align: 3, memory_index: 0,
};
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I64Load(mem_arg));
func.instruction(&Instruction::I64Const(1000));
func.instruction(&Instruction::I64Mul);
let ns_mem_arg = wasm_encoder::MemArg {
offset: 8,
align: 2, memory_index: 0,
};
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Load(ns_mem_arg));
func.instruction(&Instruction::I64ExtendI32U);
func.instruction(&Instruction::I64Const(1_000_000));
func.instruction(&Instruction::I64DivU);
func.instruction(&Instruction::I64Add);
Ok(())
}
pub(super) fn emit_time_now_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Time.now on wasip2: lowering ctx missing".into())
})?;
if !args.is_empty() {
return Err(WasmGcError::Validation(format!(
"Time.now on `--target wasip2` expects 0 args, got {}",
args.len()
)));
}
let now_fn = lowering.clocks_now_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Time.now on wasip2: clocks-now fn idx missing — slot not registered".into(),
)
})?;
let fmt_fn = lowering.fmt_iso8601_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Time.now on wasip2: __rt_format_iso8601 fn idx missing — helper not allocated".into(),
)
})?;
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::Call(now_fn));
let secs_mem = wasm_encoder::MemArg {
offset: 0,
align: 3, memory_index: 0,
};
let nanos_mem = wasm_encoder::MemArg {
offset: 8,
align: 2, memory_index: 0,
};
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I64Load(secs_mem));
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Load(nanos_mem));
func.instruction(&Instruction::Call(fmt_fn));
Ok(())
}
pub(super) fn emit_console_read_line_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Console.readLine on wasip2: lowering ctx missing".into())
})?;
if !args.is_empty() {
return Err(WasmGcError::Validation(format!(
"Console.readLine on `--target wasip2` expects 0 args, got {}",
args.len()
)));
}
let read_fn = lowering.console_read_line_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Console.readLine on wasip2: __rt_console_read_line fn idx missing — \
helper not allocated"
.into(),
)
})?;
func.instruction(&Instruction::Call(read_fn));
Ok(())
}
pub(super) fn emit_time_sleep_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Time.sleep on wasip2: lowering ctx missing".into())
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Time.sleep on `--target wasip2` expects 1 arg (ms: Int), got {}",
args.len()
)));
}
let sleep_fn = lowering.time_sleep_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Time.sleep on wasip2: __rt_time_sleep fn idx missing — helper not allocated".into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?; func.instruction(&Instruction::Call(sleep_fn));
Ok(())
}
pub(super) fn emit_disk_exists_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Disk.exists on wasip2: lowering ctx missing".into())
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Disk.exists on `--target wasip2` expects 1 arg (path: String), got {}",
args.len()
)));
}
let exists_fn = lowering.disk_exists_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Disk.exists on wasip2: __rt_disk_exists fn idx missing — \
helper not allocated"
.into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?; func.instruction(&Instruction::Call(exists_fn));
Ok(())
}
pub(super) fn emit_disk_read_text_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Disk.readText on wasip2: lowering ctx missing".into())
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Disk.readText on `--target wasip2` expects 1 arg (path: String), got {}",
args.len()
)));
}
let read_fn = lowering.disk_read_text_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Disk.readText on wasip2: __rt_disk_read_text fn idx missing — \
helper not allocated"
.into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?; func.instruction(&Instruction::Call(read_fn));
Ok(())
}
pub(super) fn emit_random_int_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Random.int on wasip2: lowering ctx missing".into())
})?;
if args.len() != 2 {
return Err(WasmGcError::Validation(format!(
"Random.int on `--target wasip2` expects 2 args (min, max), got {}",
args.len()
)));
}
let rand_fn = lowering.random_u64_fn_idx.ok_or_else(|| {
WasmGcError::Validation("Random.int on wasip2: random get-random-u64 fn idx missing".into())
})?;
let min_scratch = slots.random_int_wasip2_min_scratch.ok_or_else(|| {
WasmGcError::Validation(
"Random.int on wasip2: i64 min scratch slot missing — \
SlotTable should have allocated via fn_needs_random_int_wasip2_scratch"
.into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?; func.instruction(&Instruction::LocalSet(min_scratch));
func.instruction(&Instruction::LocalGet(min_scratch));
func.instruction(&Instruction::Call(rand_fn)); emit_expr(func, &args[1], slots, ctx)?; func.instruction(&Instruction::LocalGet(min_scratch));
func.instruction(&Instruction::I64Sub);
func.instruction(&Instruction::I64Const(1));
func.instruction(&Instruction::I64Add);
func.instruction(&Instruction::I64RemU); func.instruction(&Instruction::I64Add);
Ok(())
}
pub(super) fn emit_random_float_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Random.float on wasip2: lowering ctx missing".into())
})?;
if !args.is_empty() {
return Err(WasmGcError::Validation(format!(
"Random.float on `--target wasip2` expects 0 args, got {}",
args.len()
)));
}
let rand_fn = lowering.random_u64_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Random.float on wasip2: random get-random-u64 fn idx missing".into(),
)
})?;
func.instruction(&Instruction::Call(rand_fn));
func.instruction(&Instruction::I64Const(11));
func.instruction(&Instruction::I64ShrU);
func.instruction(&Instruction::F64ConvertI64U);
func.instruction(&Instruction::F64Const(
(1.0_f64 / (1u64 << 53) as f64).into(),
));
func.instruction(&Instruction::F64Mul);
Ok(())
}
pub(super) fn emit_disk_write_text_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Disk.writeText on wasip2: lowering ctx missing".into())
})?;
if args.len() != 2 {
return Err(WasmGcError::Validation(format!(
"Disk.writeText on `--target wasip2` expects 2 args (path, content), got {}",
args.len()
)));
}
let write_fn = lowering.disk_write_text_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Disk.writeText on wasip2: __rt_disk_write_text fn idx missing — \
helper not allocated"
.into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?; emit_expr(func, &args[1], slots, ctx)?; func.instruction(&Instruction::Call(write_fn));
Ok(())
}
pub(super) fn emit_disk_delete_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Disk.delete on wasip2: lowering ctx missing".into())
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Disk.delete on `--target wasip2` expects 1 arg (path), got {}",
args.len()
)));
}
let fn_idx = lowering.disk_delete_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Disk.delete on wasip2: __rt_disk_delete fn idx missing — helper not allocated".into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?;
func.instruction(&Instruction::Call(fn_idx));
Ok(())
}
pub(super) fn emit_disk_delete_dir_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Disk.deleteDir on wasip2: lowering ctx missing".into())
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Disk.deleteDir on `--target wasip2` expects 1 arg (path), got {}",
args.len()
)));
}
let fn_idx = lowering.disk_delete_dir_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Disk.deleteDir on wasip2: __rt_disk_delete_dir fn idx missing".into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?;
func.instruction(&Instruction::Call(fn_idx));
Ok(())
}
pub(super) fn emit_disk_make_dir_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Disk.makeDir on wasip2: lowering ctx missing".into())
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Disk.makeDir on `--target wasip2` expects 1 arg (path), got {}",
args.len()
)));
}
let fn_idx = lowering.disk_make_dir_fn_idx.ok_or_else(|| {
WasmGcError::Validation("Disk.makeDir on wasip2: __rt_disk_make_dir fn idx missing".into())
})?;
emit_expr(func, &args[0], slots, ctx)?;
func.instruction(&Instruction::Call(fn_idx));
Ok(())
}
pub(super) fn emit_disk_append_text_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Disk.appendText on wasip2: lowering ctx missing".into())
})?;
if args.len() != 2 {
return Err(WasmGcError::Validation(format!(
"Disk.appendText on `--target wasip2` expects 2 args (path, content), got {}",
args.len()
)));
}
let fn_idx = lowering.disk_append_text_fn_idx.ok_or_else(|| {
WasmGcError::Validation(
"Disk.appendText on wasip2: __rt_disk_append_text fn idx missing".into(),
)
})?;
emit_expr(func, &args[0], slots, ctx)?;
emit_expr(func, &args[1], slots, ctx)?;
func.instruction(&Instruction::Call(fn_idx));
Ok(())
}
pub(super) fn emit_disk_list_dir_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation("Disk.listDir on wasip2: lowering ctx missing".into())
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"Disk.listDir on `--target wasip2` expects 1 arg (path), got {}",
args.len()
)));
}
let fn_idx = lowering.disk_list_dir_fn_idx.ok_or_else(|| {
WasmGcError::Validation("Disk.listDir on wasip2: __rt_disk_list_dir fn idx missing".into())
})?;
emit_expr(func, &args[0], slots, ctx)?;
func.instruction(&Instruction::Call(fn_idx));
Ok(())
}
fn emit_http_simple_method_wasip2(
method_name: &str,
method_tag: i32,
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation(format!("{method_name} on wasip2: lowering ctx missing"))
})?;
if args.len() != 1 {
return Err(WasmGcError::Validation(format!(
"{method_name} on `--target wasip2` expects 1 arg (url), got {}",
args.len()
)));
}
let fn_idx = lowering.http_get_fn_idx.ok_or_else(|| {
WasmGcError::Validation(format!(
"{method_name} on wasip2: __rt_http_request fn idx missing"
))
})?;
let registry = ctx.registry;
let string_idx = registry.string_array_type_idx.ok_or_else(|| {
WasmGcError::Validation(format!("{method_name} on wasip2: string type idx missing"))
})?;
let map_slots = registry
.map_slots("Map<String,List<String>>")
.ok_or_else(|| {
WasmGcError::Validation(format!(
"{method_name} on wasip2: Map<String, List<String>> slots missing"
))
})?;
func.instruction(&Instruction::I32Const(method_tag));
emit_expr(func, &args[0], slots, ctx)?;
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::ArrayNewDefault(string_idx));
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::ArrayNewDefault(string_idx));
const INITIAL_CAP: i32 = 16384;
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Const(INITIAL_CAP));
func.instruction(&Instruction::I32Const(INITIAL_CAP));
func.instruction(&Instruction::ArrayNewDefault(map_slots.keys_array));
func.instruction(&Instruction::I32Const(INITIAL_CAP));
func.instruction(&Instruction::ArrayNewDefault(map_slots.values_array));
func.instruction(&Instruction::StructNew(map_slots.map));
func.instruction(&Instruction::Call(fn_idx));
Ok(())
}
fn emit_http_body_method_wasip2(
method_name: &str,
method_tag: i32,
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
let lowering = ctx.wasip2_lowering.ok_or_else(|| {
WasmGcError::Validation(format!("{method_name} on wasip2: lowering ctx missing"))
})?;
if args.len() != 4 {
return Err(WasmGcError::Validation(format!(
"{method_name} on `--target wasip2` expects 4 args (url, content_type, body, headers), got {}",
args.len()
)));
}
let fn_idx = lowering.http_get_fn_idx.ok_or_else(|| {
WasmGcError::Validation(format!(
"{method_name} on wasip2: __rt_http_request fn idx missing"
))
})?;
func.instruction(&Instruction::I32Const(method_tag));
emit_expr(func, &args[0], slots, ctx)?; emit_expr(func, &args[1], slots, ctx)?; emit_expr(func, &args[2], slots, ctx)?; emit_expr(func, &args[3], slots, ctx)?; func.instruction(&Instruction::Call(fn_idx));
Ok(())
}
pub(super) fn emit_http_get_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
emit_http_simple_method_wasip2("Http.get", 0, func, args, slots, ctx)
}
pub(super) fn emit_http_head_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
emit_http_simple_method_wasip2("Http.head", 1, func, args, slots, ctx)
}
pub(super) fn emit_http_delete_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
emit_http_simple_method_wasip2("Http.delete", 4, func, args, slots, ctx)
}
pub(super) fn emit_http_post_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
emit_http_body_method_wasip2("Http.post", 2, func, args, slots, ctx)
}
pub(super) fn emit_http_put_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
emit_http_body_method_wasip2("Http.put", 3, func, args, slots, ctx)
}
pub(super) fn emit_http_patch_wasip2(
func: &mut wasm_encoder::Function,
args: &[Spanned<Expr>],
slots: &SlotTable,
ctx: &EmitCtx<'_>,
) -> Result<(), WasmGcError> {
emit_http_body_method_wasip2("Http.patch", 8, func, args, slots, ctx)
}