1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! Byte-offset allocator for the tier-1 adapter's linear memory.
//!
//! Every slot the adapter reserves in the dispatch module's memory —
//! function-name bytes, async and sync-complex result buffers, the
//! `waitable-set.wait` event record, the `should-block-call` bool
//! slot, and the start of the bump allocator — goes through
//! [`MemoryLayoutBuilder`]. Centralizing the math in one place keeps
//! the extraction phase (which assigns per-func offsets) and the
//! build phase (which assigns the fixed post-func slots and the
//! bump-allocator start) from re-deriving cursor positions by
//! iterating the func table.
//!
//! The layout emitted by a normal run is:
//!
//! ```text
//! [0 .. total_name_bytes) concatenated UTF-8 function names
//! [i32-aligned .. …) per-func result buffers
//! - async results pack contiguously
//! - sync-complex results re-align to i32
//! [… .. +sum(EVENT_RECORD_SHAPE)) event slot (if has_async_machinery)
//! [… .. +sum(BLOCK_RESULT_SHAPE)) block slot (if has_blocking)
//! i64-aligned upward bump_start (consumed on finish)
//! ```
//!
//! Call ordering matters: the builder is single-cursor across the
//! post-name region, so callers must allocate in the order sections
//! appear above. [`super::func::extract_adapter_funcs`] handles the
//! name + per-func result passes; [`super::component`] finishes the
//! layout with the event / block / bump calls.
use ValType;
/// Byte size of a core Wasm value type in linear memory.
/// Round `offset` up to the nearest multiple of `align`.
// ─── Slot shapes ───────────────────────────────────────────────────────────
//
// Every fixed slot the builder reserves in the post-name region
// corresponds to a canonical-ABI record with a known flat core-Wasm
// shape. We declare the SHAPE here; [`MemoryLayoutBuilder::alloc_record`]
// derives size and natural alignment from the shape so the numbers
// the allocator uses can't drift out of sync with the dispatch
// module's loads/stores that read and write those bytes.
//
// Per-region alignment choices live inline in the allocator methods
// below, each expressed as `val_type_byte_size(&ValType::<the
// relevant slot type>)` — so "4" and "8" never appear as raw literals;
// the numbers fall out of the ValTypes they belong to.
/// Flat shape of the event record `waitable-set.wait` writes:
/// `(event_code: i32, waitable_handle: i32)`. The wait-loop in the
/// dispatch module reads both halves via `i32.load` at
/// `event_ptr + 0` and `event_ptr + 4`.
const EVENT_RECORD_SHAPE: & = &;
/// Flat shape of the bool slot `should-block-call` writes. The
/// canonical ABI stores a bool as an i32; the blocking phase
/// (see `super::dispatch::emit_blocking_phase`) reads it via
/// `i32.load` at `block_result_ptr + 0` and branches on zero /
/// non-zero.
const BLOCK_RESULT_SHAPE: & = &;
/// Byte-offset bookkeeper for the dispatch module's linear memory.
/// See the module docs for the overall layout and call-ordering rules.
pub