Virtual_machine/
Instance.rs

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]

use core::ffi::c_void;

use wamr_rust_sdk::{
    function::Function,
    instance::Instance,
    sys::{
        wasm_runtime_addr_app_to_native, wasm_runtime_addr_native_to_app,
        wasm_runtime_get_custom_data, wasm_runtime_validate_native_addr,
    },
    value::WasmValue,
};

use crate::{
    Custom_data_type, Error_type, Module::Module_type, Result_type, Runtime::Runtime_type,
    WASM_pointer_type,
};

pub struct Instance_type<'module> {
    Instance: Instance<'module>,
}

unsafe impl Send for Instance_type<'_> {}

impl Drop for Instance_type<'_> {
    fn drop(&mut self) {
        let Instance = self.Get_inner_reference().get_inner_instance();
        unsafe {
            let User_data = wasm_runtime_get_custom_data(Instance) as *mut Custom_data_type;

            if !User_data.is_null() {
                let _ = Box::from_raw(User_data);
            }
        }

        // User data is dropped here.
    }
}

impl<'module> Instance_type<'module> {
    pub fn New(
        Runtime: &Runtime_type,
        Module: &'module Module_type<'module>,
        Stack_size: usize,
    ) -> Result_type<Self> {
        let WAMR_instance = Instance::new(
            Runtime.Get_inner_reference(),
            Module.Get_inner_reference(),
            Stack_size as u32,
        )?;

        let Instance = Instance_type {
            Instance: WAMR_instance,
        };

        Ok(Instance)
    }

    pub fn Validate_native_pointer<T>(&self, Pointer: *const T, Size: usize) -> bool {
        unsafe {
            wasm_runtime_validate_native_addr(
                self.Get_inner_reference().get_inner_instance(),
                Pointer as *mut c_void,
                Size as u64,
            )
        }
    }

    pub fn Validate_WASM_pointer(&self, Address: WASM_pointer_type, Size: usize) -> bool {
        unsafe {
            wasm_runtime_validate_native_addr(
                self.Get_inner_reference().get_inner_instance(),
                Address as *mut c_void,
                Size as u64,
            )
        }
    }

    pub fn Convert_to_WASM_pointer<T>(&self, Pointer: *const T) -> WASM_pointer_type {
        unsafe {
            wasm_runtime_addr_native_to_app(
                self.Get_inner_reference().get_inner_instance(),
                Pointer as *mut c_void,
            ) as WASM_pointer_type
        }
    }

    /// # Safety
    ///
    /// This function is unsafe because it is not checked that the address is valid.
    #[allow(clippy::mut_from_ref)]
    pub unsafe fn Convert_to_native_pointer<T>(&self, Address: WASM_pointer_type) -> *mut T {
        wasm_runtime_addr_app_to_native(
            self.Get_inner_reference().get_inner_instance(),
            Address as u64,
        ) as *mut T
    }

    pub fn Call_export_function(
        &self,
        Name: &str,
        Parameters: &Vec<WasmValue>,
    ) -> Result_type<Vec<WasmValue>> {
        if Parameters.is_empty() {
            Ok(
                Function::find_export_func(self.Get_inner_reference(), Name)?
                    .call(&self.Instance, &vec![WasmValue::I32(0)])?,
            )
        } else {
            Ok(
                Function::find_export_func(self.Get_inner_reference(), Name)?
                    .call(&self.Instance, Parameters)?,
            )
        }
    }

    pub fn Call_main(&self, Parameters: &Vec<WasmValue>) -> Result_type<Vec<WasmValue>> {
        self.Call_export_function("_start", Parameters)
    }

    pub fn Allocate<T>(&mut self, Size: usize) -> Result_type<*mut T> {
        let Result = self.Call_export_function("Allocate", &vec![WasmValue::I32(Size as i32)])?;

        if let Some(WasmValue::I32(Pointer)) = Result.first() {
            let Pointer = unsafe { self.Convert_to_native_pointer(*Pointer as u32) };

            Ok(Pointer)
        } else {
            Err(Error_type::Allocation_failure)
        }
    }

    pub fn Deallocate<T>(&mut self, Data: *mut T) {
        let _ = self.Call_export_function("Deallocate", &vec![WasmValue::I32(Data as i32)]);
    }

    pub(crate) fn Get_inner_reference(&self) -> &Instance {
        &self.Instance
    }
}