walrus/module/
memories.rs1use crate::emit::{Emit, EmitContext};
4use crate::map::IdHashSet;
5use crate::parse::IndicesToIds;
6use crate::tombstone_arena::{Id, Tombstone, TombstoneArena};
7use crate::{Data, ImportId, Module, Result};
8
9pub type MemoryId = Id<Memory>;
11
12#[derive(Debug)]
14pub struct Memory {
15 id: MemoryId,
16 pub shared: bool,
20 pub memory64: bool,
24 pub initial: u64,
26 pub maximum: Option<u64>,
28 pub page_size_log2: Option<u32>,
34 pub import: Option<ImportId>,
36 pub data_segments: IdHashSet<Data>,
38 pub name: Option<String>,
41}
42
43impl Tombstone for Memory {
44 fn on_delete(&mut self) {
45 self.data_segments = Default::default();
46 }
47}
48
49impl Memory {
50 pub fn id(&self) -> MemoryId {
52 self.id
53 }
54}
55
56#[derive(Debug, Default)]
58pub struct ModuleMemories {
59 arena: TombstoneArena<Memory>,
60}
61
62impl ModuleMemories {
63 pub fn add_import(
65 &mut self,
66 shared: bool,
67 memory64: bool,
68 initial: u64,
69 maximum: Option<u64>,
70 page_size_log2: Option<u32>,
71 import: ImportId,
72 ) -> MemoryId {
73 let id = self.arena.next_id();
74 let id2 = self.arena.alloc(Memory {
75 id,
76 shared,
77 memory64,
78 initial,
79 maximum,
80 page_size_log2,
81 import: Some(import),
82 data_segments: Default::default(),
83 name: None,
84 });
85 debug_assert_eq!(id, id2);
86 id
87 }
88
89 pub fn add_local(
92 &mut self,
93 shared: bool,
94 memory64: bool,
95 initial: u64,
96 maximum: Option<u64>,
97 page_size_log2: Option<u32>,
98 ) -> MemoryId {
99 let id = self.arena.next_id();
100 let id2 = self.arena.alloc(Memory {
101 id,
102 shared,
103 memory64,
104 initial,
105 maximum,
106 page_size_log2,
107 import: None,
108 data_segments: Default::default(),
109 name: None,
110 });
111 debug_assert_eq!(id, id2);
112 id
113 }
114
115 pub fn get(&self, id: MemoryId) -> &Memory {
117 &self.arena[id]
118 }
119
120 pub fn get_mut(&mut self, id: MemoryId) -> &mut Memory {
122 &mut self.arena[id]
123 }
124
125 pub fn delete(&mut self, id: MemoryId) {
130 self.arena.delete(id);
131 }
132
133 pub fn iter(&self) -> impl Iterator<Item = &Memory> {
135 self.arena.iter().map(|(_, f)| f)
136 }
137
138 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Memory> {
140 self.arena.iter_mut().map(|(_, f)| f)
141 }
142
143 pub fn len(&self) -> usize {
145 self.arena.len()
146 }
147
148 pub fn is_empty(&self) -> bool {
150 self.arena.len() == 0
151 }
152}
153
154impl Module {
155 pub(crate) fn parse_memories(
157 &mut self,
158 section: wasmparser::MemorySectionReader,
159 ids: &mut IndicesToIds,
160 ) -> Result<()> {
161 log::debug!("parse memory section");
162 for m in section {
163 let m = m?;
164 let id = self.memories.add_local(
165 m.shared,
166 m.memory64,
167 m.initial,
168 m.maximum,
169 m.page_size_log2,
170 );
171 ids.push_memory(id);
172 }
173 Ok(())
174 }
175}
176
177impl Emit for ModuleMemories {
178 fn emit(&self, cx: &mut EmitContext) {
179 log::debug!("emit memory section");
180
181 let mut wasm_memory_section = wasm_encoder::MemorySection::new();
182
183 let memories = self.iter().filter(|m| m.import.is_none()).count();
185 if memories == 0 {
186 return;
187 }
188
189 for memory in self.iter().filter(|m| m.import.is_none()) {
190 cx.indices.push_memory(memory.id());
191
192 wasm_memory_section.memory(wasm_encoder::MemoryType {
193 minimum: memory.initial,
194 maximum: memory.maximum,
195 memory64: memory.memory64,
196 shared: memory.shared,
197 page_size_log2: memory.page_size_log2,
198 });
199 }
200
201 cx.wasm_module.section(&wasm_memory_section);
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use crate::Module;
208
209 #[test]
210 fn memories_len() {
211 let mut module = Module::default();
212 assert_eq!(module.memories.len(), 0);
213
214 module.memories.add_local(false, false, 0, Some(1024), None);
215 assert_eq!(module.memories.len(), 1);
216
217 module
218 .memories
219 .add_local(true, true, 1024, Some(2048), Some(16));
220 assert_eq!(module.memories.len(), 2);
221 }
222}