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
#![allow(clippy::cast_ptr_alignment)]
use more_asserts::assert_le;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::ptr;
use wasmtime_environ::entity::EntityRef;
use wasmtime_environ::isa::TargetFrontendConfig;
use wasmtime_environ::wasm::GlobalInit;
use wasmtime_environ::{Module, ModuleType, TargetSharedSignatureIndex, VMOffsets};
pub struct TableRelocation {
pub index: usize,
pub offset: usize,
}
pub fn layout_vmcontext(
module: &Module,
target_config: &TargetFrontendConfig,
) -> (Box<[u8]>, Box<[TableRelocation]>) {
let ofs = VMOffsets::new(target_config.pointer_bytes(), &module);
let out_len = ofs.size_of_vmctx() as usize;
let mut out = vec![0; out_len];
let mut signature_registry = HashMap::new();
let mut signature_registry_len = signature_registry.len();
for (index, sig) in module.types.iter() {
let offset = ofs.vmctx_vmshared_signature_id(index) as usize;
let target_index = match sig {
ModuleType::Function(sig) => match signature_registry.entry(sig) {
Entry::Occupied(o) => *o.get(),
Entry::Vacant(v) => {
assert_le!(signature_registry_len, std::u32::MAX as usize);
let id = TargetSharedSignatureIndex::new(signature_registry_len as u32);
signature_registry_len += 1;
*v.insert(id)
}
},
_ => TargetSharedSignatureIndex::new(u32::max_value()),
};
unsafe {
let to = out.as_mut_ptr().add(offset) as *mut TargetSharedSignatureIndex;
ptr::write(to, target_index);
}
}
let num_tables_imports = module.num_imported_tables;
let mut table_relocs = Vec::with_capacity(module.table_plans.len() - num_tables_imports);
for (index, table) in module.table_plans.iter().skip(num_tables_imports) {
let def_index = module.defined_table_index(index).unwrap();
let offset = ofs.vmctx_vmtable_definition(def_index) as usize;
let current_elements = table.table.minimum;
unsafe {
assert_eq!(
::std::mem::size_of::<u32>() as u8,
ofs.size_of_vmtable_definition_current_elements(),
"vmtable_definition_current_elements expected to be u32"
);
let to = out
.as_mut_ptr()
.add(offset)
.add(ofs.vmtable_definition_current_elements() as usize);
ptr::write(to as *mut u32, current_elements);
}
table_relocs.push(TableRelocation {
index: def_index.index(),
offset,
});
}
let num_globals_imports = module.num_imported_globals;
for (index, global) in module.globals.iter().skip(num_globals_imports) {
let def_index = module.defined_global_index(index).unwrap();
let offset = ofs.vmctx_vmglobal_definition(def_index) as usize;
let to = unsafe { out.as_mut_ptr().add(offset) };
match global.initializer {
GlobalInit::I32Const(x) => unsafe {
ptr::write(to as *mut i32, x);
},
GlobalInit::I64Const(x) => unsafe {
ptr::write(to as *mut i64, x);
},
GlobalInit::F32Const(x) => unsafe {
ptr::write(to as *mut u32, x);
},
GlobalInit::F64Const(x) => unsafe {
ptr::write(to as *mut u64, x);
},
_ => panic!("unsupported global type"),
}
}
(out.into_boxed_slice(), table_relocs.into_boxed_slice())
}