1//
2// m3_core.h
3//
4// Created by Steven Massey on 4/15/19.
5// Copyright © 2019 Steven Massey. All rights reserved.
6//
7
8#ifndef m3_core_h
9#define m3_core_h
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <stdbool.h>
14#include <string.h>
15#include <assert.h>
16
17#include "wasm3.h"
18#include "m3_config.h"
19
20# if defined(__cplusplus)
21# define d_m3BeginExternC extern "C" {
22# define d_m3EndExternC }
23# else
24# define d_m3BeginExternC
25# define d_m3EndExternC
26# endif
27
28d_m3BeginExternC
29
30#define d_m3ImplementFloat (d_m3HasFloat || d_m3NoFloatDynamic)
31
32#if !defined(d_m3ShortTypesDefined)
33
34typedef uint64_t u64;
35typedef int64_t i64;
36typedef uint32_t u32;
37typedef int32_t i32;
38typedef uint16_t u16;
39typedef int16_t i16;
40typedef uint8_t u8;
41typedef int8_t i8;
42
43#if d_m3ImplementFloat
44typedef double f64;
45typedef float f32;
46#endif
47
48#endif // d_m3ShortTypesDefined
49
50#define PRIf32 "f"
51#define PRIf64 "lf"
52
53typedef const void * m3ret_t;
54typedef const void * voidptr_t;
55typedef const char * cstr_t;
56typedef const char * const ccstr_t;
57typedef const u8 * bytes_t;
58typedef const u8 * const cbytes_t;
59
60typedef u16 m3opcode_t;
61
62typedef i64 m3reg_t;
63
64# if d_m3Use32BitSlots
65typedef u32 m3slot_t;
66# else
67typedef u64 m3slot_t;
68# endif
69
70typedef m3slot_t * m3stack_t;
71
72typedef
73const void * const cvptr_t;
74
75# if defined (DEBUG)
76
77# define d_m3Log(CATEGORY, FMT, ...) printf (" %8s | " FMT, #CATEGORY, ##__VA_ARGS__);
78
79# if d_m3LogParse
80# define m3log_parse(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__)
81# else
82# define m3log_parse(...) {}
83# endif
84
85# if d_m3LogCompile
86# define m3log_compile(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__)
87# else
88# define m3log_compile(...) {}
89# endif
90
91# if d_m3LogEmit
92# define m3log_emit(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__)
93# else
94# define m3log_emit(...) {}
95# endif
96
97# if d_m3LogCodePages
98# define m3log_code(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__)
99# else
100# define m3log_code(...) {}
101# endif
102
103# if d_m3LogModule
104# define m3log_module(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__)
105# else
106# define m3log_module(...) {}
107# endif
108
109# if d_m3LogRuntime
110# define m3log_runtime(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__)
111# else
112# define m3log_runtime(...) {}
113# endif
114
115# define m3log(CATEGORY, FMT, ...) m3log_##CATEGORY (CATEGORY, FMT "\n", ##__VA_ARGS__)
116# else
117# define d_m3Log(CATEGORY, FMT, ...) {}
118# define m3log(CATEGORY, FMT, ...) {}
119# endif
120
121
122# if defined(ASSERTS) || (defined(DEBUG) && !defined(NASSERTS))
123# define d_m3Assert(ASS) if (!(ASS)) { printf("Assertion failed at %s:%d : %s\n", __FILE__, __LINE__, #ASS); abort(); }
124# else
125# define d_m3Assert(ASS)
126# endif
127
128typedef void /*const*/ * code_t;
129typedef code_t const * /*__restrict__*/ pc_t;
130
131
132typedef struct M3MemoryHeader
133{
134 IM3Runtime runtime;
135 void * maxStack;
136 size_t length;
137}
138M3MemoryHeader;
139
140struct M3CodeMappingPage;
141
142typedef struct M3CodePageHeader
143{
144 struct M3CodePage * next;
145
146 u32 lineIndex;
147 u32 numLines;
148 u32 sequence; // this is just used for debugging; could be removed
149 u32 usageCount;
150
151# if d_m3RecordBacktraces
152 struct M3CodeMappingPage * mapping;
153# endif // d_m3RecordBacktraces
154}
155M3CodePageHeader;
156
157
158#define d_m3CodePageFreeLinesThreshold 4+2 // max is: select _sss & CallIndirect + 2 for bridge
159
160#define d_m3MemPageSize 65536
161
162#define d_m3Reg0SlotAlias 60000
163#define d_m3Fp0SlotAlias (d_m3Reg0SlotAlias + 2)
164
165#define d_m3MaxSaneTypesCount 100000
166#define d_m3MaxSaneFunctionsCount 100000
167#define d_m3MaxSaneImportsCount 10000
168#define d_m3MaxSaneExportsCount 10000
169#define d_m3MaxSaneGlobalsCount 100000
170#define d_m3MaxSaneElementSegments 100000
171#define d_m3MaxSaneDataSegments 100000
172#define d_m3MaxSaneTableSize 100000
173#define d_m3MaxSaneUtf8Length 10000
174#define d_m3MaxSaneFunctionArgRetCount 1000 // still insane, but whatever
175
176#define d_externalKind_function 0
177#define d_externalKind_table 1
178#define d_externalKind_memory 2
179#define d_externalKind_global 3
180
181static const char * const c_waTypes [] = { "nil", "i32", "i64", "f32", "f64", "unknown" };
182static const char * const c_waCompactTypes [] = { "_", "i", "I", "f", "F", "?" };
183
184
185# if d_m3VerboseErrorMessages
186
187M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module, IM3Function i_function,
188 const char * const i_file, u32 i_lineNum, const char * const i_errorMessage, ...);
189
190# define _m3Error(RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ...) \
191 m3Error (RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ##__VA_ARGS__)
192
193# else
194# define _m3Error(RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ...) (RESULT)
195# endif
196
197#define ErrorRuntime(RESULT, RUNTIME, FORMAT, ...) _m3Error (RESULT, RUNTIME, NULL, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__)
198#define ErrorModule(RESULT, MOD, FORMAT, ...) _m3Error (RESULT, MOD->runtime, MOD, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__)
199#define ErrorCompile(RESULT, COMP, FORMAT, ...) _m3Error (RESULT, COMP->runtime, COMP->module, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__)
200
201#if d_m3LogNativeStack
202void m3StackCheckInit ();
203void m3StackCheck ();
204int m3StackGetMax ();
205#else
206#define m3StackCheckInit()
207#define m3StackCheck()
208#define m3StackGetMax() 0
209#endif
210
211#if d_m3LogTimestamps
212#define PRIts "%llu"
213uint64_t m3_GetTimestamp ();
214#else
215#define PRIts "%s"
216#define m3_GetTimestamp() ""
217#endif
218
219void m3_Abort (const char* message);
220void * m3_Malloc_Impl (size_t i_size);
221void * m3_Realloc_Impl (void * i_ptr, size_t i_newSize, size_t i_oldSize);
222void m3_Free_Impl (void * i_ptr);
223void * m3_CopyMem (const void * i_from, size_t i_size);
224
225#if d_m3LogHeapOps
226
227// Tracing format: timestamp;heap:OpCode;name;size(bytes);new items;new ptr;old items;old ptr
228
229static inline void * m3_AllocStruct_Impl(ccstr_t name, size_t i_size) {
230 void * result = m3_Malloc_Impl(i_size);
231 fprintf(stderr, PRIts ";heap:AllocStruct;%s;%zu;;%p;;\n", m3_GetTimestamp(), name, i_size, result);
232 return result;
233}
234
235static inline void * m3_AllocArray_Impl(ccstr_t name, size_t i_num, size_t i_size) {
236 void * result = m3_Malloc_Impl(i_size * i_num);
237 fprintf(stderr, PRIts ";heap:AllocArr;%s;%zu;%zu;%p;;\n", m3_GetTimestamp(), name, i_size, i_num, result);
238 return result;
239}
240
241static inline void * m3_ReallocArray_Impl(ccstr_t name, void * i_ptr_old, size_t i_num_new, size_t i_num_old, size_t i_size) {
242 void * result = m3_Realloc_Impl (i_ptr_old, i_size * i_num_new, i_size * i_num_old);
243 fprintf(stderr, PRIts ";heap:ReallocArr;%s;%zu;%zu;%p;%zu;%p\n", m3_GetTimestamp(), name, i_size, i_num_new, result, i_num_old, i_ptr_old);
244 return result;
245}
246
247static inline void * m3_Malloc (ccstr_t name, size_t i_size) {
248 void * result = m3_Malloc_Impl (i_size);
249 fprintf(stderr, PRIts ";heap:AllocMem;%s;%zu;;%p;;\n", m3_GetTimestamp(), name, i_size, result);
250 return result;
251}
252static inline void * m3_Realloc (ccstr_t name, void * i_ptr, size_t i_newSize, size_t i_oldSize) {
253 void * result = m3_Realloc_Impl (i_ptr, i_newSize, i_oldSize);
254 fprintf(stderr, PRIts ";heap:ReallocMem;%s;;%zu;%p;%zu;%p\n", m3_GetTimestamp(), name, i_newSize, result, i_oldSize, i_ptr);
255 return result;
256}
257
258#define m3_AllocStruct(STRUCT) (STRUCT *)m3_AllocStruct_Impl (#STRUCT, sizeof (STRUCT))
259#define m3_AllocArray(STRUCT, NUM) (STRUCT *)m3_AllocArray_Impl (#STRUCT, NUM, sizeof (STRUCT))
260#define m3_ReallocArray(STRUCT, PTR, NEW, OLD) (STRUCT *)m3_ReallocArray_Impl (#STRUCT, (void *)(PTR), (NEW), (OLD), sizeof (STRUCT))
261#define m3_Free(P) do { void* p = (void*)(P); \
262 if (p) { fprintf(stderr, PRIts ";heap:FreeMem;;;;%p;\n", m3_GetTimestamp(), p); } \
263 m3_Free_Impl (p); (P) = NULL; } while(0)
264#else
265#define m3_Malloc(NAME, SIZE) m3_Malloc_Impl(SIZE)
266#define m3_Realloc(NAME, PTR, NEW, OLD) m3_Realloc_Impl(PTR, NEW, OLD)
267#define m3_AllocStruct(STRUCT) (STRUCT *)m3_Malloc_Impl (sizeof (STRUCT))
268#define m3_AllocArray(STRUCT, NUM) (STRUCT *)m3_Malloc_Impl (sizeof (STRUCT) * (NUM))
269#define m3_ReallocArray(STRUCT, PTR, NEW, OLD) (STRUCT *)m3_Realloc_Impl ((void *)(PTR), sizeof (STRUCT) * (NEW), sizeof (STRUCT) * (OLD))
270#define m3_Free(P) do { m3_Free_Impl ((void*)(P)); (P) = NULL; } while(0)
271#endif
272
273M3Result NormalizeType (u8 * o_type, i8 i_convolutedWasmType);
274
275bool IsIntType (u8 i_wasmType);
276bool IsFpType (u8 i_wasmType);
277bool Is64BitType (u8 i_m3Type);
278u32 SizeOfType (u8 i_m3Type);
279
280M3Result Read_u64 (u64 * o_value, bytes_t * io_bytes, cbytes_t i_end);
281M3Result Read_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
282#if d_m3ImplementFloat
283M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end);
284M3Result Read_f32 (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
285#endif
286M3Result Read_u8 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end);
287M3Result Read_opcode (m3opcode_t * o_value, bytes_t * io_bytes, cbytes_t i_end);
288
289M3Result ReadLebUnsigned (u64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end);
290M3Result ReadLebSigned (i64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end);
291M3Result ReadLEB_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
292M3Result ReadLEB_u7 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end);
293M3Result ReadLEB_i7 (i8 * o_value, bytes_t * io_bytes, cbytes_t i_end);
294M3Result ReadLEB_i32 (i32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
295M3Result ReadLEB_i64 (i64 * o_value, bytes_t * io_bytes, cbytes_t i_end);
296M3Result Read_utf8 (cstr_t * o_utf8, bytes_t * io_bytes, cbytes_t i_end);
297
298cstr_t SPrintValue (void * i_value, u8 i_type);
299size_t SPrintArg (char * o_string, size_t i_stringBufferSize, voidptr_t i_sp, u8 i_type);
300
301void ReportError (IM3Runtime io_runtime, IM3Module i_module, IM3Function i_function, ccstr_t i_errorMessage, ccstr_t i_file, u32 i_lineNum);
302
303# if d_m3RecordBacktraces
304void PushBacktraceFrame (IM3Runtime io_runtime, pc_t i_pc);
305void FillBacktraceFunctionInfo (IM3Runtime io_runtime, IM3Function i_function);
306void ClearBacktrace (IM3Runtime io_runtime);
307# endif
308
309d_m3EndExternC
310
311#endif // m3_core_h
312