ruka_codegen_wasm/memory_and_release/
string_ops.rs1use super::*;
2
3pub(crate) fn emit_string_release(
4 body: &mut walrus::InstrSeqBuilder,
5 runtime: &RuntimeFunctions,
6 memory_id: MemoryId,
7 string_local: LocalId,
8 scratch_ptr_local: LocalId,
9 scratch_header_local: LocalId,
10 scratch_len_local: LocalId,
11) -> Result<(), LowerError> {
12 let free = runtime_function(runtime, wasm_api::RT_FREE_BYTES_SYMBOL)?;
13 emit_string_release_with_free(
14 body,
15 memory_id,
16 string_local,
17 scratch_ptr_local,
18 scratch_header_local,
19 scratch_len_local,
20 free.function_id,
21 );
22 Ok(())
23}
24
25pub(crate) fn emit_string_release_with_free(
26 body: &mut walrus::InstrSeqBuilder,
27 memory_id: MemoryId,
28 string_local: LocalId,
29 scratch_ptr_local: LocalId,
30 scratch_header_local: LocalId,
31 scratch_len_local: LocalId,
32 free_id: FunctionId,
33) {
34 body.local_get(string_local)
35 .local_set(scratch_ptr_local)
36 .local_get(scratch_ptr_local)
37 .i32_const(0)
38 .binop(BinaryOp::I32Ne)
39 .if_else(
40 None,
41 |then_| {
42 then_
43 .local_get(scratch_ptr_local)
44 .instr(Load {
45 memory: memory_id,
46 kind: LoadKind::I32 { atomic: false },
47 arg: MemArg {
48 align: 4,
49 offset: STRING_HEADER_OFFSET,
50 },
51 })
52 .local_set(scratch_header_local)
53 .local_get(scratch_header_local)
54 .i32_const(0)
55 .binop(BinaryOp::I32Eq)
56 .if_else(
57 None,
58 |_static_literal| {},
59 |heap_string| {
60 heap_string
61 .local_get(scratch_ptr_local)
62 .instr(Load {
63 memory: memory_id,
64 kind: LoadKind::I32 { atomic: false },
65 arg: MemArg {
66 align: 4,
67 offset: STRING_LEN_OFFSET,
68 },
69 })
70 .local_set(scratch_len_local)
71 .local_get(scratch_ptr_local)
72 .local_get(scratch_len_local)
73 .i32_const(STRING_DATA_OFFSET as i32)
74 .binop(BinaryOp::I32Add)
75 .call(free_id);
76 },
77 );
78 },
79 |_else_| {},
80 );
81}