1 #pragma once
2 #include <string_view>
3 
4 #define CHECK_ERR(err)                                                         \
5   do {                                                                         \
6     if (err) {                                                                 \
7       auto msg = wasm_name_t{};                                                \
8       wasmtime_error_message(err, &msg);                                       \
9       EXPECT_EQ(err, nullptr) << std::string_view{msg.data, msg.size};         \
10     }                                                                          \
11   } while (false)
12 
13 // From crates/component-util/src/lib.rs
14 inline constexpr std::string_view REALLOC_AND_FREE =
15     R"END(
16 (global $last (mut i32) (i32.const 8))
17 (func $realloc (export "realloc")
18 	(param $old_ptr i32)
19 	(param $old_size i32)
20 	(param $align i32)
21 	(param $new_size i32)
22 	(result i32)
23 
24 	(local $ret i32)
25 
26 	;; Test if the old pointer is non-null
27 	local.get $old_ptr
28 	if
29 		;; If the old size is bigger than the new size then
30 		;; this is a shrink and transparently allow it
31 		local.get $old_size
32 		local.get $new_size
33 		i32.gt_u
34 		if
35 			local.get $old_ptr
36 			return
37 		end
38 
39 		;; otherwise fall through to allocate a new chunk which will later
40 		;; copy data over
41 	end
42 
43 	;; align up `$last`
44 	(global.set $last
45 		(i32.and
46 			(i32.add
47 				(global.get $last)
48 				(i32.add
49 					(local.get $align)
50 					(i32.const -1)))
51 			(i32.xor
52 				(i32.add
53 					(local.get $align)
54 					(i32.const -1))
55 				(i32.const -1))))
56 
57 	;; save the current value of `$last` as the return value
58 	global.get $last
59 	local.set $ret
60 
61 	;; bump our pointer
62 	(global.set $last
63 		(i32.add
64 			(global.get $last)
65 			(local.get $new_size)))
66 
67 	;; while `memory.size` is less than `$last`, grow memory
68 	;; by one page
69 	(loop $loop
70 		(if
71 			(i32.lt_u
72 				(i32.mul (memory.size) (i32.const 65536))
73 				(global.get $last))
74 			(then
75 				i32.const 1
76 				memory.grow
77 				;; test to make sure growth succeeded
78 				i32.const -1
79 				i32.eq
80 				if unreachable end
81 
82 				br $loop)))
83 
84 
85 	;; ensure anything necessary is set to valid data by spraying a bit
86 	;; pattern that is invalid
87 	local.get $ret
88 	i32.const 0xde
89 	local.get $new_size
90 	memory.fill
91 
92 	;; If the old pointer is present then that means this was a reallocation
93 	;; of an existing chunk which means the existing data must be copied.
94 	local.get $old_ptr
95 	if
96 		local.get $ret          ;; destination
97 		local.get $old_ptr      ;; source
98 		local.get $old_size     ;; size
99 		memory.copy
100 	end
101 
102 	local.get $ret
103 )
104 )END";
105