1 //! Offsets and sizes of various structs in wasmtime-runtime's vmcontext
2 //! module.
3
4 // Currently the `VMContext` allocation by field looks like this:
5 //
6 // struct VMContext {
7 // interrupts: *const VMInterrupts,
8 // signature_ids: [VMSharedSignatureIndex; module.num_signature_ids],
9 // imported_functions: [VMFunctionImport; module.num_imported_functions],
10 // imported_tables: [VMTableImport; module.num_imported_tables],
11 // imported_memories: [VMMemoryImport; module.num_imported_memories],
12 // imported_globals: [VMGlobalImport; module.num_imported_globals],
13 // tables: [VMTableDefinition; module.num_defined_tables],
14 // memories: [VMMemoryDefinition; module.num_defined_memories],
15 // globals: [VMGlobalDefinition; module.num_defined_globals],
16 // builtins: VMBuiltinFunctionsArray,
17 // }
18
19 use crate::module::ModuleLocal;
20 use crate::BuiltinFunctionIndex;
21 use cranelift_codegen::ir;
22 use cranelift_wasm::{
23 DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, GlobalIndex, MemoryIndex,
24 SignatureIndex, TableIndex,
25 };
26 use more_asserts::assert_lt;
27 use std::convert::TryFrom;
28
29 /// Sentinel value indicating that wasm has been interrupted.
30 // Note that this has a bit of an odd definition. See the `insert_stack_check`
31 // function in `cranelift/codegen/src/isa/x86/abi.rs` for more information
32 pub const INTERRUPTED: usize = usize::max_value() - 32 * 1024;
33
34 #[cfg(target_pointer_width = "32")]
cast_to_u32(sz: usize) -> u3235 fn cast_to_u32(sz: usize) -> u32 {
36 u32::try_from(sz).unwrap()
37 }
38 #[cfg(target_pointer_width = "64")]
cast_to_u32(sz: usize) -> u3239 fn cast_to_u32(sz: usize) -> u32 {
40 u32::try_from(sz).expect("overflow in cast from usize to u32")
41 }
42
43 /// Align an offset used in this module to a specific byte-width by rounding up
align(offset: u32, width: u32) -> u3244 fn align(offset: u32, width: u32) -> u32 {
45 (offset + (width - 1)) / width * width
46 }
47
48 /// This class computes offsets to fields within `VMContext` and other
49 /// related structs that JIT code accesses directly.
50 pub struct VMOffsets {
51 /// The size in bytes of a pointer on the target.
52 pub pointer_size: u8,
53 /// The number of signature declarations in the module.
54 pub num_signature_ids: u32,
55 /// The number of imported functions in the module.
56 pub num_imported_functions: u32,
57 /// The number of imported tables in the module.
58 pub num_imported_tables: u32,
59 /// The number of imported memories in the module.
60 pub num_imported_memories: u32,
61 /// The number of imported globals in the module.
62 pub num_imported_globals: u32,
63 /// The number of defined tables in the module.
64 pub num_defined_tables: u32,
65 /// The number of defined memories in the module.
66 pub num_defined_memories: u32,
67 /// The number of defined globals in the module.
68 pub num_defined_globals: u32,
69 }
70
71 impl VMOffsets {
72 /// Return a new `VMOffsets` instance, for a given pointer size.
new(pointer_size: u8, module: &ModuleLocal) -> Self73 pub fn new(pointer_size: u8, module: &ModuleLocal) -> Self {
74 Self {
75 pointer_size,
76 num_signature_ids: cast_to_u32(module.signatures.len()),
77 num_imported_functions: cast_to_u32(module.num_imported_funcs),
78 num_imported_tables: cast_to_u32(module.num_imported_tables),
79 num_imported_memories: cast_to_u32(module.num_imported_memories),
80 num_imported_globals: cast_to_u32(module.num_imported_globals),
81 num_defined_tables: cast_to_u32(module.table_plans.len()),
82 num_defined_memories: cast_to_u32(module.memory_plans.len()),
83 num_defined_globals: cast_to_u32(module.globals.len()),
84 }
85 }
86 }
87
88 /// Offsets for `VMFunctionImport`.
89 impl VMOffsets {
90 /// The offset of the `body` field.
91 #[allow(clippy::erasing_op)]
vmfunction_import_body(&self) -> u892 pub fn vmfunction_import_body(&self) -> u8 {
93 0 * self.pointer_size
94 }
95
96 /// The offset of the `vmctx` field.
97 #[allow(clippy::identity_op)]
vmfunction_import_vmctx(&self) -> u898 pub fn vmfunction_import_vmctx(&self) -> u8 {
99 1 * self.pointer_size
100 }
101
102 /// Return the size of `VMFunctionImport`.
size_of_vmfunction_import(&self) -> u8103 pub fn size_of_vmfunction_import(&self) -> u8 {
104 2 * self.pointer_size
105 }
106 }
107
108 /// Offsets for `*const VMFunctionBody`.
109 impl VMOffsets {
110 /// The size of the `current_elements` field.
111 #[allow(clippy::identity_op)]
size_of_vmfunction_body_ptr(&self) -> u8112 pub fn size_of_vmfunction_body_ptr(&self) -> u8 {
113 1 * self.pointer_size
114 }
115 }
116
117 /// Offsets for `VMTableImport`.
118 impl VMOffsets {
119 /// The offset of the `from` field.
120 #[allow(clippy::erasing_op)]
vmtable_import_from(&self) -> u8121 pub fn vmtable_import_from(&self) -> u8 {
122 0 * self.pointer_size
123 }
124
125 /// The offset of the `vmctx` field.
126 #[allow(clippy::identity_op)]
vmtable_import_vmctx(&self) -> u8127 pub fn vmtable_import_vmctx(&self) -> u8 {
128 1 * self.pointer_size
129 }
130
131 /// Return the size of `VMTableImport`.
size_of_vmtable_import(&self) -> u8132 pub fn size_of_vmtable_import(&self) -> u8 {
133 2 * self.pointer_size
134 }
135 }
136
137 /// Offsets for `VMTableDefinition`.
138 impl VMOffsets {
139 /// The offset of the `base` field.
140 #[allow(clippy::erasing_op)]
vmtable_definition_base(&self) -> u8141 pub fn vmtable_definition_base(&self) -> u8 {
142 0 * self.pointer_size
143 }
144
145 /// The offset of the `current_elements` field.
146 #[allow(clippy::identity_op)]
vmtable_definition_current_elements(&self) -> u8147 pub fn vmtable_definition_current_elements(&self) -> u8 {
148 1 * self.pointer_size
149 }
150
151 /// The size of the `current_elements` field.
size_of_vmtable_definition_current_elements(&self) -> u8152 pub fn size_of_vmtable_definition_current_elements(&self) -> u8 {
153 4
154 }
155
156 /// Return the size of `VMTableDefinition`.
size_of_vmtable_definition(&self) -> u8157 pub fn size_of_vmtable_definition(&self) -> u8 {
158 2 * self.pointer_size
159 }
160
161 /// The type of the `current_elements` field.
type_of_vmtable_definition_current_elements(&self) -> ir::Type162 pub fn type_of_vmtable_definition_current_elements(&self) -> ir::Type {
163 ir::Type::int(u16::from(self.size_of_vmtable_definition_current_elements()) * 8).unwrap()
164 }
165 }
166
167 /// Offsets for `VMMemoryImport`.
168 impl VMOffsets {
169 /// The offset of the `from` field.
170 #[allow(clippy::erasing_op)]
vmmemory_import_from(&self) -> u8171 pub fn vmmemory_import_from(&self) -> u8 {
172 0 * self.pointer_size
173 }
174
175 /// The offset of the `vmctx` field.
176 #[allow(clippy::identity_op)]
vmmemory_import_vmctx(&self) -> u8177 pub fn vmmemory_import_vmctx(&self) -> u8 {
178 1 * self.pointer_size
179 }
180
181 /// Return the size of `VMMemoryImport`.
size_of_vmmemory_import(&self) -> u8182 pub fn size_of_vmmemory_import(&self) -> u8 {
183 2 * self.pointer_size
184 }
185 }
186
187 /// Offsets for `VMMemoryDefinition`.
188 impl VMOffsets {
189 /// The offset of the `base` field.
190 #[allow(clippy::erasing_op)]
vmmemory_definition_base(&self) -> u8191 pub fn vmmemory_definition_base(&self) -> u8 {
192 0 * self.pointer_size
193 }
194
195 /// The offset of the `current_length` field.
196 #[allow(clippy::identity_op)]
vmmemory_definition_current_length(&self) -> u8197 pub fn vmmemory_definition_current_length(&self) -> u8 {
198 1 * self.pointer_size
199 }
200
201 /// The size of the `current_length` field.
size_of_vmmemory_definition_current_length(&self) -> u8202 pub fn size_of_vmmemory_definition_current_length(&self) -> u8 {
203 4
204 }
205
206 /// Return the size of `VMMemoryDefinition`.
size_of_vmmemory_definition(&self) -> u8207 pub fn size_of_vmmemory_definition(&self) -> u8 {
208 2 * self.pointer_size
209 }
210
211 /// The type of the `current_length` field.
type_of_vmmemory_definition_current_length(&self) -> ir::Type212 pub fn type_of_vmmemory_definition_current_length(&self) -> ir::Type {
213 ir::Type::int(u16::from(self.size_of_vmmemory_definition_current_length()) * 8).unwrap()
214 }
215 }
216
217 /// Offsets for `VMGlobalImport`.
218 impl VMOffsets {
219 /// The offset of the `from` field.
220 #[allow(clippy::erasing_op)]
vmglobal_import_from(&self) -> u8221 pub fn vmglobal_import_from(&self) -> u8 {
222 0 * self.pointer_size
223 }
224
225 /// Return the size of `VMGlobalImport`.
226 #[allow(clippy::identity_op)]
size_of_vmglobal_import(&self) -> u8227 pub fn size_of_vmglobal_import(&self) -> u8 {
228 1 * self.pointer_size
229 }
230 }
231
232 /// Offsets for `VMGlobalDefinition`.
233 impl VMOffsets {
234 /// Return the size of `VMGlobalDefinition`; this is the size of the largest value type (i.e. a
235 /// V128).
size_of_vmglobal_definition(&self) -> u8236 pub fn size_of_vmglobal_definition(&self) -> u8 {
237 16
238 }
239 }
240
241 /// Offsets for `VMSharedSignatureIndex`.
242 impl VMOffsets {
243 /// Return the size of `VMSharedSignatureIndex`.
size_of_vmshared_signature_index(&self) -> u8244 pub fn size_of_vmshared_signature_index(&self) -> u8 {
245 4
246 }
247 }
248
249 /// Offsets for `VMInterrupts`.
250 impl VMOffsets {
251 /// Return the offset of the `stack_limit` field of `VMInterrupts`
vminterrupts_stack_limit(&self) -> u8252 pub fn vminterrupts_stack_limit(&self) -> u8 {
253 0
254 }
255 }
256
257 /// Offsets for `VMCallerCheckedAnyfunc`.
258 impl VMOffsets {
259 /// The offset of the `func_ptr` field.
260 #[allow(clippy::erasing_op)]
vmcaller_checked_anyfunc_func_ptr(&self) -> u8261 pub fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 {
262 0 * self.pointer_size
263 }
264
265 /// The offset of the `type_index` field.
266 #[allow(clippy::identity_op)]
vmcaller_checked_anyfunc_type_index(&self) -> u8267 pub fn vmcaller_checked_anyfunc_type_index(&self) -> u8 {
268 1 * self.pointer_size
269 }
270
271 /// The offset of the `vmctx` field.
vmcaller_checked_anyfunc_vmctx(&self) -> u8272 pub fn vmcaller_checked_anyfunc_vmctx(&self) -> u8 {
273 2 * self.pointer_size
274 }
275
276 /// Return the size of `VMCallerCheckedAnyfunc`.
size_of_vmcaller_checked_anyfunc(&self) -> u8277 pub fn size_of_vmcaller_checked_anyfunc(&self) -> u8 {
278 3 * self.pointer_size
279 }
280 }
281
282 /// Offsets for `VMContext`.
283 impl VMOffsets {
284 /// Return the offset to the `VMInterrupts` structure
vmctx_interrupts(&self) -> u32285 pub fn vmctx_interrupts(&self) -> u32 {
286 0
287 }
288
289 /// The offset of the `signature_ids` array.
vmctx_signature_ids_begin(&self) -> u32290 pub fn vmctx_signature_ids_begin(&self) -> u32 {
291 self.vmctx_interrupts()
292 .checked_add(u32::from(self.pointer_size))
293 .unwrap()
294 }
295
296 /// The offset of the `tables` array.
297 #[allow(clippy::erasing_op)]
vmctx_imported_functions_begin(&self) -> u32298 pub fn vmctx_imported_functions_begin(&self) -> u32 {
299 self.vmctx_signature_ids_begin()
300 .checked_add(
301 self.num_signature_ids
302 .checked_mul(u32::from(self.size_of_vmshared_signature_index()))
303 .unwrap(),
304 )
305 .unwrap()
306 }
307
308 /// The offset of the `tables` array.
309 #[allow(clippy::identity_op)]
vmctx_imported_tables_begin(&self) -> u32310 pub fn vmctx_imported_tables_begin(&self) -> u32 {
311 self.vmctx_imported_functions_begin()
312 .checked_add(
313 self.num_imported_functions
314 .checked_mul(u32::from(self.size_of_vmfunction_import()))
315 .unwrap(),
316 )
317 .unwrap()
318 }
319
320 /// The offset of the `memories` array.
vmctx_imported_memories_begin(&self) -> u32321 pub fn vmctx_imported_memories_begin(&self) -> u32 {
322 self.vmctx_imported_tables_begin()
323 .checked_add(
324 self.num_imported_tables
325 .checked_mul(u32::from(self.size_of_vmtable_import()))
326 .unwrap(),
327 )
328 .unwrap()
329 }
330
331 /// The offset of the `globals` array.
vmctx_imported_globals_begin(&self) -> u32332 pub fn vmctx_imported_globals_begin(&self) -> u32 {
333 self.vmctx_imported_memories_begin()
334 .checked_add(
335 self.num_imported_memories
336 .checked_mul(u32::from(self.size_of_vmmemory_import()))
337 .unwrap(),
338 )
339 .unwrap()
340 }
341
342 /// The offset of the `tables` array.
vmctx_tables_begin(&self) -> u32343 pub fn vmctx_tables_begin(&self) -> u32 {
344 self.vmctx_imported_globals_begin()
345 .checked_add(
346 self.num_imported_globals
347 .checked_mul(u32::from(self.size_of_vmglobal_import()))
348 .unwrap(),
349 )
350 .unwrap()
351 }
352
353 /// The offset of the `memories` array.
vmctx_memories_begin(&self) -> u32354 pub fn vmctx_memories_begin(&self) -> u32 {
355 self.vmctx_tables_begin()
356 .checked_add(
357 self.num_defined_tables
358 .checked_mul(u32::from(self.size_of_vmtable_definition()))
359 .unwrap(),
360 )
361 .unwrap()
362 }
363
364 /// The offset of the `globals` array.
vmctx_globals_begin(&self) -> u32365 pub fn vmctx_globals_begin(&self) -> u32 {
366 let offset = self
367 .vmctx_memories_begin()
368 .checked_add(
369 self.num_defined_memories
370 .checked_mul(u32::from(self.size_of_vmmemory_definition()))
371 .unwrap(),
372 )
373 .unwrap();
374 align(offset, 16)
375 }
376
377 /// The offset of the builtin functions array.
vmctx_builtin_functions_begin(&self) -> u32378 pub fn vmctx_builtin_functions_begin(&self) -> u32 {
379 self.vmctx_globals_begin()
380 .checked_add(
381 self.num_defined_globals
382 .checked_mul(u32::from(self.size_of_vmglobal_definition()))
383 .unwrap(),
384 )
385 .unwrap()
386 }
387
388 /// Return the size of the `VMContext` allocation.
size_of_vmctx(&self) -> u32389 pub fn size_of_vmctx(&self) -> u32 {
390 self.vmctx_builtin_functions_begin()
391 .checked_add(
392 BuiltinFunctionIndex::builtin_functions_total_number()
393 .checked_mul(u32::from(self.pointer_size))
394 .unwrap(),
395 )
396 .unwrap()
397 }
398
399 /// Return the offset to `VMSharedSignatureId` index `index`.
vmctx_vmshared_signature_id(&self, index: SignatureIndex) -> u32400 pub fn vmctx_vmshared_signature_id(&self, index: SignatureIndex) -> u32 {
401 assert_lt!(index.as_u32(), self.num_signature_ids);
402 self.vmctx_signature_ids_begin()
403 .checked_add(
404 index
405 .as_u32()
406 .checked_mul(u32::from(self.size_of_vmshared_signature_index()))
407 .unwrap(),
408 )
409 .unwrap()
410 }
411
412 /// Return the offset to `VMFunctionImport` index `index`.
vmctx_vmfunction_import(&self, index: FuncIndex) -> u32413 pub fn vmctx_vmfunction_import(&self, index: FuncIndex) -> u32 {
414 assert_lt!(index.as_u32(), self.num_imported_functions);
415 self.vmctx_imported_functions_begin()
416 .checked_add(
417 index
418 .as_u32()
419 .checked_mul(u32::from(self.size_of_vmfunction_import()))
420 .unwrap(),
421 )
422 .unwrap()
423 }
424
425 /// Return the offset to `VMTableImport` index `index`.
vmctx_vmtable_import(&self, index: TableIndex) -> u32426 pub fn vmctx_vmtable_import(&self, index: TableIndex) -> u32 {
427 assert_lt!(index.as_u32(), self.num_imported_tables);
428 self.vmctx_imported_tables_begin()
429 .checked_add(
430 index
431 .as_u32()
432 .checked_mul(u32::from(self.size_of_vmtable_import()))
433 .unwrap(),
434 )
435 .unwrap()
436 }
437
438 /// Return the offset to `VMMemoryImport` index `index`.
vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32439 pub fn vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32 {
440 assert_lt!(index.as_u32(), self.num_imported_memories);
441 self.vmctx_imported_memories_begin()
442 .checked_add(
443 index
444 .as_u32()
445 .checked_mul(u32::from(self.size_of_vmmemory_import()))
446 .unwrap(),
447 )
448 .unwrap()
449 }
450
451 /// Return the offset to `VMGlobalImport` index `index`.
vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32452 pub fn vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32 {
453 assert_lt!(index.as_u32(), self.num_imported_globals);
454 self.vmctx_imported_globals_begin()
455 .checked_add(
456 index
457 .as_u32()
458 .checked_mul(u32::from(self.size_of_vmglobal_import()))
459 .unwrap(),
460 )
461 .unwrap()
462 }
463
464 /// Return the offset to `VMTableDefinition` index `index`.
vmctx_vmtable_definition(&self, index: DefinedTableIndex) -> u32465 pub fn vmctx_vmtable_definition(&self, index: DefinedTableIndex) -> u32 {
466 assert_lt!(index.as_u32(), self.num_defined_tables);
467 self.vmctx_tables_begin()
468 .checked_add(
469 index
470 .as_u32()
471 .checked_mul(u32::from(self.size_of_vmtable_definition()))
472 .unwrap(),
473 )
474 .unwrap()
475 }
476
477 /// Return the offset to `VMMemoryDefinition` index `index`.
vmctx_vmmemory_definition(&self, index: DefinedMemoryIndex) -> u32478 pub fn vmctx_vmmemory_definition(&self, index: DefinedMemoryIndex) -> u32 {
479 assert_lt!(index.as_u32(), self.num_defined_memories);
480 self.vmctx_memories_begin()
481 .checked_add(
482 index
483 .as_u32()
484 .checked_mul(u32::from(self.size_of_vmmemory_definition()))
485 .unwrap(),
486 )
487 .unwrap()
488 }
489
490 /// Return the offset to the `VMGlobalDefinition` index `index`.
vmctx_vmglobal_definition(&self, index: DefinedGlobalIndex) -> u32491 pub fn vmctx_vmglobal_definition(&self, index: DefinedGlobalIndex) -> u32 {
492 assert_lt!(index.as_u32(), self.num_defined_globals);
493 self.vmctx_globals_begin()
494 .checked_add(
495 index
496 .as_u32()
497 .checked_mul(u32::from(self.size_of_vmglobal_definition()))
498 .unwrap(),
499 )
500 .unwrap()
501 }
502
503 /// Return the offset to the `body` field in `*const VMFunctionBody` index `index`.
vmctx_vmfunction_import_body(&self, index: FuncIndex) -> u32504 pub fn vmctx_vmfunction_import_body(&self, index: FuncIndex) -> u32 {
505 self.vmctx_vmfunction_import(index)
506 .checked_add(u32::from(self.vmfunction_import_body()))
507 .unwrap()
508 }
509
510 /// Return the offset to the `vmctx` field in `*const VMFunctionBody` index `index`.
vmctx_vmfunction_import_vmctx(&self, index: FuncIndex) -> u32511 pub fn vmctx_vmfunction_import_vmctx(&self, index: FuncIndex) -> u32 {
512 self.vmctx_vmfunction_import(index)
513 .checked_add(u32::from(self.vmfunction_import_vmctx()))
514 .unwrap()
515 }
516
517 /// Return the offset to the `from` field in `VMTableImport` index `index`.
vmctx_vmtable_import_from(&self, index: TableIndex) -> u32518 pub fn vmctx_vmtable_import_from(&self, index: TableIndex) -> u32 {
519 self.vmctx_vmtable_import(index)
520 .checked_add(u32::from(self.vmtable_import_from()))
521 .unwrap()
522 }
523
524 /// Return the offset to the `base` field in `VMTableDefinition` index `index`.
vmctx_vmtable_definition_base(&self, index: DefinedTableIndex) -> u32525 pub fn vmctx_vmtable_definition_base(&self, index: DefinedTableIndex) -> u32 {
526 self.vmctx_vmtable_definition(index)
527 .checked_add(u32::from(self.vmtable_definition_base()))
528 .unwrap()
529 }
530
531 /// Return the offset to the `current_elements` field in `VMTableDefinition` index `index`.
vmctx_vmtable_definition_current_elements(&self, index: DefinedTableIndex) -> u32532 pub fn vmctx_vmtable_definition_current_elements(&self, index: DefinedTableIndex) -> u32 {
533 self.vmctx_vmtable_definition(index)
534 .checked_add(u32::from(self.vmtable_definition_current_elements()))
535 .unwrap()
536 }
537
538 /// Return the offset to the `from` field in `VMMemoryImport` index `index`.
vmctx_vmmemory_import_from(&self, index: MemoryIndex) -> u32539 pub fn vmctx_vmmemory_import_from(&self, index: MemoryIndex) -> u32 {
540 self.vmctx_vmmemory_import(index)
541 .checked_add(u32::from(self.vmmemory_import_from()))
542 .unwrap()
543 }
544
545 /// Return the offset to the `vmctx` field in `VMMemoryImport` index `index`.
vmctx_vmmemory_import_vmctx(&self, index: MemoryIndex) -> u32546 pub fn vmctx_vmmemory_import_vmctx(&self, index: MemoryIndex) -> u32 {
547 self.vmctx_vmmemory_import(index)
548 .checked_add(u32::from(self.vmmemory_import_vmctx()))
549 .unwrap()
550 }
551
552 /// Return the offset to the `base` field in `VMMemoryDefinition` index `index`.
vmctx_vmmemory_definition_base(&self, index: DefinedMemoryIndex) -> u32553 pub fn vmctx_vmmemory_definition_base(&self, index: DefinedMemoryIndex) -> u32 {
554 self.vmctx_vmmemory_definition(index)
555 .checked_add(u32::from(self.vmmemory_definition_base()))
556 .unwrap()
557 }
558
559 /// Return the offset to the `current_length` field in `VMMemoryDefinition` index `index`.
vmctx_vmmemory_definition_current_length(&self, index: DefinedMemoryIndex) -> u32560 pub fn vmctx_vmmemory_definition_current_length(&self, index: DefinedMemoryIndex) -> u32 {
561 self.vmctx_vmmemory_definition(index)
562 .checked_add(u32::from(self.vmmemory_definition_current_length()))
563 .unwrap()
564 }
565
566 /// Return the offset to the `from` field in `VMGlobalImport` index `index`.
vmctx_vmglobal_import_from(&self, index: GlobalIndex) -> u32567 pub fn vmctx_vmglobal_import_from(&self, index: GlobalIndex) -> u32 {
568 self.vmctx_vmglobal_import(index)
569 .checked_add(u32::from(self.vmglobal_import_from()))
570 .unwrap()
571 }
572
573 /// Return the offset to builtin function in `VMBuiltinFunctionsArray` index `index`.
vmctx_builtin_function(&self, index: BuiltinFunctionIndex) -> u32574 pub fn vmctx_builtin_function(&self, index: BuiltinFunctionIndex) -> u32 {
575 self.vmctx_builtin_functions_begin()
576 .checked_add(
577 index
578 .index()
579 .checked_mul(u32::from(self.pointer_size))
580 .unwrap(),
581 )
582 .unwrap()
583 }
584 }
585
586 /// Offsets for `VMExternData`.
587 impl VMOffsets {
588 /// Return the offset for `VMExternData::ref_count`.
vm_extern_data_ref_count() -> u32589 pub fn vm_extern_data_ref_count() -> u32 {
590 0
591 }
592 }
593
594 /// Target specific type for shared signature index.
595 #[derive(Debug, Copy, Clone)]
596 pub struct TargetSharedSignatureIndex(u32);
597
598 impl TargetSharedSignatureIndex {
599 /// Constructs `TargetSharedSignatureIndex`.
new(value: u32) -> Self600 pub fn new(value: u32) -> Self {
601 Self(value)
602 }
603
604 /// Returns index value.
index(self) -> u32605 pub fn index(self) -> u32 {
606 self.0
607 }
608 }
609
610 #[cfg(test)]
611 mod tests {
612 use crate::vmoffsets::align;
613
614 #[test]
alignment()615 fn alignment() {
616 fn is_aligned(x: u32) -> bool {
617 x % 16 == 0
618 }
619 assert!(is_aligned(align(0, 16)));
620 assert!(is_aligned(align(32, 16)));
621 assert!(is_aligned(align(33, 16)));
622 assert!(is_aligned(align(31, 16)));
623 }
624 }
625