| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include <time.h> | ||
| 2 | #include "gwion_util.h" | ||
| 3 | #include "gwion_ast.h" | ||
| 4 | #include "gwion_env.h" | ||
| 5 | #include "vm.h" | ||
| 6 | #include "instr.h" | ||
| 7 | #include "shreduler_private.h" | ||
| 8 | #include "emit.h" | ||
| 9 | #include "gwion.h" | ||
| 10 | #include "object.h" | ||
| 11 | #include "ugen.h" | ||
| 12 | #include "operator.h" | ||
| 13 | #include "import.h" | ||
| 14 | #include "gack.h" | ||
| 15 | #include "array.h" | ||
| 16 | |||
| 17 | 712 | static inline uint64_t splitmix64_stateless(uint64_t index) { | |
| 18 | 712 | uint64_t z = (index + UINT64_C(0x9E3779B97F4A7C15)); | |
| 19 | 712 | z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); | |
| 20 | 712 | z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB); | |
| 21 | 712 | return z ^ (z >> 31); | |
| 22 | } | ||
| 23 | |||
| 24 | 117 | static inline uint32_t rotl(const uint32_t x, int k) { | |
| 25 | 117 | return (x << k) | (x >> (32 - k)); | |
| 26 | } | ||
| 27 | |||
| 28 | 712 | void gw_seed(uint32_t rnd[2], const uint64_t s) { | |
| 29 | 712 | uint64_t seed = splitmix64_stateless(s); | |
| 30 | 712 | memcpy(rnd, &seed, sizeof(uint64_t)); | |
| 31 | 712 | } | |
| 32 | |||
| 33 | /*xoroshiro32** */ | ||
| 34 | 39 | uint32_t gw_rand(uint32_t s[2]) { | |
| 35 | 39 | const uint32_t s0 = s[0]; | |
| 36 | 39 | const uint32_t s1 = s[1] ^ s0; | |
| 37 | 39 | const uint32_t ret = rotl(s0 * 0x9E3779BB, 5) * 5; | |
| 38 | 39 | s[0] = rotl(s0, 26) ^ s1 ^ (s1 << 9); | |
| 39 | 39 | s[1] = rotl(s1, 13); | |
| 40 | 39 | return ret; | |
| 41 | } | ||
| 42 | |||
| 43 | 8190 | ANN static inline void shred_unwind(const VM_Shred shred) { | |
| 44 | 8190 | register frame_t *frame = &*(frame_t *)(shred->mem - sizeof(frame_t)); | |
| 45 | 8190 | shred->code = frame->code; | |
| 46 | 8190 | shred->pc = frame->pc; | |
| 47 | 8190 | shred->mem -= frame->push; | |
| 48 | 8190 | } | |
| 49 | |||
| 50 | 18 | ANN static void clean_values(const VM_Shred shred) { | |
| 51 | 18 | const VM_Code code = shred->code; | |
| 52 | 18 | const uint16_t pc = shred->pc; | |
| 53 |
2/2✓ Branch 1 taken 21 times.
✓ Branch 2 taken 12 times.
|
33 | for (m_uint i = m_vector_size(&code->live_values) + 1; --i;) { |
| 54 | 21 | VMValue *vmval = (VMValue *)m_vector_addr(&code->live_values, i - 1); | |
| 55 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 15 times.
|
21 | if (pc <= vmval->start) break; |
| 56 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (pc >= vmval->end) continue; |
| 57 | 15 | m_bit *const data = &*(m_bit *)(shred->mem + vmval->offset); | |
| 58 | 15 | compound_release(shred, vmval->t, data); | |
| 59 | } | ||
| 60 | 18 | } | |
| 61 | |||
| 62 | 3 | ANN static uint16_t find_pc(const VM_Shred shred, const Symbol effect) { | |
| 63 | 3 | const VM_Code code = shred->code; | |
| 64 | 3 | const m_uint start = vector_at(&shred->info->frame, vector_size(&shred->info->frame) - 2); | |
| 65 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (start > shred->pc) return true; |
| 66 | 3 | const Map m = &shred->code->handlers; | |
| 67 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | for (m_uint i = 0; i < map_size(m); i++) { |
| 68 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (start > shred->pc) break; |
| 69 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (start < shred->pc && VKEY(m, i) > shred->pc) { |
| 70 | 3 | const m_uint next = VKEY(m, i); | |
| 71 | 3 | const Instr instr = (Instr)vector_at(&code->instr, next); | |
| 72 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (!instr->m_val2 || (Symbol)instr->m_val2 == effect) |
| 73 | 3 | return next + 1; | |
| 74 | } | ||
| 75 | } | ||
| 76 | ✗ | return 0; | |
| 77 | } | ||
| 78 | |||
| 79 | 3 | ANN static inline bool find_handle(const VM_Shred shred, const Symbol effect) { | |
| 80 | 3 | const uint16_t pc = find_pc(shred, effect); | |
| 81 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!pc) return false; // outside of a try statement |
| 82 | 3 | shred->reg = // restore reg | |
| 83 | 3 | (m_bit *)VPTR(&shred->info->frame, VLEN(&shred->info->frame) - 1); | |
| 84 | 3 | shredule(shred->tick->shreduler, shred, 0); | |
| 85 | 3 | shred->pc = pc; // VKEY(m, i); | |
| 86 | 3 | const Instr instr = (Instr)vector_at(&shred->code->instr, pc); | |
| 87 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if(!instr->m_val) |
| 88 | 3 | *(m_str*)(shred->mem + instr->m_val2) = s_name(effect); | |
| 89 | |||
| 90 | 3 | vector_pop(&shred->info->frame); | |
| 91 | 3 | vector_pop(&shred->info->frame); | |
| 92 | 3 | return true; | |
| 93 | } | ||
| 94 | |||
| 95 | 8220 | ANN bool unwind(const VM_Shred shred, const Symbol effect, const m_uint size) { | |
| 96 | 8220 | const VM_Code code = shred->code; | |
| 97 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 8202 times.
|
8220 | if (code->live_values.ptr) |
| 98 | 18 | clean_values(shred); | |
| 99 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 8193 times.
|
8220 | if (!size) return false; |
| 100 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8190 times.
|
8193 | if (code->handlers.ptr) |
| 101 | 3 | return find_handle(shred, effect); | |
| 102 | // there might be no more stack to unwind | ||
| 103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8190 times.
|
8190 | if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG) |
| 104 | ✗ | return false; | |
| 105 | 8190 | shred_unwind(shred); | |
| 106 | 8190 | return unwind(shred, effect, size - (code != shred->code)); | |
| 107 | } | ||
| 108 | |||
| 109 | ✗ | ANN static void trace(VM_Shred shred, const m_uint size) { | |
| 110 | ✗ | const m_uint line = vector_at(&shred->info->line, size - 1); | |
| 111 | m_uint i; | ||
| 112 | ✗ | bool can_skip = false; | |
| 113 | ✗ | if(!size)return; | |
| 114 | ✗ | for (i = size; --i;) { | |
| 115 | ✗ | const m_uint val = VPTR(&shred->info->line, i - 1); | |
| 116 | ✗ | if (!val) | |
| 117 | ✗ | can_skip = true; | |
| 118 | ✗ | else if (can_skip && val) | |
| 119 | ✗ | break; | |
| 120 | } | ||
| 121 | ✗ | loc_t loc = {.first = {.line = line, .column = 1}, | |
| 122 | .last = {.line = line, .column = 1}}; | ||
| 123 | ✗ | gwerr_secondary("called from here", code_name(shred->code->name, true), loc); | |
| 124 | ✗ | gw_err(" {M}┗━╸{0} {-}in code{0} {+W}%s{0}{-}:{0}\n", shred->code->name); | |
| 125 | ✗ | if (shred->mem == (m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG) | |
| 126 | ✗ | return; | |
| 127 | ✗ | shred_unwind(shred); | |
| 128 | ✗ | trace(shred, i); | |
| 129 | } | ||
| 130 | |||
| 131 | struct TraceStart { | ||
| 132 | const VM_Code code; | ||
| 133 | m_bit *const reg; | ||
| 134 | m_bit *const mem; | ||
| 135 | }; | ||
| 136 | |||
| 137 | ✗ | ANN static inline void shred_trace(const VM_Shred shred, const struct TraceStart *ts) { | |
| 138 | ✗ | shred->code = ts->code; | |
| 139 | ✗ | shred->reg = ts->reg; | |
| 140 | ✗ | shred->mem = ts->mem; | |
| 141 | ✗ | gw_err("\n{-/}here is the trace:\n"); | |
| 142 | ✗ | trace(shred, vector_size(&shred->info->line)); | |
| 143 | } | ||
| 144 | |||
| 145 | 27 | ANN static inline void unhandled_pp(VM_Shred shred, const m_str effect, const struct TraceStart *ts) { | |
| 146 | 27 | gw_err("{-}[{0}{+}Gwion{0}{-}](VM):{0} {-}in code {/+}'%s'{0}{-}. origin: {/+}'%s'{0}{-}\n", | |
| 147 | ts->code->name, shred->info->orig->name); | ||
| 148 | 27 | gw_err("{-C}shred{W}[{Y}% 5" UINT_F "{W}]{-}:{-R}Unhandled {+R}%s{0}\n", | |
| 149 | shred->tick->xid, effect); | ||
| 150 | 27 | } | |
| 151 | |||
| 152 | 27 | ANN static inline void handle_fail(VM_Shred shred, const m_str effect, const struct TraceStart *ts) { | |
| 153 | 27 | unhandled_pp(shred, effect, ts); | |
| 154 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (shred->info->line.ptr) // trace if available |
| 155 | ✗ | shred_trace(shred, ts); | |
| 156 | 27 | shreduler_remove(shred->tick->shreduler, shred, true); | |
| 157 | 27 | } | |
| 158 | |||
| 159 | 30 | ANN bool handle(VM_Shred shred, const m_str effect) { | |
| 160 | 30 | shreduler_remove(shred->tick->shreduler, shred, false); | |
| 161 | // store trace info | ||
| 162 | 30 | struct TraceStart ts = { | |
| 163 | 30 | .code = shred->code, | |
| 164 | 30 | .reg = shred->reg, | |
| 165 | 30 | .mem = shred->mem | |
| 166 | }; | ||
| 167 | 30 | const m_uint size = | |
| 168 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 27 times.
|
30 | shred->info->frame.ptr ? vector_size(&shred->info->frame) : 0; |
| 169 | // maybe we should use a string to avoid the insert_symbol call | ||
| 170 |
2/2✓ Branch 1 taken 27 times.
✓ Branch 2 taken 3 times.
|
30 | if (!unwind(shred, insert_symbol(shred->info->vm->gwion->st, effect), size)) { |
| 171 | 27 | handle_fail(shred, effect, &ts); | |
| 172 | 27 | return false; | |
| 173 | } | ||
| 174 | 3 | return true; | |
| 175 | } | ||
| 176 | |||
| 177 | ✗ | ANN bool vm_remove(const VM *vm, const m_uint index) { | |
| 178 | ✗ | const Vector v = (Vector)&vm->shreduler->active_shreds; | |
| 179 | LOOP_OPTIM | ||
| 180 | ✗ | for (m_uint i = vector_size(v) + 1; --i;) { | |
| 181 | ✗ | const VM_Shred sh = (VM_Shred)vector_at(v, i - 1); | |
| 182 | ✗ | if (sh && sh->tick->xid == index) { | |
| 183 | ✗ | handle(sh, "MsgRemove"); | |
| 184 | ✗ | return true; | |
| 185 | } | ||
| 186 | } | ||
| 187 | ✗ | return false; | |
| 188 | } | ||
| 189 | |||
| 190 | 424 | ANN void vm_add_shred(const VM *vm, const VM_Shred shred) { | |
| 191 | 424 | shred->info->vm = (VM *)vm; | |
| 192 | 424 | shred->info->me = new_shred(shred); | |
| 193 | 424 | shreduler_add(vm->shreduler, shred); | |
| 194 | 424 | } | |
| 195 | |||
| 196 | 638 | ANN void vm_ini_shred(const VM *vm, const VM_Shred shred) { | |
| 197 | 638 | shred->info->vm = (VM *)vm; | |
| 198 | 638 | shred->info->me = new_shred(shred); | |
| 199 | 638 | shreduler_ini(vm->shreduler, shred); | |
| 200 | 638 | } | |
| 201 | |||
| 202 | 11 | ANN void vm_lock(VM const *vm) { | |
| 203 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
|
11 | if (vm->parent) vm_lock(vm->parent); |
| 204 | 11 | MUTEX_LOCK(vm->shreduler->mutex); | |
| 205 | 11 | } | |
| 206 | |||
| 207 | 11 | ANN void vm_unlock(VM const *vm) { | |
| 208 | 11 | do MUTEX_UNLOCK(vm->shreduler->mutex); | |
| 209 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
|
11 | while ((vm = vm->parent)); |
| 210 | 5 | } | |
| 211 | |||
| 212 | ✗ | ANN bool vm_running(VM const *vm) { | |
| 213 | ✗ | if (!vm->shreduler->bbq->is_running) return 0; | |
| 214 | ✗ | if (!vm->parent) return 1; | |
| 215 | ✗ | return vm->shreduler->bbq->is_running = vm_running(vm->parent); | |
| 216 | } | ||
| 217 | |||
| 218 | 6080218 | __attribute__((hot)) ANN static inline void compute_audio(const VM *vm) { | |
| 219 | 6080218 | const Vector v = (Vector)&vm->ugen; | |
| 220 | LOOP_OPTIM | ||
| 221 |
2/2✓ Branch 1 taken 12971128 times.
✓ Branch 2 taken 5914406 times.
|
18962234 | for (m_uint i = vector_size(v) + 1; --i;) { |
| 222 | 12971128 | const UGen u = (UGen)vector_at(v, i - 1); | |
| 223 | 12882016 | u->done = 0; | |
| 224 |
2/2✓ Branch 0 taken 6574264 times.
✓ Branch 1 taken 6307752 times.
|
12882016 | if (u->multi) { |
| 225 | 6574264 | struct ugen_multi_ *m = u->connect.multi; | |
| 226 | LOOP_OPTIM | ||
| 227 |
2/2✓ Branch 0 taken 13148528 times.
✓ Branch 1 taken 6574264 times.
|
19722792 | for (m_uint j = m->n_chan + 1; --j;) UGEN(m->channel[j - 1])->done = 0; |
| 228 | } | ||
| 229 | } | ||
| 230 | 5914406 | const UGen hole = (UGen)vector_at(v, 0); | |
| 231 | 5899260 | hole->compute(hole); | |
| 232 | 5928344 | } | |
| 233 | |||
| 234 | #ifdef DEBUG_STACK | ||
| 235 | #define VM_INFO \ | ||
| 236 | gw_err("{-C}shred{W}[{Y}% 5" UINT_F "{W}] {C}mem{W}[{Y}% 5" INT_F \ | ||
| 237 | "{W}] {C}reg{W}[{Y}% 5" INT_F "{W}]{0}\n", \ | ||
| 238 | shred->tick->xid, \ | ||
| 239 | mem - ((m_bit *)shred + sizeof(struct VM_Shred_) + SIZEOF_REG), \ | ||
| 240 | reg - ((m_bit *)shred + sizeof(struct VM_Shred_))); | ||
| 241 | #else | ||
| 242 | #define VM_INFO | ||
| 243 | #endif | ||
| 244 | |||
| 245 | 17136 | ANN static inline bool overflow_(const m_bit *mem, const VM_Shred c) { | |
| 246 | 17136 | return mem > (((m_bit *)c + sizeof(struct VM_Shred_) + SIZEOF_REG) + | |
| 247 | (SIZEOF_MEM)); | ||
| 248 | } | ||
| 249 | |||
| 250 | 74 | ANN static VM_Shred init_spork_shred(const VM_Shred shred, | |
| 251 | const VM_Code code) { | ||
| 252 | 74 | const VM_Shred sh = new_shred_base(shred, code); | |
| 253 | 74 | vm_add_shred(shred->info->vm, sh); | |
| 254 | 74 | sh->tick->parent = shred->tick; | |
| 255 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 43 times.
|
74 | if (!shred->tick->child.ptr) vector_init(&shred->tick->child); |
| 256 | 74 | vector_add(&shred->tick->child, (vtype)sh); | |
| 257 | 74 | return sh; | |
| 258 | } | ||
| 259 | |||
| 260 | ANN M_Object new_fork(const VM_Shred, const VM_Code code, const Type); | ||
| 261 | 5 | ANN static VM_Shred init_fork_shred(const VM_Shred shred, const VM_Code code, | |
| 262 | const Type t) { | ||
| 263 | 5 | const M_Object o = new_fork(shred, code, t); | |
| 264 | 5 | VM * vm = shred->info->vm; | |
| 265 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (!vm->gwion->data->child.ptr) vector_init(&vm->gwion->data->child); |
| 266 | 5 | vector_add(&vm->gwion->data->child, (vtype)o); | |
| 267 | 5 | return ME(o); | |
| 268 | } | ||
| 269 | |||
| 270 | #define handle(a, b) VM_OUT handle(a, b); | ||
| 271 | #define TEST0(t, pos) \ | ||
| 272 | if (!*(t *)(reg - pos)) { \ | ||
| 273 | handle(shred, "ZeroDivideException"); \ | ||
| 274 | break; \ | ||
| 275 | } | ||
| 276 | |||
| 277 | //#define ADVANCE() { byte += BYTECODE_SZ; shred->pc++;} | ||
| 278 | #define IDISPATCH() \ | ||
| 279 | { \ | ||
| 280 | VM_INFO; \ | ||
| 281 | SDISPATCH(); \ | ||
| 282 | } | ||
| 283 | |||
| 284 | #define SET_BYTE(pc) (byte = bytecode + (pc)*BYTECODE_SZ) | ||
| 285 | |||
| 286 | #define PC_DISPATCH(_pc) \ | ||
| 287 | SET_BYTE((_pc)); \ | ||
| 288 | IDISPATCH(); | ||
| 289 | |||
| 290 | #define DISPATCH() \ | ||
| 291 | ADVANCE(); \ | ||
| 292 | IDISPATCH(); | ||
| 293 | |||
| 294 | #define ADISPATCH() \ | ||
| 295 | { \ | ||
| 296 | ADVANCE(); \ | ||
| 297 | SDISPATCH(); \ | ||
| 298 | } | ||
| 299 | |||
| 300 | #define PC (*(m_uint *)(byte + SZ_INT*3)) | ||
| 301 | |||
| 302 | #define OP(t, sz, op, ...) \ | ||
| 303 | reg -= sz; \ | ||
| 304 | __VA_ARGS__ \ | ||
| 305 | *(t *)(reg - sz) op## = *(t *)reg; \ | ||
| 306 | DISPATCH(); | ||
| 307 | |||
| 308 | #define INT_OP(op, ...) OP(m_int, SZ_INT, op, __VA_ARGS__) | ||
| 309 | #define INT_IMM_OP(op) *(m_int*)(reg-SZ_INT) op VAL; DISPATCH() | ||
| 310 | #define FLOAT_OP(op, ...) OP(m_float, SZ_FLOAT, op, __VA_ARGS__) | ||
| 311 | #define FLOAT_IMM_OP(op) *(m_float*)(reg-SZ_FLOAT) op FVAL; DISPATCH() | ||
| 312 | |||
| 313 | #define LOGICAL(t, sz0, sz, op) \ | ||
| 314 | reg -= sz0; \ | ||
| 315 | *(m_uint *)(reg - SZ_INT) = (*(t *)(reg - SZ_INT) op * (t *)(reg + sz)); \ | ||
| 316 | DISPATCH() | ||
| 317 | |||
| 318 | #define INT_LOGICAL(op) LOGICAL(m_int, SZ_INT, 0, op) | ||
| 319 | #define INT_IMM_LOGICAL(op) *(m_int *)(reg - SZ_INT) = *(m_int*)(reg-SZ_INT) op IVAL; DISPATCH(); | ||
| 320 | |||
| 321 | #define FLOAT_LOGICAL(op) \ | ||
| 322 | LOGICAL(m_float, SZ_FLOAT * 2 - SZ_INT, SZ_FLOAT - SZ_INT, op) | ||
| 323 | |||
| 324 | #define FLOAT_IMM_LOGICAL(op) \ | ||
| 325 | reg -= SZ_FLOAT - SZ_INT;\ | ||
| 326 | *(m_uint *)(reg - SZ_INT) = *(m_float*)(reg-SZ_INT) op FVAL; DISPATCH(); | ||
| 327 | |||
| 328 | #define SELF(t, sz, op) \ | ||
| 329 | *(t *)(reg - sz) = op * (t *)(reg - sz); \ | ||
| 330 | DISPATCH(); | ||
| 331 | |||
| 332 | // check me | ||
| 333 | #define R(t, sz, op, ...) \ | ||
| 334 | reg -= SZ_INT; \ | ||
| 335 | __VA_ARGS__ \ | ||
| 336 | *(t *)(reg - sz) = (**(t **)reg op## = (*(t *)(reg - sz))); \ | ||
| 337 | DISPATCH() | ||
| 338 | #define INT_R(op, ...) R(m_int, SZ_INT, op, __VA_ARGS__) | ||
| 339 | #define FLOAT_R(op, ...) R(m_float, SZ_FLOAT, op) | ||
| 340 | |||
| 341 | #define INT_PRE(op) \ | ||
| 342 | /*assert(*(m_int**)(reg-SZ_INT));*/ \ | ||
| 343 | *(m_int *)(reg - SZ_INT) = op(**(m_int **)(reg - SZ_INT)); \ | ||
| 344 | DISPATCH() | ||
| 345 | |||
| 346 | #define INT_POST(op) \ | ||
| 347 | /*assert(*(m_int**)(reg-SZ_INT));*/ \ | ||
| 348 | *(m_int *)(reg - SZ_INT) = (**(m_int **)(reg - SZ_INT)) op; \ | ||
| 349 | DISPATCH() | ||
| 350 | |||
| 351 | #define IF_OP(op) \ | ||
| 352 | reg -= SZ_INT; \ | ||
| 353 | *(m_float *)(reg - SZ_FLOAT) = (m_float) * (m_int *)(reg - SZ_FLOAT) op * \ | ||
| 354 | (m_float *)(reg + SZ_INT - SZ_FLOAT); \ | ||
| 355 | DISPATCH() | ||
| 356 | |||
| 357 | #define IF_LOGICAL(op) \ | ||
| 358 | reg -= SZ_FLOAT; \ | ||
| 359 | *(m_int *)(reg - SZ_INT) = \ | ||
| 360 | (m_int)(*(m_int *)(reg - SZ_INT) op * (m_float *)reg); \ | ||
| 361 | DISPATCH() | ||
| 362 | __attribute__((hot)) | ||
| 363 | |||
| 364 | #define IF_R(op) \ | ||
| 365 | reg -= SZ_INT * 2 - SZ_FLOAT; \ | ||
| 366 | *(m_float *)(reg - SZ_FLOAT) = \ | ||
| 367 | (**(m_float **)(reg + SZ_INT - SZ_FLOAT) op## = \ | ||
| 368 | (m_float) * (m_int *)(reg - SZ_FLOAT)); \ | ||
| 369 | DISPATCH() | ||
| 370 | |||
| 371 | #define FI_OP(op) \ | ||
| 372 | reg -= SZ_INT; \ | ||
| 373 | *(m_float *)(reg - SZ_FLOAT) op## = (m_float) * (m_int *)reg; \ | ||
| 374 | DISPATCH() | ||
| 375 | |||
| 376 | #define FI_LOGICAL(op) \ | ||
| 377 | reg -= SZ_FLOAT; \ | ||
| 378 | *(m_int *)(reg - SZ_INT) = (m_int)(*(m_float *)(reg - SZ_INT) op * \ | ||
| 379 | (m_int *)(reg + SZ_FLOAT - SZ_INT)); \ | ||
| 380 | DISPATCH() | ||
| 381 | |||
| 382 | #define FI_R(op, ...) \ | ||
| 383 | reg -= SZ_FLOAT; \ | ||
| 384 | __VA_ARGS__ \ | ||
| 385 | *(m_int *)(reg - SZ_INT) = (**(m_int **)(reg + SZ_FLOAT - SZ_INT) op## = \ | ||
| 386 | /*(m_int)*/ (*(m_float *)(reg - SZ_INT))); \ | ||
| 387 | DISPATCH() | ||
| 388 | |||
| 389 | #define STRINGIFY_NX(a) #a | ||
| 390 | #define STRINGIFY(a) STRINGIFY_NX(a) | ||
| 391 | #define PPCAT_NX(A, B) A##B | ||
| 392 | #define PPCAT(A, B) PPCAT_NX(A, B) | ||
| 393 | |||
| 394 | #if defined(__clang__) | ||
| 395 | #define COMPILER clang | ||
| 396 | #define UNINITIALIZED "-Wuninitialized") | ||
| 397 | #elif defined(__GNUC__) || defined(__GNUG__) | ||
| 398 | #define COMPILER GCC | ||
| 399 | #define UNINITIALIZED "-Wmaybe-uninitialized") | ||
| 400 | #endif | ||
| 401 | |||
| 402 | #define PRAGMA_PUSH() \ | ||
| 403 | _Pragma(STRINGIFY(COMPILER diagnostic push)) \ | ||
| 404 | _Pragma(STRINGIFY(COMPILER diagnostic ignored UNINITIALIZED) | ||
| 405 | #define PRAGMA_POP() _Pragma(STRINGIFY(COMPILER diagnostic pop)) | ||
| 406 | |||
| 407 | #define VAL (*(m_uint *)(byte + SZ_INT)) | ||
| 408 | #define IVAL (*(m_int *)(byte + SZ_INT)) | ||
| 409 | #define FVAL (*(m_float *)(byte + SZ_INT)) | ||
| 410 | #define VAL2 (*(m_uint *)(byte + SZ_INT + SZ_INT)) | ||
| 411 | #define IVAL2 (*(m_int *)(byte + SZ_INT + SZ_INT)) | ||
| 412 | #define SVAL (*(uint16_t *)(byte + SZ_INT + SZ_INT)) | ||
| 413 | #define SVAL2 (*(uint16_t *)(byte + SZ_INT + SZ_INT + sizeof(uint16_t))) | ||
| 414 | |||
| 415 | #define BRANCH_DISPATCH(check) \ | ||
| 416 | if (check) { \ | ||
| 417 | SET_BYTE(VAL); \ | ||
| 418 | shred->pc = VAL + 1;\ | ||
| 419 | } else \ | ||
| 420 | ADVANCE(); \ | ||
| 421 | IDISPATCH(); | ||
| 422 | |||
| 423 | __attribute__((hot)) void | ||
| 424 | 6086953 | vm_prepare(const VM *vm, m_bit *prepare_code) { // lgtm [cpp/use-of-goto] | |
| 425 | static const void *dispatch[] = { | ||
| 426 | &®setimm, &®pushimm, &®pushfloat, &®pushother, &®pushaddr, | ||
| 427 | &®pushmem, &®pushmemfloat, &®pushmemother, &®pushmemaddr, | ||
| 428 | &®pushmemderef, &&pushnow, &&baseint, &&basefloat, &&baseother, | ||
| 429 | &&baseaddr, &®toreg, &®toregother2, &®toregaddr, &®toregderef, | ||
| 430 | &&structmember, &&structmemberfloat, &&structmemberother, | ||
| 431 | &&structmemberaddr, &&memsetimm, &&memaddimm, &&repeatidx, &&repeat, | ||
| 432 | &®pushme, &®pushmaybe, &&funcreturn, &&_goto, &&allocint, | ||
| 433 | &&allocfloat, &&allocother, | ||
| 434 | &&intplus, &&intminus, &&intmul, &&intdiv, &&intmod, | ||
| 435 | &&intplusimm, &&intminusimm, &&intmulimm, &&intdivimm, &&intmodimm, | ||
| 436 | // int relationnal | ||
| 437 | &&inteq, &&intne, &&intand, &&intor, | ||
| 438 | &&intgt, &&intge, &&intlt, &&intle, | ||
| 439 | &&intgtimm, &&intgeimm, &&intltimm, &&intleimm, | ||
| 440 | &&intsl, &&intsr, &&intsand, &&intsor, &&intxor, &&intnegate, &&intnot, | ||
| 441 | &&intcmp, &&intrassign, &&intradd, &&intrsub, &&intrmul, &&intrdiv, | ||
| 442 | &&intrmod, &&intrsl, &&intrsr, &&intrsand, &&intrsor, &&intrxor, &&preinc, | ||
| 443 | &&predec, &&postinc, &&postdec, | ||
| 444 | &&floatadd, &&floatsub, &&floatmul, &&floatdiv, | ||
| 445 | &&floataddimm, &&floatsubimm, &&floatmulimm, &&floatdivimm, | ||
| 446 | // logical | ||
| 447 | &&floatand, &&floator, &&floateq, &&floatne, | ||
| 448 | &&floatgt, &&floatge, &&floatlt, &&floatle, | ||
| 449 | &&floatgtimm, &&floatgeimm, &&floatltimm, &&floatleimm, | ||
| 450 | &&floatneg, &&floatnot, &&floatrassign, &&floatradd, | ||
| 451 | &&floatrsub, &&floatrmul, &&floatrdiv, &&ifadd, &&ifsub, &&ifmul, &&ifdiv, | ||
| 452 | &&ifand, &&ifor, &&ifeq, &&ifne, &&ifgt, &&ifge, &&iflt, &&ifle, | ||
| 453 | &&ifrassign, &&ifradd, &&ifrsub, &&ifrmul, &&ifrdiv, &&fiadd, &&fisub, | ||
| 454 | &&fimul, &&fidiv, &&fiand, &&fior, &&fieq, &&fine, &&figt, &&fige, &&filt, | ||
| 455 | &&file, &&firassign, &&firadd, &&firsub, &&firmul, &&firdiv, &&itof, | ||
| 456 | &&ftoi, &&timeadv, &&recurs, &&setcode, &®move, | ||
| 457 | &®tomem, &®tomemother, | ||
| 458 | &&overflow, | ||
| 459 | &&funcusrend, &&funcusrend2, &&funcmemberend, | ||
| 460 | &&sporkini, &&forkini, &&sporkfunc, &&sporkexp, &&sporkcode, | ||
| 461 | &&forkend, &&sporkend, &&brancheqint, &&branchneint, &&brancheqfloat, | ||
| 462 | &&branchnefloat, &&unroll, &&arrayappend, &&autounrollinit, &&autoloop, | ||
| 463 | &&arraytop, &&arrayaccess, &&arrayget, &&arrayaddr, &&newobj, &&addref, | ||
| 464 | &&addrefaddr, &&structaddref, &&structaddrefaddr, &&objassign, &&assign, | ||
| 465 | &&_remref, &&_remref2, &&_structreleaseregaddr, &&structreleasemem, | ||
| 466 | &&_except, | ||
| 467 | &&dotmembermem, &&dotmembermem2, /*&&dotmembermem3, */&&dotmembermem4, | ||
| 468 | &&dotmember, &&dotfloat, &&dotother, &&dotaddr, | ||
| 469 | &&unioncheck, &&unionint, &&unionfloat, | ||
| 470 | &&unionother, &&unionaddr, &&staticint, &&staticfloat, &&staticother, | ||
| 471 | &&dotfunc, &&gacktype, &&gackend, &&gack, &&try_ini, | ||
| 472 | &&try_end, &&handleeffect, &&performeffect, &&noop, &&debugline, | ||
| 473 | &&debugvalue, &&debugpush, &&debugpop, &&eoc, &&vmin, &&other}; | ||
| 474 | // &®pushimm}; | ||
| 475 | |||
| 476 |
2/2✓ Branch 0 taken 6083918 times.
✓ Branch 1 taken 3035 times.
|
6086953 | if(!prepare_code) { |
| 477 | PRAGMA_PUSH() | ||
| 478 | 6083918 | const Shreduler s = vm->shreduler; | |
| 479 | VM_Shred shred; | ||
| 480 |
2/2✓ Branch 1 taken 573 times.
✓ Branch 2 taken 6113154 times.
|
6084491 | while ((shred = shreduler_get(s))) { |
| 481 | 573 | VM_Code code = shred->code; | |
| 482 | 573 | m_bit * bytecode = code->bytecode; | |
| 483 | 573 | m_bit * byte = bytecode + shred->pc * BYTECODE_SZ; | |
| 484 | 573 | m_bit * reg = shred->reg; | |
| 485 | 573 | m_bit * mem = shred->mem; | |
| 486 | m_bit next; | ||
| 487 | |||
| 488 | #define VM_OUT \ | ||
| 489 | shred->code = code; \ | ||
| 490 | shred->reg = reg; \ | ||
| 491 | shred->mem = mem; \ | ||
| 492 | shred->pc = PC; | ||
| 493 | |||
| 494 | #define ADVANCE() byte += BYTECODE_SZ | ||
| 495 | #define SDISPATCH() goto **(void***)byte; | ||
| 496 | |||
| 497 | union { | ||
| 498 | M_Object obj; | ||
| 499 | VM_Code code; | ||
| 500 | } a; | ||
| 501 | VM_Shred child; | ||
| 502 | do { | ||
| 503 | 573 | SDISPATCH(); | |
| 504 | 20354 | regsetimm: | |
| 505 | 20354 | *(m_uint *)(reg + IVAL2) = VAL; | |
| 506 | 20354 | DISPATCH(); | |
| 507 | 8432 | regpushimm: | |
| 508 | 8432 | *(m_uint *)reg = VAL; | |
| 509 | 8432 | reg += SZ_INT; | |
| 510 | 8432 | DISPATCH(); | |
| 511 | 408 | regpushfloat: | |
| 512 | 408 | *(m_float *)reg = FVAL; | |
| 513 | 408 | reg += SZ_FLOAT; | |
| 514 | 408 | DISPATCH(); | |
| 515 | ✗ | regpushother: | |
| 516 | // LOOP_OPTIM | ||
| 517 | ✗ | for (m_uint i = 0; i <= VAL2; i += SZ_INT) | |
| 518 | ✗ | *(m_bit **)(reg + i) = *(m_bit **)(VAL + i); | |
| 519 | ✗ | reg += VAL2; | |
| 520 | ✗ | DISPATCH(); | |
| 521 | ✗ | regpushaddr: | |
| 522 | ✗ | *(m_uint **)reg = &VAL; | |
| 523 | ✗ | reg += SZ_INT; | |
| 524 | ✗ | DISPATCH() | |
| 525 | 1069 | regpushmem: | |
| 526 | 1069 | *(m_uint *)reg = *(m_uint *)(mem + IVAL); | |
| 527 | 1069 | reg += SZ_INT; | |
| 528 | 1069 | DISPATCH(); | |
| 529 | 161 | regpushmemfloat: | |
| 530 | 161 | *(m_float *)reg = *(m_float *)(mem + IVAL); | |
| 531 | 161 | reg += SZ_FLOAT; | |
| 532 | 161 | DISPATCH(); | |
| 533 | 2 | regpushmemother: | |
| 534 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
|
6 | for (m_uint i = 0; i <= VAL2; i += SZ_INT) |
| 535 | 4 | *(m_uint *)(reg + i) = *(m_uint *)((m_bit *)(mem + IVAL) + i); | |
| 536 | 2 | reg += VAL2; | |
| 537 | 2 | DISPATCH(); | |
| 538 | 315 | regpushmemaddr: | |
| 539 | 315 | *(m_bit **)reg = &*(m_bit *)(mem + IVAL); | |
| 540 | 315 | reg += SZ_INT; | |
| 541 | 315 | DISPATCH(); | |
| 542 | 27 | regpushmemderef: | |
| 543 | 27 | memcpy(reg, *(m_bit **)(mem + IVAL), VAL2); | |
| 544 | 27 | reg += VAL2; | |
| 545 | 27 | DISPATCH() | |
| 546 | 149 | pushnow: | |
| 547 | 149 | *(m_float *)reg = vm->bbq->pos; | |
| 548 | 149 | reg += SZ_FLOAT; | |
| 549 | 149 | DISPATCH(); | |
| 550 | 481 | baseint: | |
| 551 | 481 | *(m_uint *)reg = *(m_uint *)(shred->base + VAL); | |
| 552 | 481 | reg += SZ_INT; | |
| 553 | 481 | DISPATCH(); | |
| 554 | 30 | basefloat: | |
| 555 | 30 | *(m_float *)reg = *(m_float *)(shred->base + VAL); | |
| 556 | 30 | reg += SZ_FLOAT; | |
| 557 | 30 | DISPATCH(); | |
| 558 | ✗ | baseother: | |
| 559 | // LOOP_OPTIM | ||
| 560 | ✗ | for (m_uint i = 0; i <= VAL2; i += SZ_INT) | |
| 561 | ✗ | *(m_uint *)(reg + i) = *(m_uint *)((shred->base + VAL) + i); | |
| 562 | ✗ | reg += VAL2; | |
| 563 | ✗ | DISPATCH(); | |
| 564 | 89 | baseaddr: | |
| 565 | 89 | *(m_uint **)reg = &*(m_uint *)(shred->base + IVAL); | |
| 566 | 89 | reg += SZ_INT; | |
| 567 | 89 | DISPATCH(); | |
| 568 | 1506 | regtoreg: | |
| 569 | 1506 | *(m_uint *)(reg + IVAL) = *(m_uint *)(reg + IVAL2); | |
| 570 | 1506 | DISPATCH() | |
| 571 | 1 | regtoregother2: | |
| 572 | 1 | memcpy(reg - VAL2, reg + IVAL, VAL2); | |
| 573 | 1 | DISPATCH() | |
| 574 | ✗ | regtoregaddr: | |
| 575 | ✗ | *(m_uint **)(reg + IVAL) = &*(m_uint *)(reg + IVAL2); | |
| 576 | ✗ | DISPATCH() | |
| 577 | 15 | regtoregderef: | |
| 578 | 15 | memcpy(*(m_bit **)(reg - SZ_INT), *(m_bit **)(reg + IVAL), VAL2); | |
| 579 | 15 | DISPATCH() | |
| 580 | 24 | structmember: | |
| 581 | 24 | *(m_bit **)(reg - SZ_INT) = | |
| 582 | 24 | *(m_bit **)(*(m_bit **)(reg - SZ_INT) + IVAL); | |
| 583 | 24 | DISPATCH() | |
| 584 | 20 | structmemberfloat: | |
| 585 | 20 | *(m_bit **)(reg - SZ_INT) = | |
| 586 | 20 | *(m_bit **)(*(m_bit **)(reg - SZ_INT) + IVAL); | |
| 587 | 20 | DISPATCH() | |
| 588 | ✗ | structmemberother: | |
| 589 | ✗ | *(m_bit **)(reg - SZ_INT) = | |
| 590 | ✗ | *(m_bit **)(*(m_bit **)(reg - SZ_INT) + IVAL); | |
| 591 | ✗ | DISPATCH() | |
| 592 | 38 | structmemberaddr: | |
| 593 | 38 | *(m_bit **)(reg - SZ_INT) = &*(*(m_bit **)(reg - SZ_INT) + IVAL); | |
| 594 | 38 | DISPATCH() | |
| 595 | 104 | memsetimm: | |
| 596 | 104 | *(m_uint *)(mem + VAL) = VAL2; | |
| 597 | 104 | DISPATCH(); | |
| 598 | ✗ | memaddimm: | |
| 599 | ✗ | *(m_int *)(mem + VAL) += IVAL2; | |
| 600 | // (*(m_int*)(mem+VAL))--; | ||
| 601 | ✗ | DISPATCH(); | |
| 602 | 101 | repeatidx: | |
| 603 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 100 times.
|
101 | BRANCH_DISPATCH(*(m_int *)(mem + VAL2 + SZ_INT) == |
| 604 | ++(*(m_int *)(mem + VAL2))); | ||
| 605 | 124 | repeat: | |
| 606 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 120 times.
|
124 | BRANCH_DISPATCH(!(*(m_uint *)(mem + VAL2))--); |
| 607 | 35 | regpushme: | |
| 608 | 35 | *(M_Object *)reg = shred->info->me; | |
| 609 | 35 | reg += SZ_INT; | |
| 610 | 35 | DISPATCH() | |
| 611 | 39 | regpushmaybe: | |
| 612 | |||
| 613 | #ifndef __AFL_HAVE_MANUAL_CONTROL | ||
| 614 | 39 | *(m_uint *)reg = gw_rand((uint32_t *)vm->rand) > (UINT32_MAX / 2); | |
| 615 | #else | ||
| 616 | *(m_uint *)reg = 0; | ||
| 617 | #endif | ||
| 618 | 39 | reg += SZ_INT; | |
| 619 | 39 | DISPATCH(); | |
| 620 | 1781 | funcreturn : { | |
| 621 | 1781 | register frame_t frame = *(frame_t *)(mem - sizeof(frame_t)); | |
| 622 | 1781 | bytecode = (code = frame.code)->bytecode; | |
| 623 | 1781 | mem -= frame.push; | |
| 624 | 1781 | PC_DISPATCH(frame.pc); | |
| 625 | } | ||
| 626 | 517 | _goto: | |
| 627 | 517 | PC_DISPATCH(VAL); | |
| 628 | 124 | allocint: | |
| 629 | 124 | *(m_uint *)reg = *(m_uint *)(mem + VAL) = 0; | |
| 630 | 124 | reg += SZ_INT; | |
| 631 | 124 | DISPATCH() | |
| 632 | 86 | allocfloat: | |
| 633 | 86 | *(m_float *)reg = *(m_float *)(mem + VAL) = 0; | |
| 634 | 86 | reg += SZ_FLOAT; | |
| 635 | 86 | DISPATCH() | |
| 636 | ✗ | allocother: | |
| 637 | // LOOP_OPTIM | ||
| 638 | ✗ | for (m_uint i = 0; i <= VAL2; i += SZ_INT) | |
| 639 | ✗ | *(m_uint *)(reg + i) = (*(m_uint *)(mem + VAL + i) = 0); | |
| 640 | ✗ | reg += VAL2; | |
| 641 | ✗ | DISPATCH() | |
| 642 | |||
| 643 | 72 | intplus: | |
| 644 | 72 | INT_OP(+) | |
| 645 | 1 | intminus: | |
| 646 | 1 | INT_OP(-) | |
| 647 | 1 | intmul: | |
| 648 | 1 | INT_OP(*) | |
| 649 | 3 | intdiv: | |
| 650 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | INT_OP(/, TEST0(m_int, 0)) |
| 651 | 1 | intmod: | |
| 652 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | INT_OP(%, TEST0(m_int, 0)) |
| 653 | |||
| 654 | 2 | intplusimm: | |
| 655 | 2 | INT_IMM_OP(+=) | |
| 656 | 104 | intminusimm: | |
| 657 | 104 | INT_IMM_OP(-=) | |
| 658 | ✗ | intmulimm: | |
| 659 | ✗ | INT_IMM_OP(*=) | |
| 660 | ✗ | intdivimm: | |
| 661 | ✗ | INT_IMM_OP(/=) | |
| 662 | ✗ | intmodimm: | |
| 663 | ✗ | INT_IMM_OP(%=) | |
| 664 | |||
| 665 | 167 | inteq: | |
| 666 | 167 | INT_LOGICAL(==) | |
| 667 | 2 | intne: | |
| 668 | 2 | INT_LOGICAL(!=) | |
| 669 | 1 | intand: | |
| 670 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | INT_LOGICAL(&&) |
| 671 | 1 | intor: | |
| 672 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | INT_LOGICAL(||) |
| 673 | 1 | intgt: | |
| 674 | 1 | INT_LOGICAL(>) | |
| 675 | 1 | intge: | |
| 676 | 1 | INT_LOGICAL(>=) | |
| 677 | 1 | intlt: | |
| 678 | 1 | INT_LOGICAL(<) | |
| 679 | 1 | intle: | |
| 680 | 1 | INT_LOGICAL(<=) | |
| 681 | 27 | intgtimm: | |
| 682 | 27 | INT_IMM_LOGICAL(>) | |
| 683 | ✗ | intgeimm: | |
| 684 | ✗ | INT_IMM_LOGICAL(>=) | |
| 685 | 38 | intltimm: | |
| 686 | 38 | INT_IMM_LOGICAL(<) | |
| 687 | ✗ | intleimm: | |
| 688 | ✗ | INT_IMM_LOGICAL(<=) | |
| 689 | 1 | intsl: | |
| 690 | 1 | INT_LOGICAL(<<) | |
| 691 | 1 | intsr: | |
| 692 | 1 | INT_LOGICAL(>>) | |
| 693 | 1 | intsand: | |
| 694 | 1 | INT_LOGICAL(&) | |
| 695 | 1 | intsor: | |
| 696 | 1 | INT_LOGICAL(|) | |
| 697 | 1 | intxor: | |
| 698 | 1 | INT_LOGICAL(^) | |
| 699 | |||
| 700 | 1 | intnegate: | |
| 701 | 1 | *(m_int *)(reg - SZ_INT) *= -1; | |
| 702 | 1 | DISPATCH() | |
| 703 | 24 | intnot: | |
| 704 | 24 | SELF(m_int, SZ_INT, !) | |
| 705 | ✗ | intcmp: | |
| 706 | ✗ | SELF(m_int, SZ_INT, ~) | |
| 707 | |||
| 708 | 1445 | intrassign: | |
| 709 | 1445 | reg -= SZ_INT; | |
| 710 | 1445 | **(m_int **)reg = *(m_int *)(reg - SZ_INT); | |
| 711 | 1445 | DISPATCH() | |
| 712 | |||
| 713 | 1 | intradd: | |
| 714 | 1 | INT_R(+) | |
| 715 | 1 | intrsub: | |
| 716 | 1 | INT_R(-) | |
| 717 | 1 | intrmul: | |
| 718 | 1 | INT_R(*) | |
| 719 | // intrdiv: INT_R(/, TEST0(m_int, -SZ_INT)) | ||
| 720 | // intrmod: INT_R(%, TEST0(m_int, -SZ_INT)) | ||
| 721 | 1 | intrdiv: | |
| 722 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | INT_R(/, TEST0(m_int, SZ_INT)) |
| 723 | 1 | intrmod: | |
| 724 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | INT_R(%, TEST0(m_int, SZ_INT)) |
| 725 | 1 | intrsl: | |
| 726 | 1 | INT_R(<<) | |
| 727 | 1 | intrsr: | |
| 728 | 1 | INT_R(>>) | |
| 729 | 1 | intrsand: | |
| 730 | 1 | INT_R(&) | |
| 731 | 1 | intrsor: | |
| 732 | 1 | INT_R(|) | |
| 733 | 1 | intrxor: | |
| 734 | 1 | INT_R(^) | |
| 735 | |||
| 736 | 67 | preinc: | |
| 737 | 67 | INT_PRE(++) | |
| 738 | 25 | predec: | |
| 739 | 25 | INT_PRE(--) | |
| 740 | |||
| 741 | 26 | postinc: | |
| 742 | 26 | INT_POST(++) | |
| 743 | 18 | postdec: | |
| 744 | 18 | INT_POST(--) | |
| 745 | |||
| 746 | 3 | floatadd: | |
| 747 | 3 | FLOAT_OP(+) | |
| 748 | 1 | floatsub: | |
| 749 | 1 | FLOAT_OP(-) | |
| 750 | 72 | floatmul: | |
| 751 | 72 | FLOAT_OP(*) | |
| 752 | 1 | floatdiv: | |
| 753 | 1 | FLOAT_OP(/) | |
| 754 | |||
| 755 | ✗ | floataddimm: | |
| 756 | ✗ | FLOAT_IMM_OP(+=) | |
| 757 | ✗ | floatsubimm: | |
| 758 | ✗ | FLOAT_IMM_OP(-=) | |
| 759 | ✗ | floatmulimm: | |
| 760 | ✗ | FLOAT_IMM_OP(*=) | |
| 761 | ✗ | floatdivimm: | |
| 762 | ✗ | FLOAT_IMM_OP(/=) | |
| 763 | |||
| 764 | 1 | floatand: | |
| 765 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | FLOAT_LOGICAL(&&) |
| 766 | 1 | floator: | |
| 767 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | FLOAT_LOGICAL(||) |
| 768 | 68 | floateq: | |
| 769 | 68 | FLOAT_LOGICAL(==) | |
| 770 | 1 | floatne: | |
| 771 | 1 | FLOAT_LOGICAL(!=) | |
| 772 | 1 | floatgt: | |
| 773 | 1 | FLOAT_LOGICAL(>) | |
| 774 | 3 | floatge: | |
| 775 | 3 | FLOAT_LOGICAL(>=) | |
| 776 | 5 | floatlt: | |
| 777 | 5 | FLOAT_LOGICAL(<) | |
| 778 | 1 | floatle: | |
| 779 | 1 | FLOAT_LOGICAL(<=) | |
| 780 | 5 | floatgtimm: | |
| 781 | 5 | FLOAT_IMM_LOGICAL(>) | |
| 782 | ✗ | floatgeimm: | |
| 783 | ✗ | FLOAT_IMM_LOGICAL(>=) | |
| 784 | ✗ | floatltimm: | |
| 785 | ✗ | FLOAT_IMM_LOGICAL(<) | |
| 786 | ✗ | floatleimm: | |
| 787 | ✗ | FLOAT_IMM_LOGICAL(<=) | |
| 788 | |||
| 789 | 1 | floatneg: | |
| 790 | 1 | SELF(m_float, SZ_FLOAT, -) | |
| 791 | |||
| 792 | 3 | floatnot: | |
| 793 | 3 | reg -= SZ_FLOAT - SZ_INT; | |
| 794 | 3 | *(m_int *)(reg - SZ_INT) = !*(m_float *)(reg - SZ_INT); | |
| 795 | 3 | DISPATCH() | |
| 796 | |||
| 797 | 9 | floatrassign: | |
| 798 | 9 | reg -= SZ_INT; | |
| 799 | 9 | **(m_float **)reg = *(m_float *)(reg - SZ_FLOAT); | |
| 800 | 9 | DISPATCH() | |
| 801 | |||
| 802 | 1 | floatradd: | |
| 803 | 1 | FLOAT_R(+) | |
| 804 | 11 | floatrsub: | |
| 805 | 11 | FLOAT_R(-) | |
| 806 | 1 | floatrmul: | |
| 807 | 1 | FLOAT_R(*) | |
| 808 | 1 | floatrdiv: | |
| 809 | 1 | FLOAT_R(/) | |
| 810 | |||
| 811 | 1 | ifadd: | |
| 812 | 1 | IF_OP(+) | |
| 813 | 2 | ifsub: | |
| 814 | 2 | IF_OP(-) | |
| 815 | 22 | ifmul: | |
| 816 | 22 | IF_OP(*) | |
| 817 | 1 | ifdiv: | |
| 818 | 1 | IF_OP(/) | |
| 819 | |||
| 820 | 1 | ifand: | |
| 821 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | IF_LOGICAL(&&) |
| 822 | 1 | ifor: | |
| 823 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | IF_LOGICAL(||) |
| 824 | 1 | ifeq: | |
| 825 | 1 | IF_LOGICAL(==) | |
| 826 | 1 | ifne: | |
| 827 | 1 | IF_LOGICAL(!=) | |
| 828 | 1 | ifgt: | |
| 829 | 1 | IF_LOGICAL(>) | |
| 830 | 1 | ifge: | |
| 831 | 1 | IF_LOGICAL(>=) | |
| 832 | 1 | iflt: | |
| 833 | 1 | IF_LOGICAL(<) | |
| 834 | 1 | ifle: | |
| 835 | 1 | IF_LOGICAL(<=) | |
| 836 | |||
| 837 | 13 | ifrassign: | |
| 838 | 13 | IF_R() | |
| 839 | 5 | ifradd: | |
| 840 | 5 | IF_R(+) | |
| 841 | 17 | ifrsub: | |
| 842 | 17 | IF_R(-) | |
| 843 | 1 | ifrmul: | |
| 844 | 1 | IF_R(*) | |
| 845 | 1 | ifrdiv: | |
| 846 | 1 | IF_R(/) | |
| 847 | |||
| 848 | 1 | fiadd: | |
| 849 | 1 | FI_OP(+) | |
| 850 | 1 | fisub: | |
| 851 | 1 | FI_OP(-) | |
| 852 | 1 | fimul: | |
| 853 | 1 | FI_OP(*) | |
| 854 | 1 | fidiv: | |
| 855 | 1 | FI_OP(/) | |
| 856 | |||
| 857 | 1 | fiand: | |
| 858 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | FI_LOGICAL(&&) |
| 859 | 1 | fior: | |
| 860 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | FI_LOGICAL(||) |
| 861 | 6 | fieq: | |
| 862 | 6 | FI_LOGICAL(==) | |
| 863 | 1 | fine: | |
| 864 | 1 | FI_LOGICAL(!=) | |
| 865 | 24 | figt: | |
| 866 | 24 | FI_LOGICAL(>) | |
| 867 | 1 | fige: | |
| 868 | 1 | FI_LOGICAL(>=) | |
| 869 | 1 | filt: | |
| 870 | 1 | FI_LOGICAL(<) | |
| 871 | 1 | file: | |
| 872 | 1 | FI_LOGICAL(<=) | |
| 873 | |||
| 874 | 1 | firassign: | |
| 875 | 1 | reg -= SZ_FLOAT; | |
| 876 | 1 | *(m_int *)(reg - SZ_INT) = **(m_int **)(reg + SZ_FLOAT - SZ_INT) = | |
| 877 | 1 | (m_int) * (m_float *)(reg - SZ_INT); | |
| 878 | 1 | DISPATCH() | |
| 879 | |||
| 880 | 1 | firadd: | |
| 881 | 1 | FI_R(+) | |
| 882 | 2 | firsub: | |
| 883 | 2 | FI_R(-) | |
| 884 | 1 | firmul: | |
| 885 | 1 | FI_R(*) | |
| 886 | 1 | firdiv: | |
| 887 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | FI_R(/, TEST0(m_float, SZ_INT)) |
| 888 | |||
| 889 | 14 | itof: | |
| 890 | 14 | reg -= SZ_INT - SZ_FLOAT; | |
| 891 | 14 | *(m_float *)(reg - SZ_FLOAT) = (m_float) * (m_int *)(reg - SZ_FLOAT); | |
| 892 | 14 | DISPATCH() | |
| 893 | 1 | ftoi: | |
| 894 | { | ||
| 895 | 1 | const m_float f = * (m_float *)(reg - SZ_FLOAT); | |
| 896 | 1 | reg -= SZ_FLOAT - SZ_INT; | |
| 897 | 1 | *(m_int *)(reg - SZ_INT) = (m_int)f; | |
| 898 | 1 | DISPATCH() | |
| 899 | } | ||
| 900 | 137 | timeadv: | |
| 901 | 137 | reg -= SZ_FLOAT; | |
| 902 | 137 | shredule(s, shred, *(m_float *)(reg - SZ_FLOAT)); | |
| 903 | 137 | *(m_float *)(reg - SZ_FLOAT) += vm->bbq->pos; | |
| 904 | 137 | VM_OUT | |
| 905 | 137 | break; | |
| 906 | 12352 | recurs: | |
| 907 | { | ||
| 908 | 12352 | register const uint push = SVAL2; | |
| 909 | 12352 | mem += push; | |
| 910 | 12352 | *(frame_t *)(mem - sizeof(frame_t)) = | |
| 911 | 12352 | (frame_t) {.code = code, .pc = SVAL, .push = push}; | |
| 912 | 12352 | reg += IVAL; | |
| 913 | 12352 | next = eFuncUsrEnd2; | |
| 914 | } | ||
| 915 | 12352 | DISPATCH(); | |
| 916 | 4784 | setcode: | |
| 917 | 4784 | a.code = *(VM_Code *)(reg - SZ_INT); | |
| 918 |
2/2✓ Branch 0 taken 4449 times.
✓ Branch 1 taken 335 times.
|
4784 | if (!a.code->builtin) { |
| 919 | 4449 | register const uint push = | |
| 920 | 4449 | *(m_uint *)reg /*+ code->stack_depth*/ + sizeof(frame_t); | |
| 921 | 4449 | mem += push; | |
| 922 | 4449 | *(frame_t *)(mem - sizeof(frame_t)) = | |
| 923 | 4449 | (frame_t) {.code = code, .pc = PC + SVAL, .push = push}; | |
| 924 | 4449 | next = eFuncUsrEnd; | |
| 925 | } else { | ||
| 926 | 335 | mem += *(m_uint *)reg; | |
| 927 | 335 | next = eFuncMemberEnd; | |
| 928 | } | ||
| 929 | 10020 | regmove: | |
| 930 | 10020 | reg += IVAL; | |
| 931 | 10020 | DISPATCH(); | |
| 932 | 4958 | regtomem: | |
| 933 | 4958 | *(m_uint *)(mem + VAL) = *(m_uint *)(reg + IVAL2); | |
| 934 | 4958 | DISPATCH() | |
| 935 | 218 | regtomemother: | |
| 936 | 218 | memcpy(mem + VAL, reg, VAL2); | |
| 937 | 218 | DISPATCH() | |
| 938 | 17136 | overflow: | |
| 939 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 17132 times.
|
17136 | if (overflow_(mem + VAL2, shred)) { |
| 940 | 4 | handle(shred, "StackOverflow"); | |
| 941 | 4 | continue; | |
| 942 | } | ||
| 943 | 17132 | goto *dispatch[next]; | |
| 944 | 4448 | funcusrend: | |
| 945 | 4448 | byte = bytecode = (code = a.code)->bytecode; | |
| 946 | 4448 | SDISPATCH(); | |
| 947 | 12349 | funcusrend2: | |
| 948 | 12349 | byte = bytecode; | |
| 949 | 12349 | SDISPATCH(); | |
| 950 | 335 | funcmemberend: | |
| 951 | 335 | VM_OUT { | |
| 952 | 335 | register const m_uint val = VAL; | |
| 953 | 335 | register const m_uint val2 = VAL2; | |
| 954 | 335 | ((f_mfun)a.code->native_func)((*(M_Object *)mem), reg, shred); | |
| 955 | 335 | reg += val; | |
| 956 | 335 | shred->mem = (mem -= val2); | |
| 957 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 301 times.
|
335 | if (!s->curr) break; |
| 958 | } | ||
| 959 | 301 | PC_DISPATCH(shred->pc) | |
| 960 | 74 | sporkini: | |
| 961 | 74 | child = init_spork_shred(shred, (VM_Code)VAL); | |
| 962 | 74 | DISPATCH() | |
| 963 | 5 | forkini: | |
| 964 | 5 | child = init_fork_shred(shred, (VM_Code)VAL, (Type)VAL2); | |
| 965 | 5 | DISPATCH() | |
| 966 | 48 | sporkfunc: | |
| 967 | // LOOP_OPTIM | ||
| 968 |
2/2✓ Branch 0 taken 99 times.
✓ Branch 1 taken 48 times.
|
147 | for (m_uint i = 0; i < VAL; i += SZ_INT) |
| 969 | 99 | *(m_uint *)(child->reg + i) = *(m_uint *)(reg + i + IVAL2); | |
| 970 | 48 | child->reg += VAL; | |
| 971 | 48 | DISPATCH() | |
| 972 | 31 | sporkexp: | |
| 973 | // LOOP_OPTIM | ||
| 974 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
|
42 | for (m_uint i = 0; i < VAL; i += SZ_INT) |
| 975 | 11 | *(m_uint *)(child->mem + i) = *(m_uint *)(mem + i); | |
| 976 | 31 | DISPATCH() | |
| 977 | 11 | sporkcode: | |
| 978 | // LOOP_OPTIM | ||
| 979 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
|
22 | for (m_uint i = 0; i < VAL; i += SZ_INT) |
| 980 | 11 | *(m_uint *)(child->mem + i) = *(m_uint *)(reg + i); | |
| 981 | 11 | DISPATCH() | |
| 982 | 5 | forkend: | |
| 983 | 5 | fork_launch(child->info->me); | |
| 984 | 79 | sporkend: | |
| 985 | assert(!VAL); // spork are not mutable | ||
| 986 | 79 | *(M_Object *)(reg - SZ_INT) = child->info->me; | |
| 987 | 79 | DISPATCH() | |
| 988 | 465 | brancheqint: | |
| 989 | 465 | reg -= SZ_INT; | |
| 990 |
2/2✓ Branch 0 taken 268 times.
✓ Branch 1 taken 197 times.
|
465 | BRANCH_DISPATCH(!*(m_uint *)reg); |
| 991 | 41 | branchneint: | |
| 992 | 41 | reg -= SZ_INT; | |
| 993 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 16 times.
|
41 | BRANCH_DISPATCH(*(m_uint *)reg); |
| 994 | 4 | brancheqfloat: | |
| 995 | 4 | reg -= SZ_FLOAT; | |
| 996 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | BRANCH_DISPATCH(!*(m_float *)reg); |
| 997 | 8 | branchnefloat: | |
| 998 | 8 | reg -= SZ_FLOAT; | |
| 999 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
|
8 | BRANCH_DISPATCH(*(m_float *)reg); |
| 1000 | 2 | unroll : { | |
| 1001 | 2 | const m_uint n = *(m_uint *)(mem + VAL - SZ_INT); | |
| 1002 | 2 | const m_uint idx = *(m_uint *)(mem + VAL); | |
| 1003 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (idx > 0) { |
| 1004 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (idx >= n) { |
| 1005 | 2 | *(m_uint *)(mem + VAL) -= n; | |
| 1006 | 2 | DISPATCH() | |
| 1007 | } | ||
| 1008 | ✗ | *(m_uint *)(mem + VAL) = 0; | |
| 1009 | ✗ | PC_DISPATCH(PC + VAL2 * (idx + 1)); | |
| 1010 | } | ||
| 1011 | ✗ | PC_DISPATCH(PC + VAL2 * n + 1); | |
| 1012 | } | ||
| 1013 | ✗ | arrayappend: | |
| 1014 | ✗ | m_vector_add(ARRAY(*(M_Object *)(reg - SZ_INT)), reg); | |
| 1015 | ✗ | DISPATCH() | |
| 1016 | 1 | autounrollinit: | |
| 1017 | 1 | *(m_uint *)(mem + VAL) = | |
| 1018 | 1 | m_vector_size(ARRAY(*(M_Object *)(mem + VAL + SZ_INT))) + 1; | |
| 1019 | 1 | DISPATCH() | |
| 1020 | 24 | autoloop: { | |
| 1021 | 24 | const M_Vector array = ARRAY(*(M_Object *)(mem + VAL2 - SZ_INT)); | |
| 1022 | 24 | const bool end = ++*(m_uint *)(mem + VAL2) == m_vector_size(array); | |
| 1023 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
|
24 | if(!end) { |
| 1024 | 18 | *(m_bit **)(mem + VAL2 + SZ_INT) = | |
| 1025 | 18 | m_vector_addr(array, *(m_uint *)(mem + VAL2)); | |
| 1026 | } | ||
| 1027 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 18 times.
|
24 | BRANCH_DISPATCH(end); |
| 1028 | } | ||
| 1029 | 11 | arraytop: | |
| 1030 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
|
11 | if (*(m_uint *)(reg - SZ_INT * 2) < *(m_uint *)(reg - SZ_INT)) |
| 1031 | 7 | goto newobj; | |
| 1032 | else | ||
| 1033 | 4 | goto _goto; | |
| 1034 | 5 | arrayaccess : { | |
| 1035 | 5 | register const m_int idx = *(m_int *)(reg + VAL); | |
| 1036 | 5 | a.obj = *(M_Object *)(reg - VAL2); | |
| 1037 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
|
5 | if (idx < 0 || (m_uint)idx >= m_vector_size(ARRAY(a.obj))) { |
| 1038 | 4 | gw_err(_("{-} ... at index {W}[{Y}%" INT_F "{W}]{0}\n"), idx); | |
| 1039 | // gw_err(_(" ... at dimension [%" INT_F "]\n"), VAL); | ||
| 1040 | // VM_OUT | ||
| 1041 | 4 | handle(shred, "ArrayOutofBounds"); | |
| 1042 | 4 | continue; // or break ? | |
| 1043 | } | ||
| 1044 | 1 | DISPATCH() | |
| 1045 | } | ||
| 1046 | 1 | arrayget: | |
| 1047 | 1 | m_vector_get(ARRAY(a.obj), *(m_int *)(reg + VAL), (reg + IVAL2)); | |
| 1048 | 1 | DISPATCH() | |
| 1049 | ✗ | arrayaddr: | |
| 1050 | ✗ | *(m_bit **)(reg + IVAL2) = | |
| 1051 | ✗ | m_vector_addr(ARRAY(a.obj), *(m_int *)(reg + VAL)); | |
| 1052 | ✗ | DISPATCH() | |
| 1053 | 2896 | newobj: | |
| 1054 | 2896 | *(M_Object *)reg = new_object(vm->gwion->mp, (Type)VAL2); | |
| 1055 | 2896 | reg += SZ_INT; | |
| 1056 | 2896 | DISPATCH() | |
| 1057 | 756 | addref : { | |
| 1058 | 756 | const M_Object o = *(M_Object *)(reg + IVAL); | |
| 1059 |
1/2✓ Branch 0 taken 756 times.
✗ Branch 1 not taken.
|
756 | if(o) |
| 1060 | 756 | ++o->ref; | |
| 1061 | } | ||
| 1062 | 756 | DISPATCH() | |
| 1063 | ✗ | addrefaddr : { | |
| 1064 | ✗ | const M_Object o = **(M_Object **)(reg + IVAL); | |
| 1065 | ✗ | if (o) ++o->ref; | |
| 1066 | } | ||
| 1067 | ✗ | DISPATCH() | |
| 1068 | ✗ | structaddref: | |
| 1069 | ✗ | struct_addref(vm->gwion, (Type)VAL2, (reg + IVAL)); | |
| 1070 | ✗ | DISPATCH() | |
| 1071 | ✗ | structaddrefaddr: | |
| 1072 | ✗ | struct_addref(vm->gwion, (Type)VAL2, *(m_bit **)(reg + IVAL)); | |
| 1073 | ✗ | DISPATCH() | |
| 1074 | 7 | objassign : { | |
| 1075 | 7 | const M_Object o = **(M_Object **)(reg - SZ_INT); | |
| 1076 | 7 | release(o, shred); | |
| 1077 | } | ||
| 1078 | 176 | assign: | |
| 1079 | 176 | reg -= SZ_INT; | |
| 1080 | 176 | **(M_Object **)reg = *(M_Object *)(reg - SZ_INT); | |
| 1081 | 176 | DISPATCH() | |
| 1082 | 203 | remref: | |
| 1083 | 203 | release(*(M_Object *)(mem + VAL), shred); | |
| 1084 | 203 | DISPATCH() | |
| 1085 | 19 | remref2: | |
| 1086 | { | ||
| 1087 | 19 | struct Vector_ v = { .ptr = (m_uint*)VAL }; | |
| 1088 |
2/2✓ Branch 1 taken 51 times.
✓ Branch 2 taken 19 times.
|
70 | for(m_uint i = 0; i < vector_size(&v); i++) |
| 1089 | 51 | release(*(M_Object *)(mem + vector_at(&v, i)), shred); | |
| 1090 | } | ||
| 1091 | 19 | DISPATCH() | |
| 1092 | ✗ | structreleaseregaddr: | |
| 1093 | ✗ | struct_release(shred, (Type)VAL2, *(m_bit**)(reg + IVAL)); | |
| 1094 | ✗ | DISPATCH(); | |
| 1095 | 29 | structreleasemem: | |
| 1096 | 29 | struct_release(shred, (Type)VAL2, mem + IVAL); | |
| 1097 | 29 | DISPATCH(); | |
| 1098 | 2 | except: | |
| 1099 | /* TODO: Refactor except instruction * | ||
| 1100 | * so that * | ||
| 1101 | * VAL = offset (no default SZ_INT) * | ||
| 1102 | * VAL2 = error message * | ||
| 1103 | * grep for GWOP_EXCEPT and Except, exception... */ | ||
| 1104 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (!*(m_bit **)(reg + (m_int)(VAL))) { |
| 1105 | 1 | handle(shred, "NullPtrException"); | |
| 1106 | 1 | continue; | |
| 1107 | } | ||
| 1108 | 1 | DISPATCH(); | |
| 1109 | 48 | dotmembermem: | |
| 1110 | 48 | *(m_uint *)reg = | |
| 1111 | 48 | *(m_uint *)((*(M_Object *)(mem + VAL2))->data + VAL); | |
| 1112 | 48 | reg += SZ_INT; | |
| 1113 | 48 | DISPATCH() | |
| 1114 | 3 | dotmembermem2: | |
| 1115 | 3 | *(m_float *)(reg + SZ_INT) = | |
| 1116 | 3 | *(m_float *)((*(M_Object *)(mem + VAL2))->data + VAL); | |
| 1117 | 3 | reg += SZ_INT - SZ_FLOAT; | |
| 1118 | 3 | DISPATCH() | |
| 1119 | // dotmembermem3: | ||
| 1120 | 1422 | dotmembermem4: | |
| 1121 | 1422 | *(m_bit **)reg = | |
| 1122 | 1422 | ((*(M_Object *)(mem + VAL2))->data + VAL); | |
| 1123 | 1422 | reg += SZ_INT; | |
| 1124 | 1422 | DISPATCH() | |
| 1125 | 47 | dotmember: | |
| 1126 | 47 | *(m_uint *)(reg - SZ_INT) = | |
| 1127 | 47 | *(m_uint *)((*(M_Object *)(reg - SZ_INT))->data + VAL); | |
| 1128 | 47 | DISPATCH() | |
| 1129 | 3 | dotfloat: | |
| 1130 | 3 | *(m_float *)(reg - SZ_INT) = | |
| 1131 | 3 | *(m_float *)((*(M_Object *)(reg - SZ_INT))->data + VAL); | |
| 1132 | 3 | reg += SZ_FLOAT - SZ_INT; | |
| 1133 | 3 | DISPATCH() | |
| 1134 | ✗ | dotother: | |
| 1135 | // LOOP_OPTIM | ||
| 1136 | ✗ | for (m_uint i = 0; i <= VAL2; i += SZ_INT) | |
| 1137 | ✗ | *(m_uint *)(reg + i - SZ_INT) = | |
| 1138 | ✗ | *(m_uint *)(((*(M_Object *)(reg - SZ_INT))->data + VAL) + i); | |
| 1139 | ✗ | reg += VAL2 - SZ_INT; | |
| 1140 | ✗ | DISPATCH() | |
| 1141 | 2 | dotaddr: | |
| 1142 | 2 | *(m_bit **)(reg - SZ_INT) = ((*(M_Object *)(reg - SZ_INT))->data + VAL); | |
| 1143 | 2 | DISPATCH() | |
| 1144 | |||
| 1145 | #define UNION_CHECK \ | ||
| 1146 | register const m_bit *data = (*(M_Object *)(reg - SZ_INT))->data; \ | ||
| 1147 | if (*(m_uint *)data != VAL) { \ | ||
| 1148 | handle(shred, "invalid union acces"); \ | ||
| 1149 | continue; \ | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | ✗ | unioncheck : { | |
| 1153 | ✗ | if (*(m_uint *)(*(M_Object *)(reg - SZ_INT))->data != VAL2) { | |
| 1154 | ✗ | reg -= SZ_INT; | |
| 1155 | ✗ | PC_DISPATCH(VAL); | |
| 1156 | } | ||
| 1157 | ✗ | DISPATCH() | |
| 1158 | } | ||
| 1159 | 4 | unionint : { | |
| 1160 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | UNION_CHECK |
| 1161 | 3 | *(m_uint *)(reg - SZ_INT) = *(m_uint *)(data + SZ_INT); | |
| 1162 | 3 | DISPATCH() | |
| 1163 | } | ||
| 1164 | 1 | unionfloat : { | |
| 1165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | UNION_CHECK |
| 1166 | 1 | *(m_float *)(reg - SZ_INT) = *(m_float *)(data + SZ_INT); | |
| 1167 | 1 | reg += SZ_FLOAT - SZ_INT; | |
| 1168 | 1 | DISPATCH() | |
| 1169 | } | ||
| 1170 | ✗ | unionother : { | |
| 1171 | ✗ | UNION_CHECK | |
| 1172 | ✗ | for (m_uint i = 0; i <= VAL2; i += SZ_INT) | |
| 1173 | ✗ | *(m_uint *)(reg + i - SZ_INT) = *(m_uint *)(data + SZ_INT + i); | |
| 1174 | ✗ | reg += VAL2 - SZ_INT; | |
| 1175 | ✗ | DISPATCH() | |
| 1176 | } | ||
| 1177 | 3 | unionaddr : { | |
| 1178 | 3 | *(m_uint *)(*(M_Object *)(reg - SZ_INT))->data = VAL; | |
| 1179 | 3 | *(m_bit **)(reg - SZ_INT) = | |
| 1180 | 3 | &*(m_bit *)((*(M_Object *)(reg - SZ_INT))->data + SZ_INT); | |
| 1181 | 3 | DISPATCH() | |
| 1182 | } | ||
| 1183 | 37 | staticint: | |
| 1184 | 37 | *(m_uint *)reg = *(m_uint *)VAL; | |
| 1185 | 37 | reg += SZ_INT; | |
| 1186 | 37 | DISPATCH() | |
| 1187 | 3 | staticfloat: | |
| 1188 | 3 | *(m_float *)reg = *(m_float *)VAL; | |
| 1189 | 3 | reg += SZ_FLOAT; | |
| 1190 | 3 | DISPATCH() | |
| 1191 | ✗ | staticother: | |
| 1192 | // LOOP_OPTIM | ||
| 1193 | // for(m_uint i = 0; i <= VAL2; i += SZ_INT) | ||
| 1194 | // *(m_uint*)(reg+i) = *(m_uint*)((m_bit*)VAL + i); | ||
| 1195 | ✗ | memcpy(reg, (m_bit *)VAL, VAL2); | |
| 1196 | ✗ | reg += VAL2; | |
| 1197 | ✗ | DISPATCH() | |
| 1198 | 283 | dotfunc: | |
| 1199 | 283 | *(VM_Code *)(reg + IVAL2) = | |
| 1200 | 283 | ((Func)(*(M_Object *)(reg - SZ_INT))->type_ref->nspc->vtable.ptr[OFFSET + VAL])->code; | |
| 1201 | 283 | DISPATCH() | |
| 1202 | 224 | gacktype : { | |
| 1203 | 224 | const M_Object o = *(M_Object *)(reg - SZ_INT); | |
| 1204 |
1/2✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
|
224 | if (o) *(Type *)reg = o->type_ref; |
| 1205 | } | ||
| 1206 | 224 | DISPATCH() | |
| 1207 | 1106 | gackend : { | |
| 1208 | 1106 | m_str str = *(m_str *)(reg - SZ_INT); | |
| 1209 |
2/2✓ Branch 0 taken 985 times.
✓ Branch 1 taken 121 times.
|
1106 | if (!VAL) { |
| 1210 | 985 | gw_out("%s\n", str); | |
| 1211 | 985 | fflush(stdout); | |
| 1212 | } else | ||
| 1213 | 121 | *(M_Object *)(reg - SZ_INT) = new_string(vm->gwion, str); | |
| 1214 |
1/2✓ Branch 0 taken 1106 times.
✗ Branch 1 not taken.
|
1106 | if (str) mp_free2(vm->gwion->mp, strlen(str), str); |
| 1215 | 1106 | DISPATCH(); | |
| 1216 | } | ||
| 1217 | 1606 | gack: | |
| 1218 | 1606 | VM_OUT | |
| 1219 | 1606 | gack(shred, VAL); | |
| 1220 | 1606 | goto vmin; | |
| 1221 | 3 | try_ini: | |
| 1222 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (!shred->info->frame.ptr) // ??? |
| 1223 | 3 | vector_init(&shred->info->frame); | |
| 1224 | 3 | vector_add(&shred->info->frame, PC); | |
| 1225 | 3 | vector_add(&shred->info->frame, (m_uint)reg); | |
| 1226 | 3 | DISPATCH(); | |
| 1227 | 3 | try_end: | |
| 1228 | 3 | vector_pop(&shred->info->frame); | |
| 1229 | 3 | vector_pop(&shred->info->frame); | |
| 1230 | 3 | handleeffect: | |
| 1231 | // this should check the *xid* of the exception | ||
| 1232 | 3 | DISPATCH(); | |
| 1233 | 1 | performeffect: | |
| 1234 | { | ||
| 1235 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | const m_str effect = (m_str)VAL ?: *(m_str*)(mem + VAL2); |
| 1236 | 1 | handle(shred, effect); | |
| 1237 | } | ||
| 1238 | 1 | break; | |
| 1239 | 2 | noop: | |
| 1240 | 2 | DISPATCH(); | |
| 1241 | 372 | other: | |
| 1242 | 372 | VM_OUT((f_instr)VAL2)(shred, (Instr)VAL); | |
| 1243 | 1978 | vmin: | |
| 1244 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1958 times.
|
1978 | if (!s->curr) break; |
| 1245 | 1958 | bytecode = (code = shred->code)->bytecode; | |
| 1246 | 1958 | reg = shred->reg; | |
| 1247 | 1958 | mem = shred->mem; | |
| 1248 | 1958 | PC_DISPATCH(shred->pc) | |
| 1249 | ✗ | debugline: | |
| 1250 | ✗ | if (!shred->info->line.ptr) { // from a problem with spork it seems | |
| 1251 | ✗ | vector_init(&shred->info->line); | |
| 1252 | ✗ | vector_add(&shred->info->line, VAL); | |
| 1253 | ✗ | } else if (!VAL) { | |
| 1254 | ✗ | vector_add(&shred->info->line, VAL); | |
| 1255 | } else { | ||
| 1256 | ✗ | const m_uint sz = vector_size(&shred->info->line); | |
| 1257 | ✗ | vector_set(&shred->info->line, sz - 1, VAL); | |
| 1258 | } | ||
| 1259 | ✗ | DISPATCH(); | |
| 1260 | ✗ | debugvalue: | |
| 1261 | ✗ | DISPATCH(); | |
| 1262 | ✗ | debugpush: | |
| 1263 | ✗ | if (!shred->info->line.ptr) vector_init(&shred->info->line); | |
| 1264 | ✗ | vector_add(&shred->info->line, 0); | |
| 1265 | ✗ | DISPATCH(); | |
| 1266 | ✗ | debugpop: | |
| 1267 | ✗ | vector_pop(&shred->info->line); | |
| 1268 | ✗ | DISPATCH(); | |
| 1269 | 370 | eoc: | |
| 1270 | 370 | VM_OUT | |
| 1271 | 370 | vm_shred_exit(shred); | |
| 1272 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
|
380 | } while (s->curr); |
| 1273 | } | ||
| 1274 | PRAGMA_POP() | ||
| 1275 | } else { | ||
| 1276 | |||
| 1277 | static void *_dispatch[] = { | ||
| 1278 | &&_regsetimm, &&_regpushimm, &&_regpushfloat, &&_regpushother, &&_regpushaddr, | ||
| 1279 | &&_regpushmem, &&_regpushmemfloat, &&_regpushmemother, &&_regpushmemaddr, | ||
| 1280 | &&_regpushmemderef, &&_pushnow, &&_baseint, &&_basefloat, &&_baseother, | ||
| 1281 | &&_baseaddr, &&_regtoreg, &&_regtoregother2, &&_regtoregaddr, &&_regtoregderef, | ||
| 1282 | &&_structmember, &&_structmemberfloat, &&_structmemberother, | ||
| 1283 | &&_structmemberaddr, &&_memsetimm, &&_memaddimm, &&_repeatidx, &&_repeat, | ||
| 1284 | &&_regpushme, &&_regpushmaybe, &&_funcreturn, &&__goto, &&_allocint, | ||
| 1285 | &&_allocfloat, &&_allocother, | ||
| 1286 | &&_intplus, &&_intminus, &&_intmul, &&_intdiv, &&_intmod, | ||
| 1287 | &&_intplusimm, &&_intminusimm, &&_intmulimm, &&_intdivimm, &&_intmodimm, | ||
| 1288 | // int relationnal | ||
| 1289 | &&_inteq, &&_intne, &&_intand, &&_intor, | ||
| 1290 | &&_intgt, &&_intge, &&_intlt, &&_intle, | ||
| 1291 | &&_intgtimm, &&_intgeimm, &&_intltimm, &&_intleimm, | ||
| 1292 | &&_intsl, &&_intsr, &&_intsand, &&_intsor, &&_intxor, &&_intnegate, &&_intnot, | ||
| 1293 | &&_intcmp, &&_intrassign, &&_intradd, &&_intrsub, &&_intrmul, &&_intrdiv, | ||
| 1294 | &&_intrmod, &&_intrsl, &&_intrsr, &&_intrsand, &&_intrsor, &&_intrxor, &&_preinc, | ||
| 1295 | &&_predec, &&_postinc, &&_postdec, | ||
| 1296 | &&_floatadd, &&_floatsub, &&_floatmul, &&_floatdiv, | ||
| 1297 | &&_floataddimm, &&_floatsubimm, &&_floatmulimm, &&_floatdivimm, | ||
| 1298 | // logical | ||
| 1299 | &&_floatand, &&_floator, &&_floateq, &&_floatne, | ||
| 1300 | &&_floatgt, &&_floatge, &&_floatlt, &&_floatle, | ||
| 1301 | &&_floatgtimm, &&_floatgeimm, &&_floatltimm, &&_floatleimm, | ||
| 1302 | &&_floatneg, &&_floatnot, &&_floatrassign, &&_floatradd, | ||
| 1303 | &&_floatrsub, &&_floatrmul, &&_floatrdiv, &&_ifadd, &&_ifsub, &&_ifmul, &&_ifdiv, | ||
| 1304 | &&_ifand, &&_ifor, &&_ifeq, &&_ifne, &&_ifgt, &&_ifge, &&_iflt, &&_ifle, | ||
| 1305 | &&_ifrassign, &&_ifradd, &&_ifrsub, &&_ifrmul, &&_ifrdiv, &&_fiadd, &&_fisub, | ||
| 1306 | &&_fimul, &&_fidiv, &&_fiand, &&_fior, &&_fieq, &&_fine, &&_figt, &&_fige, &&_filt, | ||
| 1307 | &&_file, &&_firassign, &&_firadd, &&_firsub, &&_firmul, &&_firdiv, &&_itof, | ||
| 1308 | &&_ftoi, &&_timeadv, &&_recurs, &&_setcode, &&_regmove, | ||
| 1309 | &&_regtomem, &&_regtomemother, | ||
| 1310 | &&_overflow, | ||
| 1311 | &&_funcusrend, &&_funcusrend2, &&_funcmemberend, | ||
| 1312 | &&_sporkini, &&_forkini, &&_sporkfunc, &&_sporkexp, &&_sporkcode, &&_forkend, | ||
| 1313 | &&_sporkend, &&_brancheqint, &&_branchneint, &&_brancheqfloat, | ||
| 1314 | &&_branchnefloat, &&_unroll, &&_arrayappend, &&_autounrollinit, &&_autoloop, | ||
| 1315 | &&_arraytop, &&_arrayaccess, &&_arrayget, &&_arrayaddr, &&_newobj, &&_addref, | ||
| 1316 | &&_addrefaddr, &&_structaddref, &&_structaddrefaddr, &&_objassign, &&_assign, | ||
| 1317 | &&_remref, &&_remref2, &&_structreleaseregaddr, &&_structreleasemem, | ||
| 1318 | &&_except, | ||
| 1319 | &&_dotmembermem, &&_dotmembermem2, /*&&_dotmembermem3, */&&_dotmembermem4, | ||
| 1320 | &&_dotmember, &&_dotfloat, &&_dotother, &&_dotaddr, | ||
| 1321 | &&_unioncheck, &&_unionint, &&_unionfloat, | ||
| 1322 | &&_unionother, &&_unionaddr, &&_staticint, &&_staticfloat, &&_staticother, | ||
| 1323 | &&_dotfunc, &&_gacktype, &&_gackend, &&_gack, &&_try_ini, | ||
| 1324 | &&_try_end, &&_handleeffect, &&_performeffect, &&_noop, &&_debugline, | ||
| 1325 | &&_debugvalue, &&_debugpush, &&_debugpop, &&_eoc, &&_vmin, &&_other}; | ||
| 1326 | |||
| 1327 | #define PREPARE(a) \ | ||
| 1328 | _##a: \ | ||
| 1329 | *(void**)prepare_code = &&a;\ | ||
| 1330 | prepare_code += BYTECODE_SZ;\ | ||
| 1331 | goto *_dispatch[*(m_bit*)prepare_code]; | ||
| 1332 | |||
| 1333 | 3035 | goto *_dispatch[*(m_bit*)prepare_code]; | |
| 1334 | 2279 | PREPARE(regsetimm); | |
| 1335 | 1912 | PREPARE(regpushimm); | |
| 1336 | 129 | PREPARE(regpushfloat); | |
| 1337 | ✗ | PREPARE(regpushother); | |
| 1338 | ✗ | PREPARE(regpushaddr); | |
| 1339 | 372 | PREPARE(regpushmem); | |
| 1340 | 94 | PREPARE(regpushmemfloat); | |
| 1341 | 1 | PREPARE(regpushmemother); | |
| 1342 | 242 | PREPARE(regpushmemaddr); | |
| 1343 | 17 | PREPARE(regpushmemderef); | |
| 1344 | 75 | PREPARE(pushnow); | |
| 1345 | 285 | PREPARE(baseint); | |
| 1346 | 12 | PREPARE(basefloat); | |
| 1347 | ✗ | PREPARE(baseother); | |
| 1348 | 51 | PREPARE(baseaddr); | |
| 1349 | 143 | PREPARE(regtoreg); | |
| 1350 | 1 | PREPARE(regtoregother2); | |
| 1351 | ✗ | PREPARE(regtoregaddr); | |
| 1352 | 14 | PREPARE(regtoregderef); | |
| 1353 | 22 | PREPARE(structmember); | |
| 1354 | 17 | PREPARE(structmemberfloat); | |
| 1355 | ✗ | PREPARE(structmemberother); | |
| 1356 | 33 | PREPARE(structmemberaddr) | |
| 1357 | 34 | PREPARE(memsetimm); | |
| 1358 | ✗ | PREPARE(memaddimm); | |
| 1359 | 1 | PREPARE(repeatidx); | |
| 1360 | 7 | PREPARE(repeat); | |
| 1361 | 53 | PREPARE(regpushme); | |
| 1362 | 19 | PREPARE(regpushmaybe); | |
| 1363 | // PREPARE(funcreturn); | ||
| 1364 | 345 | _funcreturn: | |
| 1365 | 345 | *(void**)prepare_code = &&funcreturn; | |
| 1366 | 345 | return; | |
| 1367 | |||
| 1368 | 109 | PREPARE(_goto); | |
| 1369 | 126 | PREPARE(allocint); | |
| 1370 | 75 | PREPARE(allocfloat); | |
| 1371 | ✗ | PREPARE(allocother) | |
| 1372 | 17 | PREPARE(intplus); | |
| 1373 | 1 | PREPARE(intminus); | |
| 1374 | 1 | PREPARE(intmul); | |
| 1375 | 3 | PREPARE(intdiv); | |
| 1376 | 1 | PREPARE(intmod); | |
| 1377 | 2 | PREPARE(intplusimm); | |
| 1378 | 12 | PREPARE(intminusimm); | |
| 1379 | ✗ | PREPARE(intmulimm); | |
| 1380 | ✗ | PREPARE(intdivimm); | |
| 1381 | ✗ | PREPARE(intmodimm); | |
| 1382 | |||
| 1383 | 14 | PREPARE(inteq); | |
| 1384 | 2 | PREPARE(intne); | |
| 1385 | 1 | PREPARE(intand); | |
| 1386 | 1 | PREPARE(intor); | |
| 1387 | 1 | PREPARE(intgt); | |
| 1388 | 1 | PREPARE(intge); | |
| 1389 | 2 | PREPARE(intlt); | |
| 1390 | 1 | PREPARE(intle); | |
| 1391 | 4 | PREPARE(intgtimm); | |
| 1392 | ✗ | PREPARE(intgeimm); | |
| 1393 | 10 | PREPARE(intltimm); | |
| 1394 | ✗ | PREPARE(intleimm); | |
| 1395 | 1 | PREPARE(intsl); | |
| 1396 | 1 | PREPARE(intsr); | |
| 1397 | 1 | PREPARE(intsand); | |
| 1398 | 1 | PREPARE(intsor); | |
| 1399 | 1 | PREPARE(intxor); | |
| 1400 | |||
| 1401 | 1 | PREPARE(intnegate); | |
| 1402 | 6 | PREPARE(intnot); | |
| 1403 | ✗ | PREPARE(intcmp); | |
| 1404 | |||
| 1405 | 78 | PREPARE(intrassign); | |
| 1406 | |||
| 1407 | 1 | PREPARE(intradd); | |
| 1408 | 1 | PREPARE(intrsub); | |
| 1409 | 1 | PREPARE(intrmul); | |
| 1410 | 1 | PREPARE(intrdiv); | |
| 1411 | 1 | PREPARE(intrmod); | |
| 1412 | 1 | PREPARE(intrsl); | |
| 1413 | 1 | PREPARE(intrsr); | |
| 1414 | 1 | PREPARE(intrsand); | |
| 1415 | 1 | PREPARE(intrsor); | |
| 1416 | 1 | PREPARE(intrxor) | |
| 1417 | |||
| 1418 | 4 | PREPARE(preinc); | |
| 1419 | 5 | PREPARE(predec); | |
| 1420 | 21 | PREPARE(postinc); | |
| 1421 | 5 | PREPARE(postdec); | |
| 1422 | |||
| 1423 | 5 | PREPARE(floatadd); | |
| 1424 | 1 | PREPARE(floatsub); | |
| 1425 | 8 | PREPARE(floatmul); | |
| 1426 | 1 | PREPARE(floatdiv); | |
| 1427 | ✗ | PREPARE(floataddimm); | |
| 1428 | 1 | PREPARE(floatsubimm); | |
| 1429 | ✗ | PREPARE(floatmulimm); | |
| 1430 | ✗ | PREPARE(floatdivimm); | |
| 1431 | |||
| 1432 | 1 | PREPARE(floatand); | |
| 1433 | 1 | PREPARE(floator); | |
| 1434 | 2 | PREPARE(floateq); | |
| 1435 | 1 | PREPARE(floatne); | |
| 1436 | 1 | PREPARE(floatgt); | |
| 1437 | 3 | PREPARE(floatge); | |
| 1438 | 3 | PREPARE(floatlt); | |
| 1439 | 1 | PREPARE(floatle); | |
| 1440 | 1 | PREPARE(floatgtimm); | |
| 1441 | ✗ | PREPARE(floatgeimm); | |
| 1442 | ✗ | PREPARE(floatltimm); | |
| 1443 | ✗ | PREPARE(floatleimm); | |
| 1444 | |||
| 1445 | 1 | PREPARE(floatneg); | |
| 1446 | 3 | PREPARE(floatnot); | |
| 1447 | |||
| 1448 | 12 | PREPARE(floatrassign); | |
| 1449 | |||
| 1450 | 1 | PREPARE(floatradd); | |
| 1451 | 2 | PREPARE(floatrsub); | |
| 1452 | 1 | PREPARE(floatrmul); | |
| 1453 | 1 | PREPARE(floatrdiv); | |
| 1454 | |||
| 1455 | 1 | PREPARE(ifadd); | |
| 1456 | 2 | PREPARE(ifsub); | |
| 1457 | 20 | PREPARE(ifmul); | |
| 1458 | 1 | PREPARE(ifdiv); | |
| 1459 | |||
| 1460 | 1 | PREPARE(ifand); | |
| 1461 | 1 | PREPARE(ifor); | |
| 1462 | 1 | PREPARE(ifeq); | |
| 1463 | 1 | PREPARE(ifne); | |
| 1464 | 1 | PREPARE(ifgt); | |
| 1465 | 1 | PREPARE(ifge); | |
| 1466 | 1 | PREPARE(iflt); | |
| 1467 | 1 | PREPARE(ifle); | |
| 1468 | |||
| 1469 | 12 | PREPARE(ifrassign); | |
| 1470 | 3 | PREPARE(ifradd); | |
| 1471 | 4 | PREPARE(ifrsub); | |
| 1472 | 1 | PREPARE(ifrmul); | |
| 1473 | 1 | PREPARE(ifrdiv); | |
| 1474 | |||
| 1475 | 1 | PREPARE(fiadd); | |
| 1476 | 1 | PREPARE(fisub); | |
| 1477 | 1 | PREPARE(fimul); | |
| 1478 | 1 | PREPARE(fidiv); | |
| 1479 | |||
| 1480 | 1 | PREPARE(fiand); | |
| 1481 | 1 | PREPARE(fior); | |
| 1482 | 2 | PREPARE(fieq); | |
| 1483 | 1 | PREPARE(fine); | |
| 1484 | 4 | PREPARE(figt); | |
| 1485 | 1 | PREPARE(fige); | |
| 1486 | 1 | PREPARE(filt); | |
| 1487 | 1 | PREPARE(file); | |
| 1488 | |||
| 1489 | 1 | PREPARE(firassign); | |
| 1490 | |||
| 1491 | 1 | PREPARE(firadd); | |
| 1492 | 2 | PREPARE(firsub); | |
| 1493 | 1 | PREPARE(firmul); | |
| 1494 | 1 | PREPARE(firdiv); | |
| 1495 | |||
| 1496 | 15 | PREPARE(itof); | |
| 1497 | 1 | PREPARE(ftoi); | |
| 1498 | |||
| 1499 | 63 | PREPARE(timeadv); | |
| 1500 | |||
| 1501 | 12 | PREPARE(recurs); | |
| 1502 | |||
| 1503 | 4994 | PREPARE(setcode); | |
| 1504 | 1730 | PREPARE(regmove); | |
| 1505 | 552 | PREPARE(regtomem); | |
| 1506 | 98 | PREPARE(regtomemother); | |
| 1507 | 5006 | PREPARE(overflow); | |
| 1508 | ✗ | PREPARE(funcusrend); | |
| 1509 | ✗ | PREPARE(funcusrend2); | |
| 1510 | ✗ | PREPARE(funcmemberend); | |
| 1511 | 45 | PREPARE(sporkini); | |
| 1512 | 5 | PREPARE(forkini); | |
| 1513 | 24 | PREPARE(sporkfunc); | |
| 1514 | 26 | PREPARE(sporkexp); | |
| 1515 | 6 | PREPARE(sporkcode); | |
| 1516 | 5 | PREPARE(forkend); | |
| 1517 | 45 | PREPARE(sporkend); | |
| 1518 | 77 | PREPARE(brancheqint); | |
| 1519 | 23 | PREPARE(branchneint); | |
| 1520 | 4 | PREPARE(brancheqfloat); | |
| 1521 | 2 | PREPARE(branchnefloat); | |
| 1522 | 1 | PREPARE(unroll); | |
| 1523 | ✗ | PREPARE(arrayappend); | |
| 1524 | 1 | PREPARE(autounrollinit); | |
| 1525 | 7 | PREPARE(autoloop); | |
| 1526 | 4 | PREPARE(arraytop); | |
| 1527 | 6 | PREPARE(arrayaccess); | |
| 1528 | 6 | PREPARE(arrayget); | |
| 1529 | ✗ | PREPARE(arrayaddr); | |
| 1530 | 167 | PREPARE(newobj); | |
| 1531 | 358 | PREPARE(addref); | |
| 1532 | ✗ | PREPARE(addrefaddr); | |
| 1533 | ✗ | PREPARE(structaddref); | |
| 1534 | ✗ | PREPARE(structaddrefaddr); | |
| 1535 | 7 | PREPARE(objassign); | |
| 1536 | 178 | PREPARE(assign); | |
| 1537 | 125 | PREPARE(remref); | |
| 1538 | 24 | PREPARE(remref2); | |
| 1539 | ✗ | PREPARE(structreleaseregaddr); | |
| 1540 | 30 | PREPARE(structreleasemem); | |
| 1541 | 6 | PREPARE(except); | |
| 1542 | 35 | PREPARE(dotmembermem); | |
| 1543 | 6 | PREPARE(dotmembermem2); | |
| 1544 | //PREPARE(dotmembermem3); | ||
| 1545 | 54 | PREPARE(dotmembermem4); | |
| 1546 | 32 | PREPARE(dotmember); | |
| 1547 | 3 | PREPARE(dotfloat); | |
| 1548 | ✗ | PREPARE(dotother); | |
| 1549 | 2 | PREPARE(dotaddr); | |
| 1550 | ✗ | PREPARE(unioncheck); | |
| 1551 | 4 | PREPARE(unionint); | |
| 1552 | 1 | PREPARE(unionfloat); | |
| 1553 | ✗ | PREPARE(unionother); | |
| 1554 | 3 | PREPARE(unionaddr); | |
| 1555 | 42 | PREPARE(staticint); | |
| 1556 | 6 | PREPARE(staticfloat); | |
| 1557 | ✗ | PREPARE(staticother); | |
| 1558 | 129 | PREPARE(dotfunc); | |
| 1559 | 132 | PREPARE(gacktype); | |
| 1560 | 650 | PREPARE(gackend); | |
| 1561 | 862 | PREPARE(gack); | |
| 1562 | 3 | PREPARE(try_ini); | |
| 1563 | 3 | PREPARE(try_end); | |
| 1564 | 3 | PREPARE(handleeffect); | |
| 1565 | 1 | PREPARE(performeffect); | |
| 1566 | ✗ | PREPARE(noop); | |
| 1567 | 9203 | _other: | |
| 1568 | { | ||
| 1569 | 9203 | *(void**)prepare_code = &&other; | |
| 1570 | 9203 | const f_instr exec = *(f_instr*)(prepare_code + SZ_INT *2); | |
| 1571 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9201 times.
|
9203 | if(exec == DTOR_EOC)return; |
| 1572 | 9201 | const Instr instr = *(Instr*)(prepare_code + SZ_INT); | |
| 1573 |
4/4✓ Branch 0 taken 9182 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 9177 times.
|
9201 | if(exec == fast_except || exec == FuncWait) |
| 1574 | 24 | instr->opcode = (m_uint)&&noop; | |
| 1575 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 9163 times.
|
9177 | else if(exec == SetFunc) |
| 1576 | 14 | instr->opcode = (m_uint)&®pushimm; | |
| 1577 | 9201 | prepare_code += BYTECODE_SZ; | |
| 1578 | 9201 | goto *_dispatch[*(m_bit*)prepare_code]; | |
| 1579 | } | ||
| 1580 | ✗ | PREPARE(vmin); | |
| 1581 | ✗ | PREPARE(debugline); | |
| 1582 | ✗ | PREPARE(debugvalue); | |
| 1583 | ✗ | PREPARE(debugpush); | |
| 1584 | ✗ | PREPARE(debugpop); | |
| 1585 | 4865 | _eoc: | |
| 1586 | 4865 | *(void**)prepare_code = &&eoc; | |
| 1587 | 4865 | return; | |
| 1588 | } | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | // remove me | ||
| 1592 | 3287132 | ANN void next_bbq_pos(const VM *vm) { | |
| 1593 | 3287132 | Driver *const di = vm->bbq; | |
| 1594 | 3287132 | MUTEX_LOCK(vm->shreduler->mutex); | |
| 1595 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3287132 times.
|
3287132 | if(++di->pos == 16777216-1) { |
| 1596 | ✗ | const Vector v = &vm->shreduler->active_shreds; | |
| 1597 | ✗ | for(m_uint i = 0; i < vector_size(v); i++) { | |
| 1598 | ✗ | const VM_Shred shred = (VM_Shred)vector_at(v, i); | |
| 1599 | ✗ | shred->tick->wake_time -= 16777216.0; | |
| 1600 | } | ||
| 1601 | ✗ | di->pos = 0; | |
| 1602 | } | ||
| 1603 | 3287132 | MUTEX_UNLOCK(vm->shreduler->mutex); | |
| 1604 | 3287132 | } | |
| 1605 | |||
| 1606 | 6058889 | ANN void vm_run_audio(const VM *vm) { | |
| 1607 | 6058889 | vm_run(vm); | |
| 1608 | 6078098 | compute_audio(vm); | |
| 1609 | 5924585 | } | |
| 1610 | |||
| 1611 | 712 | VM *new_vm(MemPool p, const bool audio) { | |
| 1612 | 712 | VM *vm = (VM *)mp_calloc(p, VM); | |
| 1613 | 712 | vector_init(&vm->ugen); | |
| 1614 | 712 | vm->shreduler = new_shreduler(p); | |
| 1615 | 712 | vm->bbq = vm->shreduler->bbq = new_driver(p); | |
| 1616 |
1/2✓ Branch 0 taken 712 times.
✗ Branch 1 not taken.
|
712 | vm->bbq->run = audio |
| 1617 | ? vm_run_audio | ||
| 1618 | : vm_run; | ||
| 1619 | #ifndef __AFL_COMPILER | ||
| 1620 | 712 | gw_seed(vm->rand, (uint64_t)time(NULL)); | |
| 1621 | #else | ||
| 1622 | gw_seed(vm->rand, 0); | ||
| 1623 | #endif | ||
| 1624 | 712 | return vm; | |
| 1625 | } | ||
| 1626 | |||
| 1627 | 707 | ANN void vm_clean(const VM* vm, const Gwion gwion) { | |
| 1628 | 707 | gwion_end_child(vm->cleaner_shred, gwion); | |
| 1629 |
1/2✓ Branch 0 taken 707 times.
✗ Branch 1 not taken.
|
707 | if (vm->bbq) free_driver(vm->bbq, gwion->vm); |
| 1630 | 707 | } | |
| 1631 | |||
| 1632 | 708 | ANN void free_vm(VM *vm) { | |
| 1633 | 708 | const MemPool mp = vm->gwion->mp; | |
| 1634 |
2/2✓ Branch 0 taken 638 times.
✓ Branch 1 taken 70 times.
|
708 | if (vm->cleaner_shred) free_vm_shred(vm->cleaner_shred); |
| 1635 | 708 | free_shreduler(mp, vm->shreduler); | |
| 1636 | 708 | vector_release(&vm->ugen); | |
| 1637 | 708 | mp_free(mp, VM, vm); | |
| 1638 | 708 | } | |
| 1639 |