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 
28 d_m3BeginExternC
29 
30 #define d_m3ImplementFloat (d_m3HasFloat || d_m3NoFloatDynamic)
31 
32 #if !defined(d_m3ShortTypesDefined)
33 
34 typedef uint64_t        u64;
35 typedef int64_t         i64;
36 typedef uint32_t        u32;
37 typedef int32_t         i32;
38 typedef uint16_t        u16;
39 typedef int16_t         i16;
40 typedef uint8_t         u8;
41 typedef int8_t          i8;
42 
43 #if d_m3ImplementFloat
44 typedef double          f64;
45 typedef float           f32;
46 #endif
47 
48 #endif // d_m3ShortTypesDefined
49 
50 #define PRIf32          "f"
51 #define PRIf64          "lf"
52 
53 typedef const void *            m3ret_t;
54 typedef const void *            voidptr_t;
55 typedef const char *            cstr_t;
56 typedef const char * const      ccstr_t;
57 typedef const u8 *              bytes_t;
58 typedef const u8 * const        cbytes_t;
59 
60 typedef u16                     m3opcode_t;
61 
62 typedef i64                     m3reg_t;
63 
64 # if d_m3Use32BitSlots
65 typedef u32                     m3slot_t;
66 # else
67 typedef u64                     m3slot_t;
68 # endif
69 
70 typedef m3slot_t *              m3stack_t;
71 
72 typedef
73 const 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 
128 typedef void /*const*/ *                    code_t;
129 typedef code_t const * /*__restrict__*/     pc_t;
130 
131 
132 typedef struct M3MemoryHeader
133 {
134     IM3Runtime      runtime;
135     void *          maxStack;
136     size_t          length;
137 }
138 M3MemoryHeader;
139 
140 struct M3CodeMappingPage;
141 
142 typedef 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 }
155 M3CodePageHeader;
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 
181 static const char * const c_waTypes []          = { "nil", "i32", "i64", "f32", "f64", "unknown" };
182 static const char * const c_waCompactTypes []   = { "_", "i", "I", "f", "F", "?" };
183 
184 
185 # if d_m3VerboseErrorMessages
186 
187 M3Result 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
202 void        m3StackCheckInit        ();
203 void        m3StackCheck            ();
204 int         m3StackGetMax           ();
205 #else
206 #define     m3StackCheckInit()
207 #define     m3StackCheck()
208 #define     m3StackGetMax()         0
209 #endif
210 
211 void        m3_Abort                (const char* message);
212 void *      m3_Malloc               (size_t i_size);
213 void *      m3_Realloc              (void *i_ptr, size_t i_newSize, size_t i_oldSize);
214 void        m3_FreeImpl             (void * i_ptr);
215 void *      m3_CopyMem              (const void * i_from, size_t i_size);
216 
217 #define     m3_AllocStruct(STRUCT)                  (STRUCT *)m3_Malloc (sizeof (STRUCT))
218 #define     m3_AllocArray(STRUCT, NUM)              (STRUCT *)m3_Malloc (sizeof (STRUCT) * (NUM))
219 #define     m3_ReallocArray(STRUCT, PTR, NEW, OLD)  (STRUCT *)m3_Realloc ((void *)(PTR), sizeof (STRUCT) * (NEW), sizeof (STRUCT) * (OLD))
220 #define     m3_Free(P)                              do { m3_FreeImpl ((void*)(P)); (P) = NULL; } while(0)
221 
222 M3Result    NormalizeType           (u8 * o_type, i8 i_convolutedWasmType);
223 
224 bool        IsIntType               (u8 i_wasmType);
225 bool        IsFpType                (u8 i_wasmType);
226 bool        Is64BitType             (u8 i_m3Type);
227 u32         SizeOfType              (u8 i_m3Type);
228 
229 M3Result    Read_u64                (u64 * o_value, bytes_t * io_bytes, cbytes_t i_end);
230 M3Result    Read_u32                (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
231 #if d_m3ImplementFloat
232 M3Result    Read_f64                (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end);
233 M3Result    Read_f32                (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
234 #endif
235 M3Result    Read_u8                 (u8  * o_value, bytes_t * io_bytes, cbytes_t i_end);
236 M3Result    Read_opcode             (m3opcode_t * o_value, bytes_t  * io_bytes, cbytes_t i_end);
237 
238 M3Result    ReadLebUnsigned         (u64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end);
239 M3Result    ReadLebSigned           (i64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end);
240 M3Result    ReadLEB_u32             (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
241 M3Result    ReadLEB_u7              (u8  * o_value, bytes_t * io_bytes, cbytes_t i_end);
242 M3Result    ReadLEB_i7              (i8  * o_value, bytes_t * io_bytes, cbytes_t i_end);
243 M3Result    ReadLEB_i32             (i32 * o_value, bytes_t * io_bytes, cbytes_t i_end);
244 M3Result    ReadLEB_i64             (i64 * o_value, bytes_t * io_bytes, cbytes_t i_end);
245 M3Result    Read_utf8               (cstr_t * o_utf8, bytes_t * io_bytes, cbytes_t i_end);
246 
247 cstr_t      SPrintValue             (void * i_value, u8 i_type);
248 size_t      SPrintArg               (char * o_string, size_t i_stringBufferSize, voidptr_t i_sp, u8 i_type);
249 
250 void        ReportError             (IM3Runtime io_runtime, IM3Module i_module, IM3Function i_function, ccstr_t i_errorMessage, ccstr_t i_file, u32 i_lineNum);
251 
252 # if d_m3RecordBacktraces
253 void        PushBacktraceFrame         (IM3Runtime io_runtime, pc_t i_pc);
254 void        FillBacktraceFunctionInfo  (IM3Runtime io_runtime, IM3Function i_function);
255 void        ClearBacktrace             (IM3Runtime io_runtime);
256 # endif
257 
258 d_m3EndExternC
259 
260 #endif // m3_core_h
261