wamr_rust_sdk/
instance.rs

1/*
2 * Copyright (C) 2019 Intel Corporation. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4 */
5
6//! an instantiated module. The module is instantiated with the given imports.
7//! get one via `Instance::new()`
8
9#![allow(unused_variables)]
10
11use core::{ffi::c_char, marker::PhantomData};
12
13use wamr_sys::{
14    wasm_module_inst_t, wasm_runtime_deinstantiate, wasm_runtime_destroy_thread_env,
15    wasm_runtime_init_thread_env, wasm_runtime_instantiate,
16};
17
18use crate::{
19    helper::error_buf_to_string, helper::DEFAULT_ERROR_BUF_SIZE, module::Module, runtime::Runtime,
20    RuntimeError,
21};
22
23#[derive(Debug)]
24pub struct Instance<'module> {
25    instance: wasm_module_inst_t,
26    _phantom: PhantomData<Module<'module>>,
27}
28
29impl<'module> Instance<'module> {
30    /// instantiate a module with stack size
31    ///
32    /// # Error
33    ///
34    /// Return `RuntimeError::CompilationError` if failed.
35    pub fn new(
36        runtime: &Runtime,
37        module: &'module Module<'module>,
38        stack_size: u32,
39    ) -> Result<Self, RuntimeError> {
40        Self::new_with_args(runtime, module, stack_size, 0)
41    }
42
43    /// instantiate a module with stack size and host managed heap size
44    ///
45    /// heap_size is used for `-nostdlib` Wasm and wasm32-unknown
46    ///
47    /// # Error
48    ///
49    /// Return `RuntimeError::CompilationError` if failed.
50    pub fn new_with_args(
51        _runtime: &Runtime,
52        module: &'module Module<'module>,
53        stack_size: u32,
54        heap_size: u32,
55    ) -> Result<Self, RuntimeError> {
56        let init_thd_env = unsafe { wasm_runtime_init_thread_env() };
57        if !init_thd_env {
58            return Err(RuntimeError::InstantiationFailure(String::from(
59                "thread signal env initialized failed",
60            )));
61        }
62
63        let mut error_buf = [0 as c_char; DEFAULT_ERROR_BUF_SIZE];
64        let instance = unsafe {
65            wasm_runtime_instantiate(
66                module.get_inner_module(),
67                stack_size,
68                heap_size,
69                error_buf.as_mut_ptr(),
70                error_buf.len() as u32,
71            )
72        };
73
74        if instance.is_null() {
75            match error_buf.len() {
76                0 => {
77                    return Err(RuntimeError::InstantiationFailure(String::from(
78                        "instantiation failed",
79                    )))
80                }
81                _ => {
82                    return Err(RuntimeError::InstantiationFailure(error_buf_to_string(
83                        &error_buf,
84                    )))
85                }
86            }
87        }
88
89        Ok(Instance {
90            instance,
91            _phantom: PhantomData,
92        })
93    }
94
95    pub fn get_inner_instance(&self) -> wasm_module_inst_t {
96        self.instance
97    }
98}
99
100impl Drop for Instance<'_> {
101    fn drop(&mut self) {
102        unsafe {
103            wasm_runtime_destroy_thread_env();
104            wasm_runtime_deinstantiate(self.instance);
105        }
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112    use crate::runtime::Runtime;
113    use wamr_sys::{
114        wasm_runtime_get_running_mode, RunningMode_Mode_Interp, RunningMode_Mode_LLVM_JIT,
115    };
116
117    #[test]
118    fn test_instance_new() {
119        let runtime = Runtime::new().unwrap();
120
121        // (module
122        //   (func (export "add") (param i32 i32) (result i32)
123        //     (local.get 0)
124        //     (local.get 1)
125        //     (i32.add)
126        //   )
127        // )
128        let binary = vec![
129            0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f,
130            0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64,
131            0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b,
132        ];
133        let binary = binary.into_iter().map(|c| c as u8).collect::<Vec<u8>>();
134
135        let module = Module::from_vec(&runtime, binary, "add");
136        assert!(module.is_ok());
137
138        let module = &module.unwrap();
139
140        let instance = Instance::new_with_args(&runtime, module, 1024, 1024);
141        assert!(instance.is_ok());
142
143        let instance = Instance::new_with_args(&runtime, module, 1024, 0);
144        assert!(instance.is_ok());
145
146        let instance = instance.unwrap();
147        assert_eq!(
148            unsafe { wasm_runtime_get_running_mode(instance.get_inner_instance()) },
149            if cfg!(feature = "llvmjit") {
150                RunningMode_Mode_LLVM_JIT
151            } else {
152                RunningMode_Mode_Interp
153            }
154        );
155    }
156
157    #[test]
158    #[ignore]
159    fn test_instance_running_mode_default() {
160        let runtime = Runtime::builder().use_system_allocator().build().unwrap();
161
162        // (module
163        //   (func (export "add") (param i32 i32) (result i32)
164        //     (local.get 0)
165        //     (local.get 1)
166        //     (i32.add)
167        //   )
168        // )
169        let binary = vec![
170            0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f,
171            0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64,
172            0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b,
173        ];
174        let binary = binary.into_iter().map(|c| c as u8).collect::<Vec<u8>>();
175
176        let module = Module::from_vec(&runtime, binary, "");
177        assert!(module.is_ok());
178
179        let module = &module.unwrap();
180
181        let instance = Instance::new_with_args(&runtime, module, 1024, 1024);
182        assert!(instance.is_ok());
183
184        let instance = instance.unwrap();
185        assert_eq!(
186            unsafe { wasm_runtime_get_running_mode(instance.get_inner_instance()) },
187            if cfg!(feature = "llvmjit") {
188                RunningMode_Mode_LLVM_JIT
189            } else {
190                RunningMode_Mode_Interp
191            }
192        );
193    }
194
195    #[test]
196    #[ignore]
197    fn test_instance_running_mode_interpreter() {
198        let runtime = Runtime::builder()
199            .run_as_interpreter()
200            .use_system_allocator()
201            .build()
202            .unwrap();
203
204        // (module
205        //   (func (export "add") (param i32 i32) (result i32)
206        //     (local.get 0)
207        //     (local.get 1)
208        //     (i32.add)
209        //   )
210        // )
211        let binary = vec![
212            0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f,
213            0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, 0x61, 0x64, 0x64,
214            0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b,
215        ];
216        let binary = binary.into_iter().map(|c| c as u8).collect::<Vec<u8>>();
217
218        let module = Module::from_vec(&runtime, binary, "add");
219        assert!(module.is_ok());
220
221        let module = &module.unwrap();
222
223        let instance = Instance::new_with_args(&runtime, module, 1024, 1024);
224        assert!(instance.is_ok());
225
226        let instance = instance.unwrap();
227        assert_eq!(
228            unsafe { wasm_runtime_get_running_mode(instance.get_inner_instance()) },
229            RunningMode_Mode_Interp
230        );
231    }
232}