1use std::ffi::c_void;
11
12use wamr_sys::{
13 mem_alloc_type_t_Alloc_With_Pool, mem_alloc_type_t_Alloc_With_System_Allocator,
14 wasm_runtime_destroy, wasm_runtime_full_init, wasm_runtime_init, NativeSymbol,
15 RunningMode_Mode_Interp, RunningMode_Mode_LLVM_JIT, RuntimeInitArgs,
16};
17
18use crate::{host_function::HostFunctionList, RuntimeError};
19
20#[allow(dead_code)]
21#[derive(Debug)]
22pub struct Runtime {
23 host_functions: HostFunctionList,
24}
25
26impl Runtime {
27 pub fn builder() -> RuntimeBuilder {
33 RuntimeBuilder::default()
34 }
35
36 pub fn new() -> Result<Self, RuntimeError> {
44 match unsafe { wasm_runtime_init() } {
45 true => Ok(Runtime {
46 host_functions: HostFunctionList::new("empty"),
47 }),
48 false => Err(RuntimeError::InitializationFailure),
49 }
50 }
51}
52
53impl Drop for Runtime {
54 fn drop(&mut self) {
55 unsafe {
56 wasm_runtime_destroy();
57 }
58 }
59}
60
61pub struct RuntimeBuilder {
64 args: RuntimeInitArgs,
65 host_functions: HostFunctionList,
66}
67
68impl Default for RuntimeBuilder {
70 fn default() -> Self {
71 let args = RuntimeInitArgs::default();
72 RuntimeBuilder {
73 args,
74 host_functions: HostFunctionList::new("host"),
75 }
76 }
77}
78
79impl RuntimeBuilder {
80 pub fn use_system_allocator(mut self) -> RuntimeBuilder {
83 self.args.mem_alloc_type = mem_alloc_type_t_Alloc_With_System_Allocator;
84 self
85 }
86
87 pub fn use_memory_pool(mut self, mut pool: Vec<u8>) -> RuntimeBuilder {
90 self.args.mem_alloc_type = mem_alloc_type_t_Alloc_With_Pool;
91 self.args.mem_alloc_option.pool.heap_buf = pool.as_mut_ptr() as *mut c_void;
92 self.args.mem_alloc_option.pool.heap_size = pool.len() as u32;
93 self
94 }
95
96 pub fn run_as_interpreter(mut self) -> RuntimeBuilder {
98 self.args.running_mode = RunningMode_Mode_Interp;
99 self
100 }
101
102 pub fn run_as_llvm_jit(mut self, opt_level: u32, size_level: u32) -> RuntimeBuilder {
104 self.args.running_mode = RunningMode_Mode_LLVM_JIT;
105 self.args.llvm_jit_opt_level = opt_level;
106 self.args.llvm_jit_size_level = size_level;
107 self
108 }
109
110 pub fn register_host_function(
112 mut self,
113 function_name: &str,
114 function_ptr: *mut c_void,
115 ) -> RuntimeBuilder {
116 self.host_functions
117 .register_host_function(function_name, function_ptr);
118 self
119 }
120
121 pub fn build(mut self) -> Result<Runtime, RuntimeError> {
127 match unsafe {
128 let module_name = &(self.host_functions).get_module_name();
129 self.args.native_module_name = module_name.as_ptr();
130
131 let native_symbols = &(self.host_functions).get_native_symbols();
132 self.args.n_native_symbols = native_symbols.len() as u32;
133 self.args.native_symbols = native_symbols.as_ptr() as *mut NativeSymbol;
134
135 wasm_runtime_full_init(&mut self.args)
136 } {
137 true => Ok(Runtime {
138 host_functions: self.host_functions,
139 }),
140 false => Err(RuntimeError::InitializationFailure),
141 }
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use wamr_sys::{wasm_runtime_free, wasm_runtime_malloc};
149
150 #[test]
151 #[ignore]
152 fn test_runtime_new() {
153 let runtime = Runtime::new();
154 assert!(runtime.is_ok());
155
156 let small_buf = unsafe { wasm_runtime_malloc(16) };
158 assert!(!small_buf.is_null());
159 unsafe { wasm_runtime_free(small_buf) };
160
161 drop(runtime);
162
163 let small_buf = unsafe { wasm_runtime_malloc(16) };
165 assert!(small_buf.is_null());
166
167 {
168 let runtime = Runtime::new();
169 assert!(runtime.is_ok());
170
171 let runtime = Runtime::new();
172 assert!(runtime.is_ok());
173
174 let runtime = Runtime::new();
175 assert!(runtime.is_ok());
176 }
177
178 let small_buf = unsafe { wasm_runtime_malloc(16) };
180 assert!(small_buf.is_null());
181 }
182
183 #[test]
184 fn test_runtime_builder_default() {
185 let runtime = Runtime::builder().use_system_allocator().build();
187 assert!(runtime.is_ok());
188
189 let small_buf = unsafe { wasm_runtime_malloc(16) };
190 assert!(!small_buf.is_null());
191 unsafe { wasm_runtime_free(small_buf) };
192 }
193
194 #[test]
195 fn test_runtime_builder_interpreter() {
196 let runtime = Runtime::builder()
197 .run_as_interpreter()
198 .use_system_allocator()
199 .build();
200 assert!(runtime.is_ok());
201
202 let small_buf = unsafe { wasm_runtime_malloc(16) };
203 assert!(!small_buf.is_null());
204 unsafe { wasm_runtime_free(small_buf) };
205 }
206
207 #[test]
208 #[cfg(feature = "llvmjit")]
209 #[ignore]
210 fn test_runtime_builder_llvm_jit() {
211 let runtime = Runtime::builder()
212 .run_as_llvm_jit(3, 3)
213 .use_system_allocator()
214 .build();
215 assert!(runtime.is_ok());
216
217 let small_buf = unsafe { wasm_runtime_malloc(16) };
218 assert!(!small_buf.is_null());
219 unsafe { wasm_runtime_free(small_buf) };
220 }
221}