1//
2// Wasm3, high performance WebAssembly interpreter
3//
4// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy.
5// All rights reserved.
6//
7
8#ifndef wasm3_h
9#define wasm3_h
10
11#define M3_VERSION_MAJOR 0
12#define M3_VERSION_MINOR 5
13#define M3_VERSION_REV 0
14#define M3_VERSION "0.5.0"
15
16#include <stdlib.h>
17#include <stdint.h>
18#include <inttypes.h>
19#include <stdarg.h>
20
21#include "wasm3_defs.h"
22
23// Constants
24#define M3_BACKTRACE_TRUNCATED (void*)(SIZE_MAX)
25
26#if defined(__cplusplus)
27extern "C" {
28#endif
29
30typedef const char * M3Result;
31
32struct M3Environment; typedef struct M3Environment * IM3Environment;
33struct M3Runtime; typedef struct M3Runtime * IM3Runtime;
34struct M3Module; typedef struct M3Module * IM3Module;
35struct M3Function; typedef struct M3Function * IM3Function;
36struct M3Global; typedef struct M3Global * IM3Global;
37
38typedef struct M3ErrorInfo
39{
40 M3Result result;
41
42 IM3Runtime runtime;
43 IM3Module module;
44 IM3Function function;
45
46 const char * file;
47 uint32_t line;
48
49 const char * message;
50} M3ErrorInfo;
51
52typedef struct M3BacktraceFrame
53{
54 uint32_t moduleOffset;
55 IM3Function function;
56
57 struct M3BacktraceFrame * next;
58}
59M3BacktraceFrame, * IM3BacktraceFrame;
60
61typedef struct M3BacktraceInfo
62{
63 IM3BacktraceFrame frames;
64 IM3BacktraceFrame lastFrame; // can be M3_BACKTRACE_TRUNCATED
65}
66M3BacktraceInfo, * IM3BacktraceInfo;
67
68
69typedef enum M3ValueType
70{
71 c_m3Type_none = 0,
72 c_m3Type_i32 = 1,
73 c_m3Type_i64 = 2,
74 c_m3Type_f32 = 3,
75 c_m3Type_f64 = 4,
76
77 c_m3Type_unknown
78} M3ValueType;
79
80typedef struct M3TaggedValue
81{
82 M3ValueType type;
83 union M3ValueUnion
84 {
85 uint32_t i32;
86 uint64_t i64;
87 float f32;
88 double f64;
89 } value;
90}
91M3TaggedValue, * IM3TaggedValue;
92
93typedef struct M3ImportInfo
94{
95 const char * moduleUtf8;
96 const char * fieldUtf8;
97}
98M3ImportInfo, * IM3ImportInfo;
99
100
101typedef struct M3ImportContext
102{
103 void * userdata;
104 IM3Function function;
105}
106M3ImportContext, * IM3ImportContext;
107
108// -------------------------------------------------------------------------------------------------------------------------------
109// error codes
110// -------------------------------------------------------------------------------------------------------------------------------
111
112# if defined(M3_IMPLEMENT_ERROR_STRINGS)
113# define d_m3ErrorConst(LABEL, STRING) extern const M3Result m3Err_##LABEL = { STRING };
114# else
115# define d_m3ErrorConst(LABEL, STRING) extern const M3Result m3Err_##LABEL;
116# endif
117
118// -------------------------------------------------------------------------------------------------------------------------------
119
120d_m3ErrorConst (none, NULL)
121
122// general errors
123d_m3ErrorConst (mallocFailed, "memory allocation failed")
124
125// parse errors
126d_m3ErrorConst (incompatibleWasmVersion, "incompatible Wasm binary version")
127d_m3ErrorConst (wasmMalformed, "malformed Wasm binary")
128d_m3ErrorConst (misorderedWasmSection, "out of order Wasm section")
129d_m3ErrorConst (wasmUnderrun, "underrun while parsing Wasm binary")
130d_m3ErrorConst (wasmOverrun, "overrun while parsing Wasm binary")
131d_m3ErrorConst (wasmMissingInitExpr, "missing init_expr in Wasm binary")
132d_m3ErrorConst (lebOverflow, "LEB encoded value overflow")
133d_m3ErrorConst (missingUTF8, "invalid length UTF-8 string")
134d_m3ErrorConst (wasmSectionUnderrun, "section underrun while parsing Wasm binary")
135d_m3ErrorConst (wasmSectionOverrun, "section overrun while parsing Wasm binary")
136d_m3ErrorConst (invalidTypeId, "unknown value_type")
137d_m3ErrorConst (tooManyMemorySections, "only one memory per module is supported")
138d_m3ErrorConst (tooManyArgsRets, "too many arguments or return values")
139
140// link errors
141d_m3ErrorConst (moduleNotLinked, "attempting to use module that is not loaded")
142d_m3ErrorConst (moduleAlreadyLinked, "attempting to bind module to multiple runtimes")
143d_m3ErrorConst (functionLookupFailed, "function lookup failed")
144d_m3ErrorConst (functionImportMissing, "missing imported function")
145
146d_m3ErrorConst (malformedFunctionSignature, "malformed function signature")
147
148// compilation errors
149d_m3ErrorConst (noCompiler, "no compiler found for opcode")
150d_m3ErrorConst (unknownOpcode, "unknown opcode")
151d_m3ErrorConst (restrictedOpcode, "restricted opcode")
152d_m3ErrorConst (functionStackOverflow, "compiling function overran its stack height limit")
153d_m3ErrorConst (functionStackUnderrun, "compiling function underran the stack")
154d_m3ErrorConst (mallocFailedCodePage, "memory allocation failed when acquiring a new M3 code page")
155d_m3ErrorConst (settingImmutableGlobal, "attempting to set an immutable global")
156d_m3ErrorConst (typeMismatch, "incorrect type on stack")
157d_m3ErrorConst (typeCountMismatch, "incorrect value count on stack")
158
159// runtime errors
160d_m3ErrorConst (missingCompiledCode, "function is missing compiled m3 code")
161d_m3ErrorConst (wasmMemoryOverflow, "runtime ran out of memory")
162d_m3ErrorConst (globalMemoryNotAllocated, "global memory is missing from a module")
163d_m3ErrorConst (globaIndexOutOfBounds, "global index is too large")
164d_m3ErrorConst (argumentCountMismatch, "argument count mismatch")
165d_m3ErrorConst (argumentTypeMismatch, "argument type mismatch")
166d_m3ErrorConst (globalLookupFailed, "global lookup failed")
167d_m3ErrorConst (globalTypeMismatch, "global type mismatch")
168d_m3ErrorConst (globalNotMutable, "global is not mutable")
169
170// traps
171d_m3ErrorConst (trapOutOfBoundsMemoryAccess, "[trap] out of bounds memory access")
172d_m3ErrorConst (trapDivisionByZero, "[trap] integer divide by zero")
173d_m3ErrorConst (trapIntegerOverflow, "[trap] integer overflow")
174d_m3ErrorConst (trapIntegerConversion, "[trap] invalid conversion to integer")
175d_m3ErrorConst (trapIndirectCallTypeMismatch, "[trap] indirect call type mismatch")
176d_m3ErrorConst (trapTableIndexOutOfRange, "[trap] undefined element")
177d_m3ErrorConst (trapTableElementIsNull, "[trap] null table element")
178d_m3ErrorConst (trapExit, "[trap] program called exit")
179d_m3ErrorConst (trapAbort, "[trap] program called abort")
180d_m3ErrorConst (trapUnreachable, "[trap] unreachable executed")
181d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow")
182
183
184//-------------------------------------------------------------------------------------------------------------------------------
185// configuration, can be found in m3_config.h, m3_config_platforms.h, m3_core.h)
186//-------------------------------------------------------------------------------------------------------------------------------
187
188//-------------------------------------------------------------------------------------------------------------------------------
189// global environment than can host multiple runtimes
190//-------------------------------------------------------------------------------------------------------------------------------
191 IM3Environment m3_NewEnvironment (void);
192
193 void m3_FreeEnvironment (IM3Environment i_environment);
194
195 typedef M3Result (* M3SectionHandler) (IM3Module i_module, const char* name, const uint8_t * start, const uint8_t * end);
196
197 void m3_SetCustomSectionHandler (IM3Environment i_environment, M3SectionHandler i_handler);
198
199
200//-------------------------------------------------------------------------------------------------------------------------------
201// execution context
202//-------------------------------------------------------------------------------------------------------------------------------
203
204 IM3Runtime m3_NewRuntime (IM3Environment io_environment,
205 uint32_t i_stackSizeInBytes,
206 void * i_userdata);
207
208 void m3_FreeRuntime (IM3Runtime i_runtime);
209
210 // Wasm currently only supports one memory region. i_memoryIndex should be zero.
211 uint8_t * m3_GetMemory (IM3Runtime i_runtime,
212 uint32_t * o_memorySizeInBytes,
213 uint32_t i_memoryIndex);
214
215 // This is used internally by Raw Function helpers
216 uint32_t m3_GetMemorySize (IM3Runtime i_runtime);
217
218 void * m3_GetUserData (IM3Runtime i_runtime);
219
220
221//-------------------------------------------------------------------------------------------------------------------------------
222// modules
223//-------------------------------------------------------------------------------------------------------------------------------
224
225 // i_wasmBytes data must be persistent during the lifetime of the module
226 M3Result m3_ParseModule (IM3Environment i_environment,
227 IM3Module * o_module,
228 const uint8_t * const i_wasmBytes,
229 uint32_t i_numWasmBytes);
230
231 // Only modules not loaded into a M3Runtime need to be freed. A module is considered unloaded if
232 // a. m3_LoadModule has not yet been called on that module. Or,
233 // b. m3_LoadModule returned a result.
234 void m3_FreeModule (IM3Module i_module);
235
236 // LoadModule transfers ownership of a module to the runtime. Do not free modules once successfully loaded into the runtime
237 M3Result m3_LoadModule (IM3Runtime io_runtime, IM3Module io_module);
238
239 // Optional, compiles all functions in the module
240 M3Result m3_CompileModule (IM3Module io_module);
241
242 // Calling m3_RunStart is optional
243 M3Result m3_RunStart (IM3Module i_module);
244
245 // Arguments and return values are passed in and out through the stack pointer _sp.
246 // Placeholder return value slots are first and arguments after. So, the first argument is at _sp [numReturns]
247 // Return values should be written into _sp [0] to _sp [num_returns - 1]
248 typedef const void * (* M3RawCall) (IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem);
249
250 M3Result m3_LinkRawFunction (IM3Module io_module,
251 const char * const i_moduleName,
252 const char * const i_functionName,
253 const char * const i_signature,
254 M3RawCall i_function);
255
256 M3Result m3_LinkRawFunctionEx (IM3Module io_module,
257 const char * const i_moduleName,
258 const char * const i_functionName,
259 const char * const i_signature,
260 M3RawCall i_function,
261 const void * i_userdata);
262
263 const char* m3_GetModuleName (IM3Module i_module);
264 void m3_SetModuleName (IM3Module i_module, const char* name);
265 IM3Runtime m3_GetModuleRuntime (IM3Module i_module);
266
267//-------------------------------------------------------------------------------------------------------------------------------
268// globals
269//-------------------------------------------------------------------------------------------------------------------------------
270 IM3Global m3_FindGlobal (IM3Module io_module,
271 const char * const i_globalName);
272
273 M3Result m3_GetGlobal (IM3Global i_global,
274 IM3TaggedValue o_value);
275
276 M3Result m3_SetGlobal (IM3Global i_global,
277 const IM3TaggedValue i_value);
278
279 M3ValueType m3_GetGlobalType (IM3Global i_global);
280
281//-------------------------------------------------------------------------------------------------------------------------------
282// functions
283//-------------------------------------------------------------------------------------------------------------------------------
284 M3Result m3_Yield (void);
285
286 // o_function is valid during the lifetime of the originating runtime
287 M3Result m3_FindFunction (IM3Function * o_function,
288 IM3Runtime i_runtime,
289 const char * const i_functionName);
290
291 uint32_t m3_GetArgCount (IM3Function i_function);
292 uint32_t m3_GetRetCount (IM3Function i_function);
293 M3ValueType m3_GetArgType (IM3Function i_function, uint32_t i_index);
294 M3ValueType m3_GetRetType (IM3Function i_function, uint32_t i_index);
295
296 M3Result m3_CallV (IM3Function i_function, ...);
297 M3Result m3_CallVL (IM3Function i_function, va_list i_args);
298 M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argptrs[]);
299 M3Result m3_CallArgv (IM3Function i_function, uint32_t i_argc, const char * i_argv[]);
300
301 M3Result m3_GetResultsV (IM3Function i_function, ...);
302 M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets);
303 M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void * o_retptrs[]);
304
305
306 void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* o_info);
307 void m3_ResetErrorInfo (IM3Runtime i_runtime);
308
309 const char* m3_GetFunctionName (IM3Function i_function);
310 IM3Module m3_GetFunctionModule (IM3Function i_function);
311
312//-------------------------------------------------------------------------------------------------------------------------------
313// debug info
314//-------------------------------------------------------------------------------------------------------------------------------
315
316 void m3_PrintRuntimeInfo (IM3Runtime i_runtime);
317 void m3_PrintM3Info (void);
318 void m3_PrintProfilerInfo (void);
319
320 // The runtime owns the backtrace, do not free the backtrace you obtain. Returns NULL if there's no backtrace.
321 IM3BacktraceInfo m3_GetBacktrace (IM3Runtime i_runtime);
322
323//-------------------------------------------------------------------------------------------------------------------------------
324// raw function definition helpers
325//-------------------------------------------------------------------------------------------------------------------------------
326
327# define m3ApiOffsetToPtr(offset) (void*)((uint8_t*)_mem + (uint32_t)(offset))
328# define m3ApiPtrToOffset(ptr) (uint32_t)((uint8_t*)ptr - (uint8_t*)_mem)
329
330# define m3ApiReturnType(TYPE) TYPE* raw_return = ((TYPE*) (_sp++));
331# define m3ApiGetArg(TYPE, NAME) TYPE NAME = * ((TYPE *) (_sp++));
332# define m3ApiGetArgMem(TYPE, NAME) TYPE NAME = (TYPE)m3ApiOffsetToPtr(* ((uint32_t *) (_sp++)));
333
334# define m3ApiIsNullPtr(addr) ((void*)(addr) <= _mem)
335# define m3ApiCheckMem(addr, len) { if (M3_UNLIKELY(((void*)(addr) < _mem) || ((uint64_t)(uintptr_t)(addr) + (len)) > ((uint64_t)(uintptr_t)(_mem)+m3_GetMemorySize(runtime)))) m3ApiTrap(m3Err_trapOutOfBoundsMemoryAccess); }
336
337# define m3ApiRawFunction(NAME) const void * NAME (IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem)
338# define m3ApiReturn(VALUE) { *raw_return = (VALUE); return m3Err_none; }
339# define m3ApiTrap(VALUE) { return VALUE; }
340# define m3ApiSuccess() { return m3Err_none; }
341
342# if defined(M3_BIG_ENDIAN)
343# define m3ApiReadMem8(ptr) (* (uint8_t *)(ptr))
344# define m3ApiReadMem16(ptr) m3_bswap16((* (uint16_t *)(ptr)))
345# define m3ApiReadMem32(ptr) m3_bswap32((* (uint32_t *)(ptr)))
346# define m3ApiReadMem64(ptr) m3_bswap64((* (uint64_t *)(ptr)))
347# define m3ApiWriteMem8(ptr, val) { * (uint8_t *)(ptr) = (val); }
348# define m3ApiWriteMem16(ptr, val) { * (uint16_t *)(ptr) = m3_bswap16((val)); }
349# define m3ApiWriteMem32(ptr, val) { * (uint32_t *)(ptr) = m3_bswap32((val)); }
350# define m3ApiWriteMem64(ptr, val) { * (uint64_t *)(ptr) = m3_bswap64((val)); }
351# else
352# define m3ApiReadMem8(ptr) (* (uint8_t *)(ptr))
353# define m3ApiReadMem16(ptr) (* (uint16_t *)(ptr))
354# define m3ApiReadMem32(ptr) (* (uint32_t *)(ptr))
355# define m3ApiReadMem64(ptr) (* (uint64_t *)(ptr))
356# define m3ApiWriteMem8(ptr, val) { * (uint8_t *)(ptr) = (val); }
357# define m3ApiWriteMem16(ptr, val) { * (uint16_t *)(ptr) = (val); }
358# define m3ApiWriteMem32(ptr, val) { * (uint32_t *)(ptr) = (val); }
359# define m3ApiWriteMem64(ptr, val) { * (uint64_t *)(ptr) = (val); }
360# endif
361
362#if defined(__cplusplus)
363}
364#endif
365
366#endif // wasm3_h
367