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