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
/*
* Wizer interface for Wasm module to be initialized.
*
* This header provides several macros that allow a Wasm module written in C/C++
* to declare an initializer function, and ensure that global constructors (in
* C++'s case) are run at initialization time rather than on startup of the
* pre-initialized module.
*/
// wasi-sdk-16 was the first wasi-sdk version that shipped with a version of
// wasi-libc that did not include __original_main. However, wasi-sdk-15 shipped
// with clang-14.0.0. To correctly identify the boundary where __original_main
// no longer exists, we check for either clang-15+ or specifically clang-14.0.4.
//
// wasi-sdk-17 ships with clang-15.0.6
// wasi-sdk-16 ships with clang-14.0.4
// We default to assuming that the compiler is new enough to provide
// __main_void.
/*
* This macro inserts the exported functions necessary to allow Wizer to
* pre-initialize a Wasm module.
*
* To use, simply invoke the macro in exactly one compilation unit (C/C++ file)
* that is compiled into the Wasm module to be pre-initialized:
*
* static void my_init_function() { ... }
*
* WIZER_INIT(my_init_function);
*
* (The macro refers to the provided init function, so it must have been defined
* or must have a forward declaration at the point the macro is used.)
*
* The resulting module should be processed by Wizer as follows:
*
* $ wizer -r _start=wizer.resume -o out.wasm in.wasm
*
* The result of this will be the following behavior:
*
* - If the `in.wasm` (the direct compilation output of a program including this
* macro invocation) is run directly according to the WASI ABI (i.e., by
* invoking `_start`), then nothing changes: global constructors are run,
* `main()` is invoked, then global destructors are run. The initialization
* function is *not* run in this case.
*
* - During pre-initialization (i.e., during this `wizer` invocation), global
* constructors will run, and then the provided initialization function will
* run. The module's memory and global-variable state is then snapshotted and
* saved into `out.wasm`.
*
* All other Wizer restrictions apply (see Wizer documentation for details):
* for example, WASI hostcalls may be blocked, depending on options, and
* invoking any other imported function will result in an immediate trap
* and failure of the Wizer run.
*
* - If the resulting `out.wasm` is then run using the WASI ABI, the program's
* global constructors are *not* re-run. Instead, execution starts directly at
* `main()`, using the heap and global-variable state left by the global
* constructor and initialization function execution during the Wizer
* invocation.
*
* If no initialization function is needed (i.e., only C++ global constructors
* should be run), use `WIZER_DEFAULT_INIT()` instead.
*/
/*
* This macro is like `WIZER_INIT()`, but takes no initialization function.
* Instead, the pre-initialization phase only executes C++ global constructors
* before snapshotting the module state.
*
* See documentation for `WIZER_INIT()` for more details and usage instructions.
*/
// _WIZER_H_