Gwion coverage report


Directory: src/
File: src/emit/emit.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 1757 1965 89.4%
Functions: 216 231 93.5%
Branches: 814 1196 68.1%

Line Branch Exec Source
1 #include "gwion_util.h"
2 #include "gwion_ast.h"
3 #include "gwion_env.h"
4 #include "vm.h"
5 #include "gwion.h"
6 #include "instr.h"
7 #include "emit.h"
8 #include "object.h"
9 #include "array.h"
10 #include "traverse.h"
11 #include "template.h"
12 #include "escape.h"
13 #include "parse.h"
14 #include "memoize.h"
15 #include "operator.h"
16 #include "import.h"
17 #include "match.h"
18 #include "specialid.h"
19 #include "looper.h"
20 #include "shreduler_private.h"
21
22 #undef insert_symbol
23 #define insert_symbol(a) insert_symbol(emit->gwion->st, (a))
24
25 #undef ERR_B
26 #define ERR_B(a, b, ...) \
27 { \
28 env_err(emit->env, (a), (b), ##__VA_ARGS__); \
29 return GW_ERROR; \
30 }
31 #undef ERR_O
32 #define ERR_O(a, b, ...) \
33 { \
34 env_err(emit->env, (a), (b), ##__VA_ARGS__); \
35 return NULL; \
36 }
37
38 typedef struct Local_ {
39 Type type;
40 m_uint offset;
41 Instr instr;
42 bool skip;
43 bool is_compound;
44 } Local;
45
46 56 static inline void emit_pop(const Emitter emit, const m_uint scope) {
47 56 env_pop(emit->env, scope);
48 56 }
49 51 static inline m_uint emit_push(const Emitter emit, const Type type,
50 const Nspc nspc) {
51 51 return env_push(emit->env, type, nspc);
52 }
53
54 5 static inline m_uint emit_push_global(const Emitter emit) {
55 5 return env_push_global(emit->env);
56 }
57
58 503 static inline void emit_debug(const Emitter emit, const Value v) {
59
1/2
✓ Branch 0 taken 503 times.
✗ Branch 1 not taken.
503 if (!emit->info->debug) return;
60 const Instr instr = emit_add_instr(emit, DebugValue);
61 instr->m_val = (m_uint)v;
62 }
63
64 752 ANEW static Frame *new_frame(MemPool p) {
65 752 Frame *frame = mp_calloc(p, Frame);
66 752 vector_init(&frame->stack);
67 752 vector_add(&frame->stack, (vtype)NULL);
68 752 vector_init(&frame->defer);
69 752 vector_add(&frame->defer, (vtype)NULL);
70 752 return frame;
71 }
72
73 ANN static void release_maybe_stack(const MemPool mp, MP_Vector * ms) {
74 for (vtype i = ms->len + 1; --i;) {
75 const MaybeVal *mv = mp_vector_at(ms, MaybeVal, i - 1);
76 struct M_Vector_ v = { .ptr = mv->ptr };
77 m_vector_release(&v);
78 }
79 free_mp_vector(mp, MaybeVal, ms);
80 }
81
82 751 ANN static void free_frame(MemPool p, Frame *a) {
83 LOOP_OPTIM
84
2/2
✓ Branch 1 taken 992 times.
✓ Branch 2 taken 751 times.
1743 for (vtype i = vector_size(&a->stack) + 1; --i;)
85
2/2
✓ Branch 1 taken 241 times.
✓ Branch 2 taken 751 times.
992 if (vector_at(&a->stack, i - 1))
86 241 mp_free(p, Local, (Local *)vector_at(&a->stack, i - 1));
87 751 vector_release(&a->stack);
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
751 if(a->maybe_stack)
89 release_maybe_stack(p, a->maybe_stack);
90 751 vector_release(&a->defer);
91
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 748 times.
751 if (a->handlers.ptr) map_release(&a->handlers);
92 751 mp_free(p, Frame, a);
93 751 }
94
95 1558 ANN static inline Local *new_local(MemPool p, const Type type) {
96 1558 Local *const local = mp_calloc(p, Local);
97 1558 local->type = type;
98 1558 return local;
99 }
100
101 1558 ANN static Local *frame_local(MemPool p, Frame *frame, const Type t) {
102 1558 Local *const l = new_local(p, t);
103 1558 l->offset = frame->curr_offset;
104 1558 frame->curr_offset += t->size;
105 1558 vector_add(&frame->stack, (vtype)l);
106 1558 return l;
107 }
108
109 1257 ANN static inline void frame_push(Frame *frame) {
110 1257 vector_add(&frame->stack, (vtype)NULL);
111 1257 vector_add(&frame->defer, (vtype)NULL);
112 1257 }
113
114 static const f_instr allocmember[] = {RegPushImm, RegPushImm2, RegPushImm3,
115 DotMemberMem4};
116 static const f_instr allocword[] = {AllocWord, AllocWord2, AllocWord3,
117 RegPushMem4};
118
119 ANN static m_bool emit_class_def(const Emitter, const Class_Def);
120 ANN /*static */ m_bool emit_cdef(const Emitter, const Type);
121
122 619 ANN /*static inline*/ m_bool ensure_emit(const Emitter emit, const Type t) {
123
6/6
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 570 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 13 times.
✓ Branch 7 taken 33 times.
✓ Branch 8 taken 3 times.
619 if (tflag(t, tflag_emit) || !(tflag(t, tflag_cdef) || tflag(t, tflag_udef)))
124 603 return GW_OK; // clean callers
125
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 13 times.
16 if(!tflag(t, tflag_tmpl))return GW_OK;
126 13 struct EnvSet es = {.env = emit->env,
127 .data = emit,
128 .func = (_exp_func)emit_cdef,
129 13 .scope = emit->env->scope->depth,
130 .flag = tflag_emit};
131 13 return envset_run(&es, t);
132 }
133
134 125 ANN void emit_object_release(const Emitter emit, const m_uint offset) {
135 125 const Instr instr = emit_add_instr(emit, ObjectRelease);
136 125 instr->m_val = offset;
137 125 }
138
139 ANN void emit_compound_release(const Emitter emit, const Type t, const m_uint offset) {
140 if(tflag(t, tflag_compound))
141 return emit_object_release(emit, offset);
142 if(tflag(t, tflag_release))
143 emit_struct_release(emit, t, offset);
144 }
145
146 30 ANN void emit_struct_release(const Emitter emit, const Type type,
147 const m_uint offset) {
148 30 const Instr instr = emit_add_instr(emit, StructReleaseMem);
149 30 instr->m_val = offset;
150 30 instr->m_val2 = (m_uint)type;
151 30 }
152
153 ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt);
154
155 2136 ANN static m_bool emit_defers(const Emitter emit) {
156 2136 const Vector v = &emit->code->frame->defer;
157
2/2
✓ Branch 1 taken 1316 times.
✓ Branch 2 taken 820 times.
2136 if (!vector_size(v)) return GW_OK;
158 m_uint i;
159
2/2
✓ Branch 1 taken 1960 times.
✓ Branch 2 taken 820 times.
2780 for(i = vector_size(v) + 1; --i;) {
160 1960 const Stmt s = (Stmt)vector_at(v, i - 1);
161
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1960 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1960 if(s) CHECK_BB(emit_stmt(emit, s));
162 }
163 820 VLEN(v) = i;
164 820 return GW_OK;
165 }
166
167 85 ANN static m_bool emit_defers2(const Emitter emit) {
168 85 const Vector v = &emit->code->frame->defer;
169
2/2
✓ Branch 1 taken 81 times.
✓ Branch 2 taken 4 times.
85 for (m_uint i = vector_size(v) + 1; --i;) {
170 81 const Stmt s = (Stmt)vector_at(v, i - 1);
171
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 if (!s) break;
172 CHECK_BB(emit_stmt(emit, s));
173 }
174 85 return GW_OK;
175 }
176
177 2573 ANN static m_int _frame_pop(const Emitter emit) {
178 2573 Frame *frame = emit->code->frame;
179
2/2
✓ Branch 1 taken 1257 times.
✓ Branch 2 taken 1316 times.
2573 DECL_OB(const Local *, l, = (Local *)vector_pop(&frame->stack));
180 1316 frame->curr_offset -= l->type->size;
181
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 1122 times.
1316 if (l->skip) return _frame_pop(emit);
182
2/2
✓ Branch 0 taken 905 times.
✓ Branch 1 taken 217 times.
1122 if (!l->is_compound) return _frame_pop(emit);
183 217 VMValue *vmval =
184 217 (VMValue *)m_vector_addr(&emit->code->live_values, --frame->value_count);
185 217 vmval->end = emit_code_size(emit);
186
2/2
✓ Branch 1 taken 187 times.
✓ Branch 2 taken 30 times.
217 if (!tflag(l->type, tflag_struct)) return (m_int)l->offset;
187 30 emit_struct_release(emit, l->type, l->offset);
188 30 return _frame_pop(emit);
189 }
190
191 ANN static void emit_maybe_release(const Emitter emit, MP_Vector *const ms) {
192 for(m_uint i = 0; i < ms->len; i++) {
193 const MaybeVal *mv = mp_vector_at(ms, MaybeVal, i);
194 struct M_Vector_ vals = { .ptr = mv->ptr };
195 for(m_uint j = 0; j < m_vector_size(&vals); j++) {
196 const VMValue val = *(VMValue*)(vals.ptr + ARRAY_OFFSET + j * sizeof(VMValue));
197 emit_compound_release(emit, val.t, val.offset);
198 }
199 }
200 }
201
202 1444 ANN static m_int frame_pop(const Emitter emit) {
203 1444 emit_defers(emit);
204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1444 times.
1444 if(emit->code->frame->maybe_stack)
205 emit_maybe_release(emit, emit->code->frame->maybe_stack);
206 1444 return _frame_pop(emit);
207 }
208
209 ANN /*static */ m_bool emit_exp(const Emitter emit, Exp exp);
210 ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt);
211 ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list);
212 ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot *member);
213
214 752 ANEW static Code *new_code(const Emitter emit, const m_str name) {
215 752 Code *code = mp_calloc(emit->gwion->mp, Code);
216 752 code->name = code_name_set(emit->gwion->mp, name, emit->env->name);
217 752 vector_init(&code->instr);
218 752 vector_init(&code->stack_break);
219 752 vector_init(&code->stack_cont);
220 752 vector_init(&code->stack_return);
221 752 m_vector_init(&code->live_values, sizeof(VMValue), 0);
222 752 code->frame = new_frame(emit->gwion->mp);
223 752 return code;
224 }
225
226 751 ANN static void free_code(MemPool p, Code *code) {
227 // we should use instr destructors
228
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 746 times.
751 if(code->instr.ptr) vector_release(&code->instr);
229 751 vector_release(&code->stack_break);
230 751 vector_release(&code->stack_cont);
231 751 vector_release(&code->stack_return);
232
2/2
✓ Branch 0 taken 583 times.
✓ Branch 1 taken 168 times.
751 if (code->live_values.ptr) m_vector_release(&code->live_values);
233 751 free_frame(p, code->frame);
234 751 free_mstr(p, code->name);
235 751 mp_free(p, Code, code);
236 751 }
237
238 1257 ANN void emit_pop_scope(const Emitter emit) {
239 m_int offset;
240 struct Vector_ v;
241 1257 vector_init(&v);
242
2/2
✓ Branch 1 taken 187 times.
✓ Branch 2 taken 1257 times.
1444 while ((offset = frame_pop(emit)) > -1)
243 187 vector_add(&v, offset);
244
2/2
✓ Branch 1 taken 1108 times.
✓ Branch 2 taken 149 times.
1257 if(!vector_size(&v))
245 1108 vector_release(&v);
246
2/2
✓ Branch 1 taken 125 times.
✓ Branch 2 taken 24 times.
149 else if(vector_size(&v) == 1) {
247 125 emit_object_release(emit, vector_front(&v));
248 125 vector_release(&v);
249 } else {
250 24 Instr instr = emit_add_instr(emit, ObjectRelease2);
251 24 instr->m_val = (m_uint)v.ptr;
252 }
253 1257 vector_pop(&emit->info->pure);
254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1257 times.
1257 if (emit->info->debug) emit_add_instr(emit, DebugPop);
255 1257 }
256
257 402 ANN static inline void emit_push_code(const Emitter emit, const m_str name) {
258 402 vector_add(&emit->stack, (vtype)emit->code);
259 402 emit->code = new_code(emit, name);
260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 402 times.
402 if (emit->info->debug) emit_add_instr(emit, DebugLine);
261 402 }
262
263 747 ANN static inline void emit_pop_code(const Emitter emit) {
264 747 emit->code = (Code *)vector_pop(&emit->stack);
265 747 }
266
267 1257 ANN void emit_push_scope(const Emitter emit) {
268 1257 frame_push(emit->code->frame);
269 1257 vector_add(&emit->info->pure, 0);
270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1257 times.
1257 if (emit->info->debug) emit_add_instr(emit, DebugPush);
271 1257 }
272
273 1415 ANN m_uint emit_code_offset(const Emitter emit) {
274 1415 return emit->code->frame->curr_offset;
275 }
276
277 1364 ANN static Local * add_local(const Emitter emit, const Type t, const bool is_compound) {
278 1364 Local *const l = frame_local(emit->gwion->mp, emit->code->frame, t);
279
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 1144 times.
1364 if (is_compound) {
280 220 l->is_compound = true;
281 440 VMValue vmval = {
282 .t = t,
283 220 .offset = l->offset,
284 220 .start = emit_code_size(emit)
285 };
286 220 m_vector_add(&emit->code->live_values, &vmval);
287 220 ++emit->code->frame->value_count;
288 }
289 1364 return l;
290 }
291
292 1312 ANN m_uint emit_local(const Emitter emit, const Type t) {
293 1312 const bool is_compound = tflag(t, tflag_compound);
294 1312 Local *const l = add_local(emit, t, is_compound);
295 1312 return l->offset;
296 }
297
298 52 ANN void* emit_localx(const Emitter emit, const Type t) {
299 52 Local *const l = add_local(emit, t, 1);
300 52 l->instr = emit_regtomem(emit, l->offset, -SZ_INT);
301 52 return l;
302 }
303
304 35 ANN m_uint emit_local_exp(const Emitter emit, const Exp e) {
305 35 Local *const l = emit_localx(emit, e->type);
306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if(e->ref) e->ref->data = l;
307 35 return l->offset;
308 }
309
310 194 ANN m_uint emit_localn(const Emitter emit, const Type t) {
311 194 Local *const l = frame_local(emit->gwion->mp, emit->code->frame, t);
312 194 l->skip = true;
313 194 return l->offset;
314 }
315
316 ANN void emit_ext_ctor(const Emitter emit, const Type t);
317
318 560 ANN static inline void maybe_ctor(const Emitter emit, const Type t) {
319
2/2
✓ Branch 1 taken 113 times.
✓ Branch 2 taken 447 times.
560 if (tflag(t, tflag_ctor))emit_ext_ctor(emit, t);
320 560 }
321
322 ANN2(1, 2)
323 static ArrayInfo *emit_array_extend_inner(const Emitter emit, const Type t,
324 const Exp e, const uint is_ref);
325 560 ANN static m_bool emit_pre_ctor(const Emitter emit, const Type type) {
326
2/2
✓ Branch 0 taken 388 times.
✓ Branch 1 taken 172 times.
560 if (type->info->parent) {
327
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 388 times.
388 CHECK_BB(emit_pre_ctor(emit, type->info->parent));
328
4/4
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 379 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 4 times.
388 if (tflag(type, tflag_typedef) && type->info->parent->array_depth)
329
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 CHECK_OB(emit_array_extend_inner(emit, type, type->info->cdef->base.ext->array->exp, false));
330 }
331 560 maybe_ctor(emit, type);
332 560 return GW_OK;
333 }
334
335 14 ANN static void struct_expand(const Emitter emit, const Type t) {
336 14 const Instr instr = emit_add_instr(emit, Reg2RegDeref);
337 14 instr->m_val = -SZ_INT;
338 14 instr->m_val2 = t->size;
339 14 }
340
341 4 ANN static m_bool emit_pre_constructor_array(const Emitter emit,
342 const Type type) {
343 4 const m_uint start_index = emit_code_size(emit);
344 4 const Instr top = emit_add_instr(emit, ArrayTop);
345 4 top->m_val2 = (m_uint)type;
346
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (tflag(type, tflag_struct)) {
347 const Instr instr = emit_add_instr(emit, ArrayStruct);
348 instr->m_val = type->size;
349 }
350
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_pre_ctor(emit, type));
351
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (!tflag(type, tflag_struct))
352 4 emit_add_instr(emit, ArrayBottom);
353 else
354 emit_regmove(emit, -SZ_INT);
355 4 emit_regmove(emit, -SZ_INT);
356 4 const Instr pc = emit_add_instr(emit, Goto);
357 4 pc->m_val = start_index;
358 4 top->m_val = emit_code_size(emit);
359 4 emit_regmove(emit, -SZ_INT*3);
360 4 emit_add_instr(emit, ArrayPost);
361 4 return GW_OK;
362 }
363
364 ANN2(1)
365 13 static m_bool extend_indices(const Emitter emit, Exp e, const m_uint depth) {
366
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
13 if (e) CHECK_BB(emit_exp(emit, e));
367 13 m_uint count = 0;
368
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 13 times.
30 while (e) {
369 17 ++count;
370 17 e = e->next;
371 }
372
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 for (m_uint i = count; i < depth; ++i) emit_pushimm(emit, 0);
373 13 return GW_OK;
374 }
375
376 13 ANEW ANN static ArrayInfo *new_arrayinfo(const Emitter emit, const Type t) {
377 13 const Type base = array_base(t);
378 13 ArrayInfo *info = mp_calloc(emit->gwion->mp, ArrayInfo);
379 13 vector_init(&info->type);
380 13 info->depth = get_depth(t);
381
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 13 times.
17 for (long i = 1; i < info->depth; ++i)
382 4 vector_add(&info->type, (vtype)array_type(emit->env, base, i));
383 13 vector_add(&info->type, (vtype)t);
384 13 info->base = base;
385 13 return info;
386 }
387
388 13 ANN static inline m_bool arrayinfo_ctor(const Emitter emit, ArrayInfo *info) {
389 13 const Type base = info->base;
390
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 9 times.
13 if (tflag(base, tflag_compound) &&
391
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 !GET_FLAG(base, abstract)) {
392
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_pre_constructor_array(emit, base));
393 4 info->is_obj = 1;
394 }
395 13 return GW_OK;
396 }
397
398 ANN2(1, 2)
399 13 static ArrayInfo *emit_array_extend_inner(const Emitter emit, const Type t,
400 const Exp e, const uint is_ref) {
401
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 CHECK_BO(extend_indices(emit, e, get_depth(t)));
402 13 ArrayInfo * info = new_arrayinfo(emit, t);
403 13 const Instr alloc = emit_add_instr(emit, ArrayAlloc);
404 13 alloc->m_val = (m_uint)info;
405
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
13 if (!is_ref) CHECK_BO(arrayinfo_ctor(emit, info));
406 13 return info;
407 }
408
409 ANN static void call_finish(const Emitter emit, const Func f,const bool);
410 138 ANN void emit_ext_ctor(const Emitter emit, const Type t) {
411 138 const Instr cpy = emit_add_instr(emit, Reg2Reg);
412 138 cpy->m_val2 = -SZ_INT;
413 138 const Func f = (Func)vector_front(&t->nspc->vtable);
414 138 emit_regmove(emit, SZ_INT);
415 138 emit_pushfunc(emit, f);
416 138 call_finish(emit, f, false);
417 138 }
418
419 182 ANN static inline void emit_notpure(const Emitter emit) {
420 182 ++VPTR(&emit->info->pure, VLEN(&emit->info->pure) - 1);
421 182 }
422
423 ANN2(1, 2)
424 176 m_bool emit_instantiate_object(const Emitter emit, const Type type,
425 const Array_Sub array, const m_bool is_ref) {
426 176 emit_notpure(emit);
427
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 168 times.
176 if (type->array_depth) {
428
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 DECL_OB(ArrayInfo *, info,
429 = emit_array_extend_inner(emit, type, array ? array->exp : NULL,
430 is_ref));
431 8 return GW_OK;
432
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 } else if (!is_ref) {
433
5/6
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 160 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
172 if(!tflag(type, tflag_typedef) || isa(type, emit->gwion->type[et_closure]) > 0 ||
434 4 tflag(type, tflag_union)) {
435 164 const Instr instr = emit_add_instr(emit, ObjectInstantiate);
436 164 instr->m_val2 = (m_uint)type;
437 } // maybe we should instantiate the first actual type
438
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 168 times.
168 CHECK_BB(emit_pre_ctor(emit, type));
439 }
440 168 return GW_OK;
441 }
442
443 ANN2(1, 2)
444 159 m_bool emit_instantiate_decl(const Emitter emit, const Type type,
445 const Type_Decl *td, const m_bool is_ref) {
446 159 return emit_instantiate_object(emit, type, td->array, is_ref);
447 }
448
449 130 ANN static m_bool emit_symbol_builtin(const Emitter emit, const Symbol *data) {
450 130 const Value v = prim_self(data)->value;
451 130 const bool emit_addr = exp_getvar(prim_exp(data));
452
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 124 times.
130 if (vflag(v, vflag_direct)) {
453 6 const m_uint size = v->type->size;
454 6 emit_dotstatic(emit, (m_uint)&v->d.ptr, size, emit_addr);
455 // prevent invalid access to global variables
456
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if(!emit_addr &&
457
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 isa(v->type, emit->gwion->type[et_object]) > 0)
458 4 emit_fast_except(emit, v->from, prim_pos(data));
459 } else {
460 124 const m_uint size = v->type->size;
461 124 const Instr instr = emit_regpushimm(emit, v->d.num, size, emit_addr);
462
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 49 times.
124 if (v->type->size == SZ_FLOAT)
463 75 instr->f = v->d.fnum;
464 }
465 130 return GW_OK;
466 }
467
468 1003 ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) {
469 1003 const Value v = prim_self(data)->value;
470
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 997 times.
1003 if (is_class(emit->gwion, v->type)) {
471 6 emit_pushimm(emit, (m_uint)actual_type(emit->gwion, v->type));
472 6 return GW_OK;
473 }
474
4/4
✓ Branch 1 taken 873 times.
✓ Branch 2 taken 124 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 867 times.
997 if (vflag(v, vflag_builtin) || vflag(v, vflag_direct))
475 130 return emit_symbol_builtin(emit, data);
476 867 const Type t = prim_exp(data)->type;
477
2/2
✓ Branch 1 taken 125 times.
✓ Branch 2 taken 742 times.
867 if(is_func(emit->gwion, v->type)) {
478 125 const Func f = t->info->func;
479
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 31 times.
125 if(f->code)
480 94 emit_pushimm(emit, (m_uint)f->code);
481
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 25 times.
31 else if(!f->def->base->tmpl) {
482 6 const Instr instr = emit_add_instr(emit, SetFunc);
483 6 instr->m_val = (m_uint)f;
484 25 } else emit_pushimm(emit, (m_uint)f);
485 125 return GW_OK;
486 }
487
3/4
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 729 times.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
742 if (tflag(v->type, tflag_ref) && !safe_tflag(prim_exp(data)->cast_to, tflag_ref)) {
488
2/2
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 8 times.
13 if (exp_getvar(exp_self(prim_self(data)))) {
489 5 const Instr instr = emit_add_instr(emit, RegPushMem);
490 5 instr->m_val = v->from->offset;
491 5 instr->m_val2 = SZ_INT;
492 } else {
493 8 const Instr instr = emit_add_instr(emit, RegPushMemDeref);
494 8 instr->m_val = v->from->offset;
495 8 const Type t = (Type)vector_front(&v->type->info->tuple->contains);
496 8 instr->m_val2 = t->size;
497 }
498 13 return GW_OK;
499 }
500 729 const m_uint size = v->type->size;
501
2/2
✓ Branch 1 taken 379 times.
✓ Branch 2 taken 350 times.
729 if(!vflag(v, vflag_fglobal))
502 379 emit_regpushmem(emit, v->from->offset, size, exp_getvar(prim_exp(data)));
503 else
504 350 emit_regpushbase(emit, v->from->offset, size, exp_getvar(prim_exp(data)));
505
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 724 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
729 if (GET_FLAG(v, late) && !exp_getvar(prim_exp(data)) &&
506
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 isa(v->type, emit->gwion->type[et_object]) > 0)
507 5 emit_fast_except(emit, v->from, prim_pos(data));
508 729 return GW_OK;
509 }
510
511 1003 ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary *prim) {
512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1003 times.
1003 if (!prim->value) // assume it's an operator
513 ERR_B(exp_self(prim)->pos, "missing value for operator");
514 1003 return _emit_symbol(emit, &prim->d.var);
515 }
516
517 746 ANN static VM_Code finalyze(const Emitter emit, const f_instr exec) {
518 746 emit_add_instr(emit, exec);
519 746 const VM_Code code = emit->info->emit_code(emit);
520 746 free_code(emit->gwion->mp, emit->code);
521 746 emit_pop_code(emit);
522 746 return code;
523 }
524
525 1 ANN static inline m_uint exp_size(const Exp e) {
526
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (exp_getvar(e)) return SZ_INT;
527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 const Type type = e->cast_to ?: e->type;
528 1 return type->size;
529 }
530
531 334 ANN void emit_object_addref(const Emitter emit, const m_int size,
532 const bool emit_var) {
533
1/2
✓ Branch 0 taken 334 times.
✗ Branch 1 not taken.
334 const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr;
534 334 const Instr instr = emit_add_instr(emit, exec);
535 334 instr->m_val = size;
536 334 }
537
538 3 ANN void emit_struct_addref(const Emitter emit, const Type t, const m_int size,
539 const bool emit_var) {
540
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if(!tflag(t, tflag_release)) return;
541 const Instr instr =
542 emit_add_instr(emit, !emit_var ? StructRegAddRef : StructRegAddRefAddr);
543 instr->m_val2 = (m_uint)t;
544 instr->m_val = !emit_var ? size : (m_int)-SZ_INT;
545 }
546
547 ANN2(1)
548 static void emit_exp_addref1(const Emitter emit, const Exp exp, m_int size) {
549 const Type t = exp->cast_to ?: exp->type;
550 if (tflag(t, tflag_compound))
551 emit_compound_addref(emit, exp->type, size, exp_getvar(exp));
552 }
553
554 /*ANN2(1)
555 static void emit_exp_addref(const Emitter emit, Exp exp,
556 m_int size) {
557 do {
558 emit_exp_addref1(emit, exp, size);
559 size += exp_size(exp);
560 } while ((exp = exp->next));
561 }*/
562
563 16 ANN static inline m_bool emit_exp1(const Emitter emit, const Exp e) {
564 16 const Exp next = e->next;
565 16 e->next = NULL;
566 16 const m_bool ret = emit_exp(emit, e);
567 16 e->next = next;
568 16 return ret;
569 }
570
571 ANN static m_bool emit_prim_array_exp(const Emitter emit, const Type t, Exp e) {
572 do {
573 CHECK_BB(emit_exp1(emit, e));
574 emit_exp_addref1(emit, e, -t->size);
575 emit_regmove(emit, - t->size + t->actual_size);
576 } while((e = e->next));
577 return GW_OK;
578 }
579
580 6 ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) {
581 6 Exp e = (*data)->exp;
582 6 const Type type = (*data)->type;
583 6 const Type base = array_base_simple(type);
584
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if(!base->actual_size) CHECK_BB(emit_exp(emit, e));
585 else CHECK_BB(emit_prim_array_exp(emit, base, e));
586 6 m_uint count = 0;
587 12 do ++count;
588
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 while ((e = e->next));
589 6 emit_regsetimm(emit, count, 0);
590 6 const Instr instr = emit_add_instr(emit, ArrayInit);
591 6 instr->m_val = (m_uint)type;
592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 const m_uint sz = base->actual_size ?: base->size;
593
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 instr->m_val2 = type->array_depth == 1 ? sz : SZ_INT;
594 6 emit_local_exp(emit, prim_exp(data));
595 6 emit_notpure(emit);
596 6 return GW_OK;
597 }
598
599 ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e);
600
601 9 ANN static m_bool emit_range(const Emitter emit, Range *range) {
602
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if (range->start)
603
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(emit_exp_pop_next(emit, range->start));
604 1 else emit_pushimm(emit, 0);
605
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
9 if (range->end)
606
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 CHECK_BB(emit_exp_pop_next(emit, range->end));
607 2 else emit_pushimm(emit, -1);
608 9 return GW_OK;
609 }
610
611 2 ANN static m_bool emit_prim_range(const Emitter emit, Range **data) {
612 2 Range *range = *data;
613
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(emit_range(emit, range));
614
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 const Exp e = range->start ?: range->end;
615 2 const Symbol sym = insert_symbol("[:]");
616 assert(e);
617 4 struct Op_Import opi = {.op = sym,
618 2 .lhs = e->type,
619 .pos = e->pos,
620 2 .data = (uintptr_t)prim_exp(data)};
621
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(op_emit(emit, &opi));
622 2 emit_local_exp(emit, prim_exp(data));
623 2 return GW_OK;
624 }
625
626 2 static inline m_uint int2pow2(const m_uint x) {
627
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 return x == 1 ? 2 : 1<<(64-__builtin_clzl(x));
628 }
629
630 2 ANN static m_bool emit_prim_dict(const Emitter emit, Exp *data) {
631 2 Exp e = *data;
632 2 const Type key = e->type;
633 2 const Type val = e->next->type;
634 2 const Type t = dict_type(emit->gwion, key, val, e->pos);
635 2 const Instr init = emit_add_instr(emit, dict_ctor_alt);
636 2 const Exp next = e->next;
637 2 e->next = NULL;
638 2 struct Exp_ func = { .exp_type = ae_exp_primary, .d = { .prim = { .prim_type = ae_prim_id, .d = { .var = insert_symbol("hash") }} }};
639 2 struct Exp_ call = { .exp_type = ae_exp_call, .d = { .exp_call = { .func = &func, .args = e}}};
640
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(traverse_exp(emit->env, &call));
641 2 e->next = next;
642 2 m_uint count = 0;
643 do {
644 4 const Exp next = e->next;
645 4 const Exp nnext = next->next;
646 4 next->next = NULL;
647 4 e->next = NULL;
648
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_exp(emit, e));
649 4 e->next = next;
650
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_exp(emit, next));
651 4 next->next = nnext;
652
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if(key->size == SZ_INT) {
653 3 const Instr instr = emit_add_instr(emit, Reg2Reg);
654 3 instr->m_val2 = -SZ_INT - val->size;
655 3 emit_regmove(emit, SZ_INT);
656 } else {
657 1 const Instr instr = emit_add_instr(emit, Reg2RegOther);
658 1 instr->m_val = -key->size;
659 1 instr->m_val2 = key->size;
660 1 emit_regmove(emit, key->size);
661 }
662 4 e->next = next;
663
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_exp(emit, &func));
664
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_exp_call1(emit, func.type->info->func, true));
665 4 count++;
666
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 } while((e = e->next->next));
667 2 init->m_val = int2pow2(count);
668 2 init->m_val2 = (m_uint)t;
669 2 const m_uint sz = (key->size + val->size + SZ_INT) * count;
670 2 emit_regmove(emit, -sz);
671 2 const Instr ctor = emit_add_instr(emit, dict_lit_ctor);
672 2 ctor->m_val = sz;
673 2 ctor->m_val2 = count;
674 2 return GW_OK;
675 }
676
677 16 ANN m_bool emit_array_access(const Emitter emit,
678 struct ArrayAccessInfo *const info) {
679
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (tflag(info->array.type, tflag_typedef))
680 info->array.type = typedef_base(info->array.type);
681 // look mum no pos
682 16 struct Op_Import opi = {.op = insert_symbol("[]"),
683 16 .lhs = info->array.exp->type,
684 16 .rhs = info->array.type,
685 16 .data = (uintptr_t)info};
686 /*
687 if (!info->is_var &&
688 (GET_FLAG(info->array.type, abstract) || type_ref(info->array.type)))
689 emit_fast_except(emit, NULL, info->array.exp->pos);
690 */
691 16 return op_emit(emit, &opi);
692 }
693
694 16 ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array *array) {
695 16 const Exp e = exp_self(array);
696 16 exp_setvar(array->base, get_emit_var(emit, array->base->type, exp_getvar(e)));
697
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 CHECK_BB(emit_exp(emit, array->base));
698 32 struct ArrayAccessInfo info = {
699 16 .array = *array->array,
700 16 .type = e->type,
701 16 .is_var = exp_getvar(e)};
702 16 return emit_array_access(emit, &info);
703 }
704
705 7 ANN static m_bool emit_exp_slice(const Emitter emit, const Exp_Slice *range) {
706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 CHECK_BB(emit_exp(emit, range->base));
707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 CHECK_BB(emit_range(emit, range->range));
708 7 const Symbol sym = insert_symbol("[:]");
709
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 const Exp e = range->range->start ?: range->range->end;
710 assert(e);
711 14 struct Op_Import opi = {.op = sym,
712 7 .lhs = e->type,
713 7 .rhs = range->base->type,
714 .pos = e->pos,
715 7 .data = (uintptr_t)exp_self(range)};
716
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 CHECK_BB(op_emit(emit, &opi));
717 7 emit_local_exp(emit, exp_self(range));
718 7 return GW_OK;
719 }
720
721 271 ANN static m_bool specialid_instr(const Emitter emit,
722 struct SpecialId_ *spid,
723 const Exp_Primary *prim) {
724
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 122 times.
271 if(spid->exec) emit_add_instr(emit, spid->exec);
725
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
122 else if (spid->em) return spid->em(emit, prim);
726 149 return GW_OK;
727 }
728
729 1274 ANN static m_bool emit_prim_id(const Emitter emit, const Symbol *data) {
730 1274 struct SpecialId_ *spid = specialid_get(emit->gwion, *data);
731
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 1003 times.
1274 if (unlikely(spid))
732 271 return specialid_instr(emit, spid, prim_self(data));
733 1003 return emit_symbol(emit, prim_self(data));
734 }
735
736 1 ANN static m_bool emit_prim_perform(const Emitter emit, const Symbol *xid) {
737 1 const Instr instr = emit_add_instr(emit, PerformEffect);
738
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(*xid) instr->m_val = (m_uint)s_name(*xid);
739 1 instr->m_val2 = emit->status.effect;
740 1 return GW_OK;
741 }
742
743 418 ANN static m_bool emit_prim_num(const Emitter emit, const m_uint *num) {
744 418 emit_pushimm(emit, *num);
745 418 return GW_OK;
746 }
747
748 48 ANN static m_bool emit_prim_float(const Emitter emit, const m_float *fnum) {
749 48 const Instr instr = emit_add_instr(emit, RegPushImm2);
750 48 instr->f = *fnum;
751 48 return GW_OK;
752 }
753
754 22 ANN static m_bool emit_prim_char(const Emitter emit, const m_str *str) {
755 22 const char c = str2char(emit, *str, prim_pos(str));
756 22 emit_pushimm(emit, c);
757 22 return GW_OK;
758 }
759
760 335 ANN static m_bool emit_prim_str(const Emitter emit, const struct AstString *str) {
761 335 const Value v = prim_self(str)->value;
762 335 bool has_obj = v->d.obj;
763
2/2
✓ Branch 0 taken 230 times.
✓ Branch 1 taken 105 times.
335 if (!has_obj) {
764 230 const size_t sz = strlen(str->data);
765 230 char c[sz + 1];
766
2/2
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 19 times.
230 if (sz) {
767 211 strcpy(c, str->data);
768
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 209 times.
211 CHECK_BB(escape_str(emit, c, prim_pos(str)));
769 } else
770 19 c[0] = '\0';
771 228 v->d.obj = new_string(emit->gwion, c);
772 }
773 333 emit_pushimm(emit, (m_uint)v->d.obj);
774 333 emit_object_addref(emit, -SZ_INT, 0);
775 333 return GW_OK;
776 }
777
778 #define emit_prim_nil (void *)dummy_func
779
780 863 ANN static inline void interp_size(const Emitter emit, const Exp e) {
781
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
870 const Type t = !tflag(e->type, tflag_ref) || safe_tflag(e->cast_to, tflag_ref) ?
782
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 856 times.
870 e->type : (Type)vector_front(&e->type->info->tuple->contains);
783 863 emit_regsetimm(emit, t->size, SZ_INT);
784 863 }
785
786 863 ANN static void emit_gack_type(const Emitter emit, const Exp e) {
787
2/2
✓ Branch 0 taken 860 times.
✓ Branch 1 taken 3 times.
863 if (e->exp_type == ae_exp_cast ||
788
4/4
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 380 times.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 239 times.
860 (e->exp_type == ae_exp_primary && e->d.prim.prim_type == ae_prim_str))
789 244 return;
790 619 const m_bool isobj = isa(e->type, emit->gwion->type[et_object]) > 0;
791
6/6
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 472 times.
✓ Branch 3 taken 146 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 131 times.
✓ Branch 6 taken 15 times.
619 if (isobj && (tflag(e->type, tflag_ref) || !GET_FLAG(e->type, final)))
792 132 emit_add_instr(emit, GackType);
793 }
794
795 655 ANN /*static*/ m_bool emit_interp(const Emitter emit, const Exp exp) {
796 655 emit_pushimm(emit, 0);
797 655 emit_local(emit, emit->gwion->type[et_int]);
798 655 Exp e = exp, next = NULL;
799 do {
800 865 next = e->next;
801 865 e->next = NULL;
802
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 863 times.
865 if (emit_exp(emit, e) < 0) {
803 2 e->next = next;
804 2 return GW_ERROR;
805 }
806
3/4
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 856 times.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
870 if(tflag(e->type, tflag_ref) && !safe_tflag(e->cast_to, tflag_ref)) {
807 7 const Type t = (Type)vector_front(&e->type->info->tuple->contains);
808 7 emit_regsetimm(emit, (m_uint)t, 0);
809 } else
810 856 emit_regsetimm(emit, (m_uint)e->type, 0);
811 863 interp_size(emit, e);
812 863 emit_gack_type(emit, e);
813 863 const Instr instr = emit_add_instr(emit, Gack);
814 863 instr->m_val = emit_code_offset(emit);
815
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 653 times.
863 } while ((e = e->next = next));
816 653 return GW_OK;
817 }
818
819 638 ANN static m_bool emit_prim_hack(const Emitter emit, const Exp *exp) {
820
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 636 times.
638 CHECK_BB(emit_interp(emit, *exp));
821
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 458 times.
636 if (!(emit->env->func &&
822
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 2 times.
178 emit->env->func->def->base->xid == insert_symbol("@gack")))
823 634 emit_add_instr(emit, GackEnd);
824 2 else emit_regtomem(emit, SZ_INT, -SZ_INT);
825 636 return GW_OK;
826 }
827
828 17 ANN static m_bool emit_prim_interp(const Emitter emit, const Exp *exp) {
829 17 const Exp e = *exp;
830
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 CHECK_BB(emit_interp(emit, e));
831 17 const Instr instr = emit_add_instr(emit, GackEnd);
832 17 instr->m_val = 1;
833 17 emit_localx(emit, emit->gwion->type[et_string]);
834 17 return GW_OK;
835 }
836
837 17 ANN m_bool emit_ensure_func(const Emitter emit, const Func f) {
838 17 const ValueFrom *from = f->value_ref->from;
839
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if(from->owner_class)
840
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 CHECK_BB(ensure_emit(emit, from->owner_class));
841
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14 times.
17 if(f->code) return GW_OK;
842 14 const m_uint scope = emit_push(emit, from->owner_class, from->owner);
843 14 const m_bool ret = emit_func_def(emit, f->def);
844 14 emit_pop(emit, scope);
845 14 return ret;
846 }
847
848 4 ANN static m_bool emit_prim_locale(const Emitter emit, const Symbol *id) {
849
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if(emit->locale->def->d.code) {
850 2 const Stmt stmt = mp_vector_at((emit->locale->def->d.code), struct Stmt_, 0);
851 2 const Func f = stmt->d.stmt_exp.val->d.exp_call.func->type->info->func;
852
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_OB(emit_ensure_func(emit, f));
853 }
854
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_OB(emit_ensure_func(emit, emit->locale));
855 4 emit_push_code(emit, "locale"); // new code {
856 4 const M_Object string = new_string(emit->gwion, s_name(*id));
857 4 emit_pushimm(emit, (m_uint)string);
858 4 emit_pushimm(emit, (m_uint)emit->locale->code);
859
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_exp_call1(emit, emit->locale, true));
860 4 emit_regmove(emit, -emit->locale->def->base->ret_type->size);
861 4 const VM_Code code = finalyze(emit, EOC);
862 4 const VM_Shred shred = new_vm_shred(emit->gwion->mp, code);
863 4 vm_add_shred(emit->gwion->vm, shred);
864 4 shred->info->me->ref++;
865 4 vm_run(emit->gwion->vm);
866 4 emit->gwion->vm->bbq->is_running = true;
867 4 const m_float ret = *(m_float*)shred->reg;
868 4 release(shred->info->me, shred);
869
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if(ret == -1.0)
870 1 ERR_B(prim_pos(id), "error in locale");
871 3 const Instr instr = emit_add_instr(emit, RegPushImm2);
872 3 instr->f = ret;
873 3 return GW_OK;
874 }
875
876 DECL_PRIM_FUNC(emit, m_bool, Emitter);
877 2774 ANN static m_bool emit_prim(const Emitter emit, Exp_Primary *const prim) {
878 2774 return emit_prim_func[prim->prim_type](emit, &prim->d);
879 }
880
881 16 ANN static m_bool emit_dot_static_data(const Emitter emit, const Value v,
882 const bool emit_var) {
883 16 const m_uint size = v->type->size;
884 16 emit_dotstatic(emit, (m_uint)(v->from->owner->class_data + v->from->offset), size, emit_var);
885 16 return GW_OK;
886 }
887
888 5 ANN static m_bool _decl_static(const Emitter emit, const Exp_Decl *decl,
889 const Var_Decl *var_decl, const uint is_ref) {
890 5 const Value v = var_decl->value;
891
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 if(!decl->args) CHECK_BB(emit_instantiate_decl(emit, v->type, decl->td, is_ref));
892 else CHECK_BB(emit_exp(emit, decl->args));
893
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 CHECK_BB(emit_dot_static_data(emit, v, 1));
894 5 emit_add_instr(emit, Assign);
895 // if(get_depth(var_decl->value->type) && !is_ref)
896 // (void)emit_object_addref(emit, -SZ_INT, 0);
897 5 emit_regmove(emit, -SZ_INT);
898 5 return GW_OK;
899 }
900
901 5 ANN static m_bool decl_static(const Emitter emit, const Exp_Decl *decl,
902 const Var_Decl *var_decl, const uint is_ref) {
903 5 Code *const code = emit->code;
904 5 emit->code = (Code *)vector_back(&emit->stack);
905 5 const m_bool ret = _decl_static(emit, decl, var_decl, is_ref);
906 5 emit->code = code;
907 5 return ret;
908 }
909
910 521 ANN static inline int struct_ctor(const Value v) {
911
3/4
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 502 times.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
521 return tflag(v->type, tflag_struct) && tflag(v->type, tflag_ctor);
912 }
913
914 14 ANN static void decl_expand(const Emitter emit, const Type t) {
915 14 struct_expand(emit, t);
916 14 emit_regmove(emit, t->size - SZ_INT);
917 14 }
918
919 391 ANN static m_uint decl_non_static_offset(const Emitter emit, const Exp_Decl *decl, const Type t) {
920
1/2
✓ Branch 1 taken 391 times.
✗ Branch 2 not taken.
391 if(!exp_self(decl)->data)
921 391 return emit_local(emit, t);
922 const Local *l = exp_self(decl)->data;
923 exp_self(decl)->data = (void*)-1;
924 return l->offset;
925 }
926
927 19 ANN static m_bool struct_finish(const Emitter emit, const Exp_Decl *decl) {
928 19 const Type t = decl->type;
929 19 const bool emit_addr = exp_getvar(exp_self(decl));
930
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (decl->args) {
931
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(emit_exp(emit, decl->args));
932
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (emit_addr) {
933 2 emit_regmove(emit, -t->size);
934 2 emit_regpushmem4(emit, decl->vd.value->from->offset, 0);
935 }
936 2 return GW_OK;
937 }
938
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 if(tflag(t, tflag_ctor)) {
939 17 emit_ext_ctor(emit, t);
940
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (!emit_addr) decl_expand(emit, t);
941 }
942 17 return GW_OK;
943 }
944
945 11 ANN static m_bool emit_exp_decl_static(const Emitter emit, const Exp_Decl *decl,
946 const Var_Decl *var_decl,
947 const bool is_ref,
948 const bool emit_addr) {
949 11 const Value v = var_decl->value;
950
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
11 if (isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
951
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 CHECK_BB(decl_static(emit, decl, var_decl, 0));
952
4/6
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
11 CHECK_BB(emit_dot_static_data(emit, v, !struct_ctor(v) ? emit_addr : 1));
953
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11 if (tflag(v->type, tflag_struct)) CHECK_BB(struct_finish(emit, decl));
954
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
11 if (isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref) {
955
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
5 if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
956 emit_object_addref(emit, 0, emit_addr);
957 }
958 11 return GW_OK;
959 }
960
961 38 ANN static Instr emit_struct_decl(const Emitter emit, const Value v,
962 const bool emit_addr) {
963 38 emit_add_instr(emit, RegPushMem);
964 38 const Instr instr = emit_structmember(emit, v->from->offset, v->type->size, emit_addr);
965
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 16 times.
38 if (!emit_addr) {
966 22 const m_int sz = v->type->size - SZ_INT;
967
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8 times.
22 if (sz) emit_regmove(emit, sz);
968 }
969 38 return instr;
970 }
971
972 ANN void unset_local(const Emitter emit, Local *const l) {
973 l->instr->opcode = eNoOp;
974 for(m_uint i = m_vector_size(&emit->code->live_values) + 1; --i;) {
975 VMValue vmval = *(VMValue*)(ARRAY_PTR((&emit->code->live_values)) + (i-1) * sizeof(VMValue));
976 if(vmval.offset != l->offset) continue;
977 m_vector_rem(&emit->code->live_values, i-1);
978 vector_rem2(&emit->code->frame->stack, (m_uint)l);
979 vector_rem2(&emit->code->instr, (m_uint)l->instr);
980 free_instr(emit->gwion, l->instr);
981 emit->code->frame->curr_offset -= l->type->size;
982 --emit->code->frame->value_count;
983 break;
984 }
985 }
986
987 5 static INSTR(UsedBy) {
988 5 const MP_Vector *v =(MP_Vector*)instr->m_val;
989
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 for(uint32_t i = 0; i < v->len; i++) {
990 6 const Func f = *mp_vector_at(v, Func, i);
991 6 const Instr instr = (Instr)vector_front(&f->code->instr);
992 6 instr->m_val2++;
993 }
994 5 }
995
996 5 ANN static void used_by(const Emitter emit, const Value v) {
997 5 MP_Vector *vec = new_mp_vector(emit->gwion->mp, Func, 0);
998
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 for(uint32_t i = 0; i < v->used_by->len; i++) {
999 6 const Func f = *mp_vector_at(v->used_by, Func, i);
1000
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 if(f->_wait) mp_vector_add(emit->gwion->mp, &vec, Func, f);
1001 }
1002 5 free_mp_vector(emit->gwion->mp, Func, v->used_by);
1003 5 v->used_by = vec;
1004
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(vec->len) {
1005 5 const Instr instr = emit_add_instr(emit, UsedBy);
1006 5 instr->m_val = (m_uint)vec;
1007 }
1008 5 }
1009 505 ANN static m_bool emit_exp_decl_non_static(const Emitter emit,
1010 const Exp_Decl *decl,
1011 const Var_Decl *var_decl,
1012 const uint is_ref,
1013 const uint emit_var) {
1014 505 const Value v = var_decl->value;
1015 505 const Type type = v->type;
1016 505 const bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
1017
8/8
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 328 times.
✓ Branch 2 taken 155 times.
✓ Branch 3 taken 22 times.
✓ Branch 4 taken 350 times.
✓ Branch 5 taken 155 times.
✓ Branch 6 taken 80 times.
✓ Branch 7 taken 270 times.
505 const bool emit_addr = (!is_obj || is_ref) ? emit_var : true;
1018
5/6
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 328 times.
✓ Branch 2 taken 155 times.
✓ Branch 3 taken 22 times.
✓ Branch 5 taken 155 times.
✗ Branch 6 not taken.
505 if (is_obj && !is_ref && !exp_self(decl)->ref) {
1019
3/4
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 153 times.
155 if(!decl->args) CHECK_BB(emit_instantiate_decl(emit, type, decl->td, is_ref));
1020
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 else CHECK_BB(emit_exp(emit, decl->args));
1021 }
1022 505 f_instr *exec = (f_instr *)allocmember;
1023
2/2
✓ Branch 0 taken 324 times.
✓ Branch 1 taken 181 times.
505 if (!emit->env->scope->depth) emit_debug(emit, v);
1024
2/2
✓ Branch 1 taken 391 times.
✓ Branch 2 taken 114 times.
505 if (!vflag(v, vflag_member)) {
1025
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 388 times.
391 if(v->used_by) used_by(emit, v);
1026 391 v->from->offset = decl_non_static_offset(emit, decl, type);
1027 391 exec = (f_instr *)(allocword);
1028
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 370 times.
391 if (GET_FLAG(v, late)) // ref or emit_var ?
1029 21 emit_memsetimm(emit, v->from->offset, 0);
1030 }
1031
3/4
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 467 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
505 if(!(safe_tflag(emit->env->class_def, tflag_struct) && !emit->env->scope->depth))
1032
4/4
✓ Branch 1 taken 449 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 214 times.
✓ Branch 4 taken 235 times.
467 emit_kind(emit, v->from->offset, v->type->size, !struct_ctor(v) ? emit_addr : true,
1033 exec);
1034
3/4
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 22 times.
38 else emit_struct_decl(emit, v, !struct_ctor(v) ? emit_addr : 1);
1035
5/6
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 328 times.
✓ Branch 2 taken 155 times.
✓ Branch 3 taken 22 times.
✓ Branch 5 taken 155 times.
✗ Branch 6 not taken.
505 if (is_obj && !is_ref && !exp_self(decl)->ref) {
1036
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 if (!emit_var)
1037 155 emit_add_instr(emit, Assign);
1038 else {
1039 emit_regmove(emit, -SZ_INT);
1040 const Instr instr = emit_add_instr(emit, Reg2Reg);
1041 instr->m_val = -SZ_INT;
1042 }
1043 // if(safe_tflag(emit->env->class_def, tflag_struct) && GET_FLAG(emit->env->class_def, global))
1044 // emit_object_addref(emit, 0, emit_addr);
1045
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 332 times.
350 } else if (tflag(v->type, tflag_struct))
1046
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 CHECK_BB(struct_finish(emit, decl));
1047 505 return GW_OK;
1048 }
1049
1050 5 ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl,
1051 const Var_Decl *var_decl,
1052 const uint is_ref, const bool emit_var) {
1053 5 const Value v = var_decl->value;
1054 5 const Type type = v->type;
1055 5 const bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
1056
7/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 3 times.
5 const bool emit_addr = (!is_obj || is_ref) ? emit_var : true;
1057
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
5 if (is_obj && !is_ref) {
1058
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if(!decl->args) CHECK_BB(emit_instantiate_decl(emit, type, decl->td, is_ref));
1059 else CHECK_BB(emit_exp(emit, decl->args));
1060 }
1061
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (type->size > SZ_INT)
1062 1 v->d.ptr = mp_calloc2(emit->gwion->mp, v->type->size);
1063
4/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
5 emit_dotstatic(emit, (m_uint)&v->d.ptr, v->type->size, !struct_ctor(v) ? emit_addr : 1);
1064 // set_vflag(v, vflag_direct); // mpalloc // set in check.c
1065
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if(v->used_by) used_by(emit, v);
1066
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
6 if (is_obj && !is_ref) {
1067 1 const Instr assign = emit_add_instr(emit, Assign);
1068 1 assign->m_val = emit_var;
1069 1 (void)emit_object_addref(emit, -SZ_INT, emit_var);
1070
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 } else if (tflag(v->type, tflag_struct)) {
1071 // (void)emit_struct_addref(emit, v->type, -v->type->size, emit_var);
1072 1 struct_finish(emit, decl);
1073 }
1074 5 return GW_OK;
1075 }
1076
1077 521 ANN static void set_late(const Exp_Decl *decl, const Var_Decl *var) {
1078 521 const Value v = var->value;
1079
2/2
✓ Branch 2 taken 439 times.
✓ Branch 3 taken 82 times.
521 if (!exp_getvar(exp_self(decl)) &&
1080
4/4
✓ Branch 1 taken 437 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 432 times.
439 (GET_FLAG(array_base_simple(v->type), abstract) || GET_FLAG(decl->td, late)))
1081 7 SET_FLAG(v, late);
1082 514 else UNSET_FLAG(v, late);
1083 521 }
1084
1085 static inline bool late_array(const Type_Decl* td) {
1086 return !td->array || !td->array->exp;
1087 }
1088
1089 521 ANN static m_bool emit_decl(const Emitter emit, Exp_Decl *const decl) {
1090 521 const m_bool global = GET_FLAG(decl->td, global);
1091 521 const uint var = exp_getvar(exp_self(decl));
1092
3/4
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 516 times.
521 const uint ref = GET_FLAG(decl->td, late) || type_ref(decl->type);
1093 521 Var_Decl *vd = &decl->vd;
1094 521 const Value v = vd->value;
1095
4/4
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 497 times.
521 const uint r = ref || GET_FLAG(v, late);
1096
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 510 times.
521 if (GET_FLAG(decl->td, static))
1097
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 CHECK_BB(emit_exp_decl_static(emit, decl, vd, r, var));
1098
2/2
✓ Branch 0 taken 505 times.
✓ Branch 1 taken 5 times.
510 else if (!global)
1099
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 505 times.
505 CHECK_BB(emit_exp_decl_non_static(emit, decl, vd, r, var));
1100 else
1101
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 CHECK_BB(emit_exp_decl_global(emit, decl, vd, r, var));
1102
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 521 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
521 if (tflag(v->type, tflag_contract) &&
1103 !exp_getvar(exp_self(decl))) {
1104 const Type t = v->type;
1105 struct Op_Import opi = {.lhs = t->info->base_type,
1106 .op = insert_symbol("@implicit"),
1107 .rhs = t};
1108 CHECK_BB(op_emit(emit, &opi));
1109 }
1110 521 set_late(decl, vd);
1111
5/8
✓ Branch 0 taken 517 times.
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 437 times.
✓ Branch 5 taken 80 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 437 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
521 if (!decl->args && !exp_getvar(exp_self(decl)) && GET_FLAG(array_base_simple(v->type), abstract) && !GET_FLAG(decl->td, late) &&
1112 GET_FLAG(v, late) && late_array(decl->td)
1113 && GET_FLAG(v->type, abstract)) {
1114 env_err(emit->env, decl->td->pos, _("Type '%s' is abstract, use {+G}late{0} instead of {G+}%s{0}"),
1115 v->type->name, !GET_FLAG(decl->td, const) ? "var" : "const");
1116 if(v->type->nspc->vtable.ptr) {
1117 const Vector vec = &v->type->nspc->vtable;
1118 for(m_uint i = 0; i < vector_size(vec); i++) {
1119 const Func f = (Func)vector_at(vec, i);
1120 if(is_new(f->def)) {
1121 gw_err(_("maybe use a constructor?\n"));
1122 break;
1123 }
1124 }
1125 }
1126 return GW_ERROR;
1127 }
1128
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 514 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 6 times.
521 if(GET_FLAG(v, late) && exp_getuse(exp_self(decl)))
1129 1 emit_add_instr(emit, GWOP_EXCEPT);
1130 521 return GW_OK;
1131 }
1132
1133 521 ANN /*static */ m_bool emit_exp_decl(const Emitter emit, Exp_Decl *const decl) {
1134 521 const Type t = decl->type;
1135
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 517 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
521 if(decl->args && !strncmp(decl->args->type->name, "partial:", 8))
1136 ERR_B(decl->args->pos, "unresolved partial");
1137
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 521 times.
521 CHECK_BB(ensure_emit(emit, t));
1138 521 const m_bool global = GET_FLAG(decl->td, global);
1139 521 const m_uint scope =
1140
2/2
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 5 times.
521 !global ? emit->env->scope->depth : emit_push_global(emit);
1141 521 const m_bool ret = emit_decl(emit, decl);
1142
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 516 times.
521 if (global) emit_pop(emit, scope);
1143
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 521 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
521 if(emit->status.in_return && GET_FLAG(decl->vd.value, late) && isa(t, emit->gwion->type[et_object]) > 0)
1144 emit_add_instr(emit, GWOP_EXCEPT);
1145 521 return ret;
1146 }
1147
1148
1149 // see take exp
1150 Exp nth_exp(Exp e, uint32_t n) {
1151 for(uint32_t i = 0; i < n; i++)
1152 e = e->next;
1153 return e;
1154 }
1155
1156 384 ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call *exp_call) {
1157
3/4
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 172 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 212 times.
384 if (exp_call->args) CHECK_BB(emit_exp(emit, exp_call->args));
1158 384 return GW_OK;
1159 }
1160
1161 363 ANN static m_bool prepare_call(const Emitter emit, const Exp_Call *exp_call) {
1162
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 363 times.
363 CHECK_BB(emit_func_args(emit, exp_call));
1163 363 return emit_exp(emit, exp_call->func);
1164 }
1165
1166 347 ANN static inline void emit_return_pc(const Emitter emit, const m_uint val) {
1167 LOOP_OPTIM
1168
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 347 times.
411 for (m_uint i = vector_size(&emit->code->stack_return) + 1; --i;) {
1169 64 const Instr instr = (Instr)vector_at(&emit->code->stack_return, i - 1);
1170 64 instr->m_val = val;
1171 }
1172 347 }
1173
1174 ANN static inline void pop_exp(const Emitter emit, Exp e);
1175
1176 314 ANN static inline void scoped_ini(const Emitter emit) {
1177 314 ++emit->env->scope->depth;
1178 314 emit_push_scope(emit);
1179 314 }
1180
1181 314 ANN static inline void scoped_end(const Emitter emit) {
1182 314 emit_pop_scope(emit);
1183 314 --emit->env->scope->depth;
1184 314 }
1185
1186 100 ANN static m_bool scoped_stmt(const Emitter emit, const Stmt stmt) {
1187 100 scoped_ini(emit);
1188 100 const m_bool ret = emit_stmt(emit, stmt);
1189 100 scoped_end(emit);
1190 100 return ret;
1191 }
1192
1193 #ifdef GWION_INLINE
1194 ANN static inline bool check_inline(const Emitter emit, const Func f) {
1195 const uint16_t caller_size = emit->env->func ? emit->env->func->weight
1196 : emit->env->class_def
1197 ? emit->env->class_def->weight
1198 : emit->env->context ? emit->env->context->weight
1199 : 0;
1200 const float threshold = caller_size * f->inline_mult;
1201 return f->weight < threshold;
1202 }
1203
1204 ANN static inline bool member_inlinable(const Emitter emit, const Func f, const Exp e) {
1205 if (f!= emit->env->func)return false;
1206 const Type owner_class = f->value_ref->from->owner_class;
1207 if (!owner_class) return true;
1208 return GET_FLAG(owner_class, final) || GET_FLAG(f->def->base, final) ||
1209 (e->exp_type == ae_exp_dot &&
1210 e->d.exp_dot.base->exp_type == ae_exp_cast);
1211 }
1212
1213 ANN static inline Func is_inlinable(const Emitter emit,
1214 const Exp_Call *exp_call) {
1215 const Type ftype = exp_call->func->type;
1216 if (!is_func(emit->gwion, ftype) ||
1217 !ftype->info->func->code || ftype->info->func->code->builtin)
1218 return false;
1219 const Func f = ftype->info->func;
1220 return (member_inlinable(emit, f, exp_call->func) && check_inline(emit, f)) ? f
1221 : NULL;
1222 }
1223
1224 ANN static inline void inline_args_ini(const Emitter emit, const Func f,
1225 const Vector v) {
1226 const bool member = f->value_ref->from->owner_class && vflag(f->value_ref, vflag_member);
1227 if(member)
1228 emit->status.this_offset = emit_local(emit, emit->gwion->type[et_int]);
1229 const m_uint start_offset = emit_code_offset(emit) - (member ? SZ_INT : 0);
1230 Arg_List args = f->def->base->args;
1231 for(uint32_t i = 0; i < args->len; i++) {
1232 const Arg *arg = mp_vector_at(args, Arg, i);
1233 const Value value = arg->var_decl.value;
1234 vector_add(v, value->from->offset);
1235 value->from->offset = emit_local(emit, value->type);
1236 _nspc_add_value(emit->env->curr, arg->var_decl.xid, value);
1237 }
1238 emit_regmove(emit, -f->code->stack_depth);
1239 emit_regtomem4(emit, f->code->stack_depth, start_offset);
1240 }
1241
1242 ANN static inline void inline_args_end(const Func f, const Vector v) {
1243 Arg_List args = f->def->base->args;
1244 for(uint32_t i = 0; i < args->len; i++) {
1245 const Arg *arg = mp_vector_at(args, Arg, i);
1246 const Value value = arg->var_decl.value;
1247 value->from->offset = vector_at(v, i++);
1248 }
1249 }
1250
1251 ANN static inline m_bool inline_body(const Emitter emit, const Func f) {
1252 struct Vector_ v = {.ptr = emit->code->stack_return.ptr};
1253 vector_init(&emit->code->stack_return);
1254 nspc_push_value(emit->gwion->mp, emit->env->curr);
1255 scoped_ini(emit);
1256 const m_bool ret = emit_stmt_list(emit, f->def->d.code);
1257 scoped_end(emit);
1258 emit_return_pc(emit, emit_code_size(emit));
1259 nspc_pop_value(emit->gwion->mp, emit->env->curr);
1260 vector_release(&emit->code->stack_return);
1261 emit->code->stack_return.ptr = v.ptr;
1262 return ret;
1263 }
1264
1265 ANN static inline m_bool inline_run(const Emitter emit, const Func f) {
1266 struct Vector_ arg_offset;
1267 vector_init(&arg_offset);
1268 inline_args_ini(emit, f, &arg_offset);
1269 const m_bool ret = inline_body(emit, f);
1270 inline_args_end(f, &arg_offset);
1271 vector_release(&arg_offset);
1272 return ret;
1273 }
1274
1275 ANN static inline m_bool _emit_inline(const Emitter emit, const Func f,
1276 const Exp_Call *exp_call) {
1277 if (!f->weight) return GW_OK;
1278 if (f->value_ref->from->owner_class && vflag(f->value_ref, vflag_member))
1279 CHECK_BB(emit_exp(emit, exp_call->func->d.exp_dot.base));
1280 CHECK_BB(emit_func_args(emit, exp_call));
1281 return inline_run(emit, f);
1282 }
1283
1284 ANN static inline m_bool emit_inline(const Emitter emit, const Func f,
1285 const Exp_Call *exp_call) {
1286 const EmitterStatus status = emit->status;
1287 nspc_push_value(emit->gwion->mp, emit->env->curr);
1288 const m_bool ret = _emit_inline(emit, f, exp_call);
1289 nspc_pop_value(emit->gwion->mp, emit->env->curr);
1290 emit->status = status;
1291 return ret;
1292 }
1293 #endif
1294
1295
1296 358 ANN static inline bool is_new_struct(const Func f, const Type t) {
1297
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 341 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 9 times.
358 return is_new(f->def) && tflag(t, tflag_struct);
1298 }
1299
1300 8 ANN static m_bool emit_new_struct(const Emitter emit,const Exp_Call *call) {
1301 8 const Exp self = exp_self(call);
1302 8 const Type t = self->type;
1303
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 const m_int offset = self->ref ? emit->code->frame->curr_offset - t->size: emit_local(emit, t);
1304
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 const Instr back = self->ref ? (Instr)vector_pop(&emit->code->instr) : NULL;
1305
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(emit_func_args(emit, call));
1306
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if(back)
1307 2 vector_add(&emit->code->instr, (m_uint)back);
1308
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 else if(tflag(t, tflag_ctor))
1309 6 emit_regpushmem4(emit, offset, 0);
1310
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 if(tflag(t, tflag_ctor)) emit_ext_ctor(emit, t);
1311 else if(!back) {
1312 emit_regmove(emit, -SZ_INT + t->size);
1313 emit_regpushmem4(emit, offset, 0);
1314 }
1315 8 emit_add_instr(emit, NoOp);
1316
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 CHECK_BB(emit_exp_call1(emit, call->func->type->info->func, is_static_call(emit->gwion, call->func))); // is a ctor, is_static is true
1317 8 return GW_OK;
1318 }
1319
1320 358 ANN static m_bool _emit_exp_call(const Emitter emit, const Exp_Call *call) {
1321 #ifdef GWION_INLINE
1322 const Func _f = is_inlinable(emit, call);
1323 if(_f) {
1324 const Func base = emit->env->func;
1325 emit->env->func = _f;
1326 const m_uint scope = emit_push(emit, _f->value_ref->from->owner_class, _f->value_ref->from->owner);
1327 const m_bool ret = emit_inline(emit, _f, call);
1328 emit_pop(emit, scope);
1329 emit->env->func = base;
1330 return ret;
1331 }
1332 #endif
1333
1334 358 const Type t = call->func->type;
1335
1336
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 358 times.
358 if(unlikely(!is_func(emit->gwion, t))) {
1337 const Type t = actual_type(emit->gwion, call->func->type);
1338 struct Op_Import opi = {.op = insert_symbol("call_type"),
1339 .rhs = t,
1340 .data = (uintptr_t)call,
1341 .pos = exp_self(call)->pos};
1342 CHECK_BB(op_emit(emit, &opi));
1343 }
1344 358 const Func f = t->info->func;
1345
2/2
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 350 times.
358 if(unlikely(is_new_struct(f, exp_self(call)->type)))
1346 8 emit_new_struct(emit, call);
1347 else {
1348
5/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 338 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 11 times.
350 if (f != emit->env->func || (f && f->value_ref->from->owner_class))
1349
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 339 times.
339 CHECK_BB(prepare_call(emit, call));
1350
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 else CHECK_BB(emit_func_args(emit, call));
1351
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 350 times.
350 CHECK_BB(emit_exp_call1(emit, f, is_static_call(emit->gwion, call->func)));
1352 }
1353 358 return GW_OK;
1354 }
1355
1356 358 ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call *exp_call) {
1357
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 358 times.
358 CHECK_BB(_emit_exp_call(emit, exp_call));
1358 358 const Exp e = exp_self(exp_call);
1359
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 352 times.
358 if (exp_getvar(e)) {
1360 6 const m_uint size = exp_self(exp_call)->type->size;
1361 6 emit_regmove(emit, -size);
1362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 const Local *l = e->ref ? e->ref->data : NULL;
1363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 const m_uint offset = l ? l->offset : emit_local_exp(emit, e);
1364 6 emit_regtomem4(emit, offset, size);
1365 6 emit_regpushmem4(emit, offset, 0);
1366 }
1367 358 return GW_OK;
1368 }
1369
1370 1569 ANN static m_uint get_type_size(const Exp e) {
1371
3/4
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1568 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1569 if(tflag(e->type, tflag_ref)&& !safe_tflag(e->cast_to, tflag_ref)) {
1372 1 const Type base =(Type)vector_front(&e->type->info->tuple->contains);
1373 1 return base->size;
1374 }
1375 1568 return e->type->size;
1376 }
1377
1378 1567 ANN static m_uint pop_exp_size(Exp e) {
1379 1567 const bool emit_addr = exp_getvar(e);
1380 1567 m_uint size = 0;
1381
1/2
✓ Branch 0 taken 1569 times.
✗ Branch 1 not taken.
1569 do size += !emit_addr ? get_type_size(e) : SZ_INT;
1382
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1567 times.
1569 while ((e = e->next));
1383 1567 return size;
1384 }
1385
1386 1567 ANN static inline void pop_exp(const Emitter emit, Exp e) {
1387 1567 const m_uint size = pop_exp_size(e);
1388
2/2
✓ Branch 0 taken 1396 times.
✓ Branch 1 taken 171 times.
1567 if (size) emit_regmove(emit, -size);
1389 1567 }
1390
1391 1068 ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e) {
1392
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1068 times.
1068 CHECK_BB(emit_exp(emit, e));
1393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
1068 if (e->next) pop_exp(emit, e->next);
1394 1068 return GW_OK;
1395 }
1396
1397 438 ANN static m_bool emit_exp_binary(const Emitter emit, const Exp_Binary *bin) {
1398 438 const Exp lhs = bin->lhs;
1399 438 const Exp rhs = bin->rhs;
1400
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 438 times.
438 CHECK_BB(emit_exp_pop_next(emit, lhs));
1401
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 438 times.
438 CHECK_BB(emit_exp_pop_next(emit, rhs));
1402 876 struct Op_Import opi = {.op = bin->op,
1403 438 .lhs = lhs->type,
1404 438 .rhs = rhs->type,
1405 438 .pos = exp_self(bin)->pos,
1406 438 .data = (uintptr_t)bin};
1407 438 return op_emit(emit, &opi);
1408 }
1409
1410 8 ANN static m_bool emit_exp_cast(const Emitter emit, const Exp_Cast *cast) {
1411
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(emit_exp(emit, cast->exp));
1412 16 struct Op_Import opi = {.op = insert_symbol("$"),
1413 8 .lhs = cast->exp->type,
1414 8 .rhs = exp_self(cast)->type,
1415 8 .data = (uintptr_t)cast}; // no pos ?
1416 8 (void)op_emit(emit, &opi);
1417 8 return GW_OK;
1418 }
1419
1420 27 ANN static m_bool emit_exp_post(const Emitter emit, const Exp_Postfix *post) {
1421
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 CHECK_BB(emit_exp(emit, post->exp));
1422 27 struct Op_Import opi = {.op = post->op,
1423 27 .lhs = post->exp->type,
1424 27 .data = (uintptr_t)post}; // no pos ?
1425 27 return op_emit(emit, &opi);
1426 }
1427
1428 6 ANN static inline m_bool traverse_emit_func_def(const Emitter emit,
1429 const Func_Def fdef) {
1430
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 if (!fdef->base->ret_type) CHECK_BB(traverse_func_def(emit->env, fdef));
1431 6 return emit_func_def(emit, fdef);
1432 }
1433
1434 6 ANN m_bool traverse_dot_tmpl(const Emitter emit, const Func_Def fdef, const Value v) {
1435 6 const m_uint scope = emit->env->scope->depth;
1436 6 const bool shadowing = emit->env->scope->shadowing;
1437 6 emit->env->scope->shadowing = true;
1438 6 struct EnvSet es = {.env = emit->env,
1439 .data = emit,
1440 .func = (_exp_func)emit_cdef,
1441 .scope = scope,
1442 .flag = tflag_emit};
1443
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 CHECK_BB(envset_pushv(&es, v));
1444 6 (void)emit_push(emit, v->from->owner_class, v->from->owner);
1445 6 const m_bool ret = traverse_emit_func_def(emit, fdef);
1446 6 emit_pop(emit, scope);
1447 6 envset_pop(&es, v->from->owner_class);
1448 6 emit->env->scope->shadowing = shadowing;
1449 6 return ret;
1450 }
1451
1452 41 static INSTR(fptr_call) {
1453 41 const M_Object o = *(M_Object*)REG(-SZ_INT);
1454 41 *(VM_Code*)REG(-SZ_INT) = *(VM_Code*)(o->data + instr->m_val);
1455 41 const m_bit *caps = *(m_bit**)(o->data + SZ_INT);
1456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if(caps) {
1457 const Func_Def fdef = *(Func_Def*) caps;
1458 const Capture *cap = mp_vector_at(fdef->captures, Capture, fdef->captures->len - 1);
1459 const uint32_t sz = cap->offset + cap->temp->type->size - fdef->stack_depth;
1460 memcpy(REG(SZ_INT), caps + SZ_INT, sz);
1461 }
1462 41 }
1463
1464 222 static inline m_bool push_func_code(const Emitter emit, const Func f) {
1465
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 219 times.
222 if (!vector_size(&emit->code->instr)) {
1466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if(fflag(f, fflag_tmpl)) {
1467 // we are sporking a template
1468 // assume static call for now
1469 emit_regsetimm(emit, (m_uint)f->code, -SZ_INT);
1470 }
1471 3 return GW_OK;
1472 }
1473 219 const Instr instr = (Instr)vector_back(&emit->code->instr);
1474
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 9 times.
219 if(f->code) {
1475 210 instr->opcode = eRegPushImm;
1476 210 instr->m_val = (m_uint)f->code;
1477 }
1478 219 return GW_OK;
1479 }
1480
1481 31 ANN static m_bool emit_template_code(const Emitter emit, const Func f) {
1482 31 const Value v = f->value_ref;
1483 31 const size_t scope = emit->env->scope->depth;
1484 31 struct EnvSet es = {.env = emit->env,
1485 .data = emit,
1486 .func = (_exp_func)emit_cdef,
1487 .scope = scope,
1488 .flag = tflag_emit};
1489
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 CHECK_BB(envset_pushv(&es, v));
1490 31 (void)emit_push(emit, v->from->owner_class, v->from->owner);
1491 31 const m_bool ret = emit_func_def(emit, f->def);
1492 31 envset_pop(&es, v->from->owner_class);
1493 31 emit_pop(emit, scope);
1494
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 return ret > 0 ? push_func_code(emit, f) : GW_ERROR;
1495 }
1496
1497 10 ANN static void tmpl_prelude(const Emitter emit, const Func f) {
1498 10 const Instr gtmpl = emit_add_instr(emit, GTmpl);
1499 10 gtmpl->m_val = (m_uint)f->def;
1500 10 gtmpl->m_val2 = (m_uint)tl2str(emit->gwion, f->def->base->tmpl->call, f->def->base->pos);
1501 10 }
1502
1503 540 ANN static Instr get_prelude(const Emitter emit, const Func f,
1504 const bool is_static) {
1505
4/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 525 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 12 times.
540 if (f != emit->env->func || !is_static) {
1506 528 const Instr instr = emit_add_instr(emit, SetCode);
1507 528 instr->udata.one = 1;
1508 528 return instr;
1509 }
1510 12 const Instr instr = emit_add_instr(emit, Recurs);
1511 12 instr->m_val = SZ_INT;
1512 12 instr->udata.one = 1;
1513 12 instr->udata.two = emit_code_offset(emit) + sizeof(frame_t);
1514 12 return instr;
1515 }
1516
1517 226 ANN static void emit_args(const Emitter emit, const Func f) {
1518
2/2
✓ Branch 1 taken 85 times.
✓ Branch 2 taken 141 times.
226 const m_uint member = vflag(f->value_ref, vflag_member) ? SZ_INT : 0;
1519
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 91 times.
226 if ((f->def->stack_depth - member) == SZ_INT)
1520 135 emit_regtomem(emit, member, 0);
1521 else
1522 91 emit_regtomem4(emit, member, f->def->stack_depth - member);
1523 226 }
1524
1525 typedef struct {
1526 const Emitter emit;
1527 const Func_Def fdef;
1528 struct Vector_ branch;
1529 const m_uint offset;
1530 m_uint arg_offset;
1531 } MemoizeEmitter;
1532
1533 1 static m_bool me_cmp(MemoizeEmitter *me, const Arg *arg) {
1534 1 const Emitter emit = me->emit;
1535 1 const Symbol sym = insert_symbol("?=");
1536 1 struct Exp_ lhs = {
1537 .exp_type = ae_exp_primary,
1538 1 .type = arg->type,
1539 1 .pos = arg->td->pos,
1540 .d = {
1541 .prim = { .prim_type = ae_prim_id }
1542 }
1543 };
1544 1 struct Exp_ rhs = {
1545 .exp_type = ae_exp_primary,
1546 1 .type = me->emit->gwion->type[et_bool],
1547 1 .pos = arg->td->pos,
1548 .d = {
1549 .prim = { .prim_type = ae_prim_id }
1550 }
1551 };
1552 1 struct Exp_ bin = {
1553 .exp_type = ae_exp_binary,
1554 1 .type = arg->type,
1555 1 .pos = arg->td->pos,
1556 .d = {
1557 .exp_binary = {
1558 .lhs = &lhs,
1559 .op = sym,
1560 .rhs = &rhs
1561 }
1562 }
1563 };
1564 1 struct Op_Import opi = {.op = sym,
1565 1 .lhs = arg->type,
1566 1 .rhs = arg->type,
1567 1 .pos = me->fdef->base->pos,
1568 1 .data = (uintptr_t)&bin.d};
1569
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BB(op_emit(emit, &opi));
1570 1 const Instr instr = emit_add_instr(emit, BranchEqInt);
1571 1 vector_add(&me->branch, (vtype)instr);
1572 1 return GW_OK;
1573 }
1574
1575 1 ANN static m_bool me_arg(MemoizeEmitter *me) {
1576 1 Arg_List args = me->fdef->base->args;
1577
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for(uint32_t i = 0; i < args->len; i++) {
1578 1 Arg *arg = mp_vector_at(args, Arg, i);
1579 1 const m_uint sz = arg->type->size;
1580 1 emit_regpushmem(me->emit, me->arg_offset, sz, false);
1581 1 emit_regpushmem(me->emit, me->offset + SZ_INT * 2, sz, false);
1582
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BB(me_cmp(me, arg));
1583 1 me->arg_offset += sz;
1584 }
1585 1 return GW_OK;
1586 }
1587
1588 540 ANN static Instr emit_call(const Emitter emit, const Func f,
1589 const bool is_static) {
1590 540 const Instr prelude = get_prelude(emit, f, is_static);
1591 540 prelude->m_val += -f->def->stack_depth - SZ_INT;
1592
2/2
✓ Branch 1 taken 333 times.
✓ Branch 2 taken 207 times.
540 const m_uint member = vflag(f->value_ref, vflag_member) ? SZ_INT : 0;
1593
2/2
✓ Branch 0 taken 333 times.
✓ Branch 1 taken 207 times.
540 if (member) {
1594 333 emit_regtomem(emit, 0, f->def->stack_depth - SZ_INT);
1595 333 ++prelude->m_val2;
1596 }
1597
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 316 times.
540 if (f->def->stack_depth - member) {
1598 // f != emit->env->func ||
1599 // f->value_ref->from->owner_class || strstr(emit->code->name, "ork~"))
1600 {
1601 224 emit_args(emit, f);
1602 224 ++prelude->m_val2;
1603 }
1604 }
1605 540 return emit_add_instr(emit, Overflow);
1606 }
1607
1608 47 ANN static void emit_fptr_call(const Emitter emit, const Func f) {
1609 47 const Instr call = emit_add_instr(emit, fptr_call);
1610
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
47 if(f->def->base->tmpl) {
1611 // maybe merge those
1612 10 call->m_val = SZ_INT*2;
1613 10 tmpl_prelude(emit, f);
1614 }
1615 47 }
1616
1617 540 ANN static void call_finish(const Emitter emit, const Func f,
1618 const bool is_static) {
1619 540 const m_uint offset = emit_code_offset(emit);
1620
5/6
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 525 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
540 if (f != emit->env->func || !is_static || !is_new(f->def))
1621 540 emit_regsetimm(emit, offset, 0);
1622 540 const Instr instr = emit_call(emit, f, is_static);
1623 540 instr->m_val = f->def->base->ret_type->size;
1624 540 instr->m_val2 = offset;
1625 540 }
1626
1627 402 ANN m_bool emit_exp_call1(const Emitter emit, const Func f,
1628 const bool is_static) {
1629 402 const EmitterStatus status = emit->status;
1630 402 emit->status = (EmitterStatus){};
1631
2/2
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 355 times.
402 if(unlikely(fflag(f, fflag_fptr))) emit_fptr_call(emit, f);
1632
4/4
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 14 times.
355 else if (unlikely(!f->code && emit->env->func != f)) {
1633
3/4
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 31 times.
42 if (fflag(f, fflag_tmpl)) CHECK_BB(emit_template_code(emit, f));
1634 else //if(is_new(f->def))//if(tflag(f->value_ref->type, tflag_ftmpl))
1635 {
1636 11 const Type t = f->value_ref->from->owner_class;
1637
5/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 7 times.
11 if(t && (!emit->env->curr || isa(t, emit->env->class_def) < 0))
1638 //!is_new(f->def) || f->value_ref->from->owner_class->array_depth)
1639 //if(f->value_ref->from->owner_class->array_depth)
1640
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(emit_ensure_func(emit, f));
1641 }
1642
2/2
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 122 times.
313 } else if(is_static)
1643 191 push_func_code(emit, f);
1644 402 call_finish(emit, f, is_static);
1645 402 emit->status = status;
1646 402 return GW_OK;
1647 }
1648
1649 24 ANN static void emit_exp_spork_finish(const Emitter emit, const m_uint depth) {
1650 24 emit_regmove(emit, -depth);
1651 24 const Instr spork = emit_add_instr(emit, SporkFunc);
1652 24 spork->m_val = depth + SZ_INT;
1653 24 spork->m_val2 = -SZ_INT;
1654 24 }
1655
1656 224 ANN static inline void stack_alloc(const Emitter emit) {
1657 224 emit_local(emit,
1658 224 emit->gwion->type[et_int]); // hiding the fact it is an object
1659 224 emit->code->stack_depth += SZ_INT;
1660 224 }
1661
1662 #define SPORK_FUNC_PREFIX "spork~func:%u"
1663 #define FORK_FUNC_PREFIX "fork~func:%u"
1664 #define SPORK_CODE_PREFIX "spork~code:%u"
1665 #define FORK_CODE_PREFIX "fork~code:%u"
1666
1667 50 static void push_spork_code(const Emitter emit, const m_str prefix,
1668 50 const loc_t pos) {
1669 50 char c[strlen(SPORK_FUNC_PREFIX) + num_digit(pos.first.line) + 1];
1670 50 sprintf(c, prefix, pos.first.line);
1671 50 emit_push_code(emit, c);
1672 50 }
1673
1674 struct Sporker {
1675 const Stmt_List code;
1676 const Exp exp;
1677 VM_Code vm_code;
1678 const Type type;
1679 const Capture_List captures;
1680 const loc_t pos;
1681 const bool emit_var;
1682 const bool is_spork;
1683 };
1684
1685 26 ANN static m_bool spork_prepare_code(const Emitter emit,
1686 const struct Sporker *sp) {
1687 26 emit_pushimm(emit, 0);
1688
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 5 times.
26 push_spork_code(emit, sp->is_spork ? SPORK_CODE_PREFIX : FORK_CODE_PREFIX,
1689 sp->pos);
1690
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 21 times.
26 if (emit->env->class_def) stack_alloc(emit);
1691
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 20 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 1 times.
26 if (emit->env->func && vflag(emit->env->func->value_ref, vflag_member))
1692 5 stack_alloc(emit);
1693
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25 times.
26 if(sp->captures) emit->code->frame->curr_offset += captures_sz(sp->captures);
1694 // return scoped_stmt(emit, sp->code);
1695 26 return emit_stmt_list(emit, sp->code);
1696 }
1697
1698 24 ANN static m_bool spork_prepare_func(const Emitter emit,
1699 const struct Sporker *sp) {
1700 24 const Type t = actual_type(emit->gwion, sp->exp->d.exp_call.func->type);
1701 24 const Func f = t->info->func;
1702
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2 times.
24 if(!f->code && f != emit->env->func)
1703
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(emit_ensure_func(emit, f));
1704 24 push_spork_code(emit, sp->is_spork ? SPORK_FUNC_PREFIX : FORK_CODE_PREFIX,
1705
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 sp->exp->pos);
1706 24 return emit_exp_call1(emit, f, false);
1707 }
1708
1709 50 ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
1710
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 26 times.
50 if (!sp->code) {
1711 assert(sp->exp);
1712
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call));
1713 }
1714
3/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 24 times.
✓ Branch 3 taken 50 times.
✗ Branch 4 not taken.
50 if ((sp->code ? spork_prepare_code : spork_prepare_func)(emit, sp) > 0)
1715 50 return finalyze(emit, EOC);
1716 emit_pop_code(emit);
1717 return NULL;
1718 }
1719
1720 26 ANN void spork_code(const Emitter emit, const struct Sporker *sp) {
1721 26 const Instr args = emit_add_instr(emit, SporkExp);
1722 26 args->m_val = emit->code->stack_depth;
1723
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 5 times.
26 const Instr instr = emit_add_instr(emit, sp->is_spork ? SporkEnd : ForkEnd);
1724 26 instr->m_val = sp->emit_var;
1725 26 }
1726
1727 24 ANN void spork_func(const Emitter emit, const struct Sporker *sp) {
1728 24 const Func f =
1729 24 actual_type(emit->gwion, sp->exp->d.exp_call.func->type)->info->func;
1730 24 emit_exp_spork_finish(emit, f->def->stack_depth);
1731 24 (void)emit_add_instr(emit, SporkEnd);
1732 24 }
1733
1734 50 ANN static void spork_ini(const Emitter emit, const struct Sporker *sp) {
1735
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 5 times.
50 if (sp->is_spork) {
1736 45 const Instr instr = emit_add_instr(emit, SporkIni);
1737 45 instr->m_val = (m_uint)sp->vm_code;
1738 45 return;
1739 }
1740 5 const Instr instr = emit_add_instr(emit, ForkIni);
1741 5 instr->m_val = (m_uint)sp->vm_code;
1742 5 instr->m_val2 = (m_uint)sp->type;
1743 }
1744
1745 50 ANN m_bool emit_exp_spork(const Emitter emit, const Exp_Unary *unary) {
1746 300 struct Sporker sporker = {
1747
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 26 times.
50 .exp = unary->unary_type == unary_exp ? unary->exp : NULL,
1748
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 24 times.
50 .code = unary->unary_type == unary_code ? unary->code : NULL,
1749 50 .type = exp_self(unary)->type,
1750 50 .captures = unary->captures,
1751 50 .pos = exp_self(unary)->pos,
1752 50 .is_spork = (unary->op == insert_symbol("spork")),
1753 50 .emit_var = exp_getvar(exp_self(unary))};
1754
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 CHECK_OB((sporker.vm_code = spork_prepare(emit, &sporker)));
1755
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 45 times.
50 if(!sporker.is_spork)
1756 5 emit_local_exp(emit, exp_self(unary));
1757 50 spork_ini(emit, &sporker);
1758 // add this if needed
1759 // uint32_t offset = 0;
1760 50 m_uint offset = 0;
1761
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 13 times.
50 if(emit->env->class_def && sporker.code) {
1762 5 struct Exp_ exp = {
1763 .d = { .prim = {
1764 5 .d = { .var = insert_symbol("this") },
1765 .prim_type = ae_prim_id
1766 }},
1767 5 .type = emit->env->class_def,
1768 .exp_type = ae_exp_primary
1769 };
1770
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 CHECK_BB(emit_exp(emit, &exp));
1771 5 offset += SZ_INT;
1772 }
1773
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 49 times.
50 if(sporker.captures) {
1774 1 Capture_List caps = sporker.captures;
1775
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (uint32_t i = 0; i < caps->len; i++) {
1776 1 Capture *cap = mp_vector_at(caps, Capture, i);
1777 1 const Value v = cap->orig;
1778 1 struct Exp_ exp = {
1779 .d = { .prim = {
1780 1 .d = { .var = cap->xid },
1781 .value = v,
1782 .prim_type = ae_prim_id
1783 }},
1784 1 .type = v->type,
1785 .exp_type = ae_exp_primary
1786 };
1787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(cap->is_ref) exp_setvar(&exp, true);
1788 1 offset += exp_size(&exp);
1789
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BB(emit_exp(emit, &exp));
1790 // emit_exp_addref(emit, &exp, -exp_size(&exp));
1791 }
1792 }
1793
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 44 times.
50 if(offset) {
1794 6 emit_regmove(emit, -offset);
1795 6 const Instr args = emit_add_instr(emit, SporkCode);
1796 6 args->m_val = offset;
1797 }
1798
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 24 times.
50 (unary->unary_type == unary_code ? spork_code : spork_func)(emit, &sporker);
1799 50 return GW_OK;
1800 }
1801
1802 87 ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary *unary) {
1803 87 const Type t = exp_self(unary)->type;
1804 87 const Type base = actual_type(emit->gwion, t);
1805
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 87 times.
87 CHECK_BB(ensure_emit(emit, base));
1806 // no pos ?
1807 87 struct Op_Import opi = {.op = unary->op, .data = (uintptr_t)unary};
1808
4/4
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 24 times.
87 if (unary->unary_type == unary_exp && unary->op != insert_symbol("spork") &&
1809
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 unary->op != insert_symbol("fork")) {
1810
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 CHECK_BB(emit_exp_pop_next(emit, unary->exp));
1811 20 opi.rhs = unary->exp->type;
1812 }
1813 87 return op_emit(emit, &opi);
1814 }
1815
1816 25 ANN static m_bool emit_implicit_cast(const Emitter emit,
1817 const restrict Exp from,
1818 const restrict Type to) {
1819 25 const struct Implicit imp = { .e=from, .t=to, .pos=from->pos};
1820 // no pos
1821 25 struct Op_Import opi = {.op = insert_symbol("@implicit"),
1822 25 .lhs = from->type,
1823 .rhs = to,
1824 25 .data = (m_uint)&imp};
1825 25 return op_emit(emit, &opi);
1826 }
1827
1828 78 ANN2(1,2) static Instr _flow(const Emitter emit, const Exp e, Instr *const instr, /*const */bool b) {
1829
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
78 CHECK_BO(emit_exp_pop_next(emit, e));
1830 {
1831 78 const Instr ex = (Instr)vector_back(&emit->code->instr);
1832
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
78 if(ex->opcode == eOP_MAX && ex->execute == fast_except) {
1833 vector_rem(&emit->code->instr, vector_size(&emit->code->instr) - 1);
1834 free_instr(emit->gwion, ex);
1835 }
1836 }
1837
1838
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 73 times.
78 if(instr)
1839 5 *instr = emit_add_instr(emit, NoOp);
1840 156 struct Op_Import opi = {
1841 78 .op = insert_symbol(b ? "@conditional" : "@unconditional"),
1842 78 .rhs = e->type,
1843 .pos = e->pos,
1844
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 13 times.
78 .data = (uintptr_t)e};
1845
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
78 CHECK_BO(op_emit(emit, &opi));
1846 78 return (Instr)vector_back(&emit->code->instr);
1847 }
1848 #define emit_flow(emit, b) _flow(emit, b, NULL, true)
1849
1850 static void emit_maybe_stack(const Emitter emit, const Instr instr, const MaybeVal *mv) {
1851 instr->opcode = eReg2Mem;
1852 instr->m_val = -SZ_INT;
1853 instr->m_val2 = mv->reg;
1854 if(!emit->code->frame->maybe_stack)
1855 emit->code->frame->maybe_stack = new_mp_vector(emit->gwion->mp, MaybeVal, 0);
1856 mp_vector_add(emit->gwion->mp, &emit->code->frame->maybe_stack, MaybeVal, *mv);
1857 }
1858
1859 5 ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If *exp_if) {
1860
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 const Exp e = exp_if->if_exp ?: exp_if->cond;
1861 Instr instr;
1862 5 struct M_Vector_ v = {};
1863 5 const m_uint reg = emit_local(emit, emit->gwion->type[et_bool]);
1864
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 DECL_OB(const Instr, op, = _flow(emit, exp_if->cond, &instr, true));
1865
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (exp_getvar(exp_self(exp_if))) {
1866 exp_setvar(e, 1);
1867 exp_setvar(exp_if->else_exp, 1);
1868 }
1869 5 const m_uint nloc = vector_size(&emit->code->frame->stack);
1870 5 const m_uint nval = m_vector_size(&emit->code->live_values);
1871 5 const uint16_t offset = emit->code->frame->curr_offset;
1872 5 const uint16_t vcount = emit->code->frame->value_count;
1873
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 CHECK_BB(emit_exp_pop_next(emit, e));
1874 5 const m_uint nval_if = m_vector_size(&emit->code->live_values);
1875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(nval < nval_if) {
1876 const m_uint diff = nval_if - nval;
1877 m_vector_init(&v, sizeof(VMValue), diff);
1878 memcpy(v.ptr + ARRAY_OFFSET, emit->code->live_values.ptr + ARRAY_OFFSET + nval * sizeof(VMValue), diff * sizeof(VMValue));
1879 }
1880 5 emit->code->frame->curr_offset = offset;
1881 5 emit->code->frame->value_count = vcount;
1882 5 VLEN(&emit->code->live_values) = nval;
1883 5 VLEN(&emit->code->frame->stack) = nloc;
1884
1885 5 const Instr op2 = emit_add_instr(emit, Goto);
1886 5 op->m_val = emit_code_size(emit);
1887 5 const m_bool ret = emit_exp_pop_next(emit, exp_if->else_exp);
1888 5 const m_uint nval_else = m_vector_size(&emit->code->live_values);
1889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(nval < nval_else) {
1890 const m_uint diff = nval_else - nval;
1891 if(!v.ptr) {
1892 m_vector_init(&v, sizeof(VMValue), diff);
1893 memcpy(v.ptr + ARRAY_OFFSET, emit->code->live_values.ptr + ARRAY_OFFSET + nval * sizeof(VMValue), diff * sizeof(VMValue));
1894 } else {
1895 for(m_uint i = 0; i < diff; i++) {
1896 m_vector_add(&v, m_vector_addr(&emit->code->live_values, i + nval));
1897 }
1898 }
1899 }
1900 5 emit->code->frame->curr_offset = offset;
1901 5 emit->code->frame->value_count = vcount;
1902 5 VLEN(&emit->code->live_values) = nval;
1903 5 VLEN(&emit->code->frame->stack) = nloc;
1904
1905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(v.ptr) {
1906 MaybeVal mv = (MaybeVal) {
1907 .ptr = v.ptr,
1908 .reg = reg,
1909 .limit = nval_if - nval,
1910 };
1911 emit_maybe_stack(emit, instr, &mv);
1912 }
1913 5 op2->m_val = emit_code_size(emit);
1914 5 return ret;
1915 }
1916
1917 17 ANN static m_bool emit_lambda(const Emitter emit, const Exp_Lambda *lambda) {
1918 17 const EmitterStatus status = emit->status;
1919 17 emit->status = (EmitterStatus){};
1920
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 CHECK_BB(emit_func_def(emit, lambda->def));
1921
3/4
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
20 if (vflag(lambda->def->base->func->value_ref, vflag_member) &&
1922 3 !exp_getvar(exp_self(lambda)))
1923 3 emit_add_instr(emit, RegPushMem);
1924 17 emit_pushimm(emit, (m_uint)lambda->def->base->func->code);
1925 17 emit->status = status;
1926 17 return GW_OK;
1927 }
1928
1929 17 ANN static m_bool emit_exp_lambda(const Emitter emit,
1930 const Exp_Lambda *lambda) {
1931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (!lambda->def->base->func) {
1932 exp_self(lambda)->type = emit->gwion->type[et_void];
1933 return GW_OK;
1934 }
1935 17 struct EnvSet es = {.env = emit->env,
1936 .data = emit,
1937 .func = (_exp_func)emit_cdef,
1938 17 .scope = emit->env->scope->depth,
1939 .flag = tflag_emit};
1940
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 CHECK_BB(envset_pushv(&es, lambda->def->base->func->value_ref));
1941 17 const m_bool ret = emit_lambda(emit, lambda);
1942 17 envset_pop(&es, lambda->owner);
1943 17 return ret;
1944 }
1945
1946 ANN static m_bool emit_exp_td(const Emitter emit, Type_Decl *td) {
1947 const Type base = exp_self(td)->type;
1948 if(!is_func(emit->gwion, base))
1949 emit_pushimm(emit, (m_uint)base);
1950 else {
1951 const Instr instr = emit_add_instr(emit, SetFunc);
1952 instr->m_val = (m_uint)base->info->func;
1953 }
1954 return GW_OK;
1955 }
1956
1957 DECL_EXP_FUNC(emit, m_bool, Emitter)
1958
1959 4572 ANN2(1) /*static */ m_bool emit_exp(const Emitter emit, /* const */ Exp e) {
1960 4572 Exp exp = e;
1961 do {
1962
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4657 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4657 if (emit->info->debug && emit->status.line < e->pos.first.line) {
1963 const Instr instr = emit_add_instr(emit, DebugLine);
1964 instr->m_val = emit->status.line = e->pos.first.line;
1965 }
1966
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4651 times.
4657 CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d));
1967
3/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 4626 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
4651 if (exp->cast_to) CHECK_BB(emit_implicit_cast(emit, exp, exp->cast_to));
1968
2/2
✓ Branch 0 taken 1232 times.
✓ Branch 1 taken 3419 times.
4651 if (isa(e->type, emit->gwion->type[et_object]) > 0 &&
1969
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1231 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1232 (e->cast_to ? isa(e->cast_to, emit->gwion->type[et_object]) > 0 : 1) &&
1970
6/6
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 1048 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 178 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 4 times.
1236 e->exp_type == ae_exp_decl && GET_FLAG(e->d.exp_decl.td, late) &&
1971
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
6 exp_getuse(e) && !exp_getvar(e) &&
1972
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 GET_FLAG(e->d.exp_decl.vd.value, late))
1973 1 emit_fast_except(emit, e->d.exp_decl.vd.value->from, e->pos);
1974
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 4566 times.
4651 } while ((exp = exp->next));
1975 4566 return GW_OK;
1976 }
1977
1978 ANN static m_bool emit_if_const(const Emitter emit, const Stmt_If stmt) {
1979 if (stmt->cond->d.prim.d.num) return emit_stmt(emit, stmt->if_body);
1980 return stmt->else_body ? emit_stmt(emit, stmt->else_body) : GW_OK;
1981 }
1982
1983 32 ANN static m_bool emit_if(const Emitter emit, const Stmt_If stmt) {
1984
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 13 times.
32 if (stmt->cond->exp_type == ae_exp_primary &&
1985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 stmt->cond->d.prim.prim_type == ae_prim_num)
1986 return emit_if_const(emit, stmt);
1987
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 DECL_OB(const Instr, op, = emit_flow(emit, stmt->cond));
1988
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 CHECK_BB(scoped_stmt(emit, stmt->if_body));
1989 32 const Instr op2 = emit_add_instr(emit, Goto);
1990 32 op->m_val = emit_code_size(emit);
1991
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
32 if (stmt->else_body) CHECK_BB(scoped_stmt(emit, stmt->else_body));
1992 32 op2->m_val = emit_code_size(emit);
1993 32 return GW_OK;
1994 }
1995
1996 32 ANN static m_bool emit_stmt_if(const Emitter emit, const Stmt_If stmt) {
1997 32 emit_push_scope(emit);
1998 32 const m_bool ret = emit_if(emit, stmt);
1999 32 emit_pop_scope(emit);
2000 32 return ret;
2001 }
2002
2003 134 ANN static m_bool emit_stmt_code(const Emitter emit, const Stmt_Code stmt) {
2004
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 133 times.
134 if(!stmt->stmt_list) return GW_OK;
2005 133 emit_push_scope(emit);
2006 133 ++emit->env->scope->depth;
2007 133 const m_bool ret = emit_stmt_list(emit, stmt->stmt_list);
2008 133 emit_pop_scope(emit);
2009 133 --emit->env->scope->depth;
2010 133 return ret;
2011 }
2012
2013 2 ANN static m_bool optimize_tail_call(const Emitter emit, const Exp_Call *e) {
2014
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (e->args) {
2015
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(emit_func_args(emit, e));
2016 2 const Func f = e->func->type->info->func;
2017 2 emit_regmove(emit, -f->def->stack_depth);
2018 2 emit_args(emit, f);
2019 }
2020 2 emit_add_instr(emit, Goto);
2021 2 return GW_OK;
2022 }
2023
2024 65 ANN static m_bool emit_stmt_return(const Emitter emit, const Stmt_Exp stmt) {
2025
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
65 CHECK_BB(emit_defers2(emit));
2026
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 2 times.
65 if (stmt->val) {
2027
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 54 times.
63 if (stmt->val->exp_type == ae_exp_call) {
2028 9 const Func f = stmt->val->d.exp_call.func->type->info->func;
2029
3/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 7 times.
9 if (stmt->val->exp_type == ae_exp_call && emit->env->func == f)
2030 2 return optimize_tail_call(emit, &stmt->val->d.exp_call);
2031 }
2032 // if(!stmt->val->ref && tflag(stmt->val->type, tflag_compound))
2033 // emit_local(emit, stmt->val->type);
2034 61 emit->status.in_return = true;
2035
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 61 times.
61 CHECK_BB(emit_exp_pop_next(emit, stmt->val));
2036 61 emit->status.in_return = false;
2037 }
2038 63 vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto));
2039 63 return GW_OK;
2040 }
2041
2042 2 ANN static inline m_bool emit_jump_index(const Emitter emit, const Vector v,
2043 const m_int n) {
2044 2 vector_add(v, 0); // make room
2045 2 const m_uint sz = vector_size(v);
2046 2 m_int idx = 1;
2047
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (m_uint i = sz; --i > 1;) {
2048
3/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 if (!vector_at(v, i) && ++idx == n) {
2049 1 m_uint *data = v->ptr + OFFSET + i;
2050 1 memmove(data + 1, data, (sz - i) * SZ_INT);
2051 1 const Instr instr = emit_add_instr(emit, Goto);
2052 1 VPTR(v, i - 1) = (m_uint)instr;
2053 1 return GW_OK;
2054 }
2055 }
2056 1 return GW_ERROR;
2057 }
2058
2059 20 ANN static inline m_bool emit_jump(const Emitter emit, const Stmt_Index stmt,
2060 const Vector v) {
2061
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 CHECK_BB(emit_defers2(emit));
2062
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 3 times.
20 if (stmt->idx == -1 || stmt->idx == 1)
2063 17 vector_add(v, (vtype)emit_add_instr(emit, Goto));
2064
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 else if (stmt->idx) {
2065
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (emit_jump_index(emit, v, stmt->idx) < 0)
2066 1 ERR_B(stmt_self(stmt)->pos, _("too many jumps required."))
2067 }
2068 19 return GW_OK;
2069 }
2070
2071 8 ANN static inline m_bool emit_stmt_continue(const Emitter emit,
2072 const Stmt_Index stmt) {
2073 8 return emit_jump(emit, stmt, &emit->code->stack_cont);
2074 }
2075 12 ANN static inline m_bool emit_stmt_break(const Emitter emit,
2076 const Stmt_Index stmt NUSED) {
2077 12 return emit_jump(emit, stmt, &emit->code->stack_break);
2078 }
2079
2080 53 ANN static inline void emit_push_stack(const Emitter emit) {
2081 53 emit_push_scope(emit);
2082 53 vector_add(&emit->code->stack_cont, (vtype)NULL);
2083 53 vector_add(&emit->code->stack_break, (vtype)NULL);
2084 53 }
2085
2086 106 ANN static void set_pcs(const Vector v, const m_uint pc) {
2087 m_uint i;
2088
1/2
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
124 for(i = vector_size(v) + 1; --i;) {
2089 124 Instr instr = (Instr)vector_at(v, i - 1);
2090
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 18 times.
124 if(!instr) break;
2091 18 instr->m_val = pc;
2092 }
2093 106 VLEN(v) = i - 1;
2094 106 }
2095
2096 53 ANN static void emit_pop_stack(const Emitter emit, const m_uint index) {
2097 53 set_pcs(&emit->code->stack_cont, index);
2098 53 set_pcs(&emit->code->stack_break, emit_code_size(emit));
2099 53 emit_pop_scope(emit);
2100 53 }
2101
2102 1 static INSTR(run_always) {
2103 1 shreduler_remove(shred->tick->shreduler, shred, 0);
2104 1 }
2105
2106 35 ANN static m_bool _emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt,
2107 const m_uint index) {
2108 35 Instr op = NULL;
2109 35 const bool is_while = stmt_self(stmt)->stmt_type == ae_stmt_while;
2110
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 14 times.
56 const bool is_const = stmt->cond->exp_type == ae_exp_primary &&
2111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 stmt->cond->d.prim.prim_type == ae_prim_num;
2112
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 14 times.
35 if (!stmt->is_do) {
2113
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (!is_const) {
2114
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 15 times.
21 if(is_while && !stmt->body->d.stmt_code.stmt_list &&
2115
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 stmt->cond->d.prim.prim_type == ae_prim_id &&
2116
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 !strcmp("true", s_name(stmt->cond->d.prim.d.var))) {
2117 1 (void)emit_add_instr(emit, run_always);
2118 }
2119 21 op = _flow(emit, stmt->cond, NULL, is_while);
2120 } else if ((!is_while && stmt->cond->d.prim.d.num) ||
2121 (is_while && !stmt->cond->d.prim.d.num))
2122 return GW_OK;
2123 }
2124
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 34 times.
35 CHECK_BB(scoped_stmt(emit, stmt->body));
2125
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 20 times.
34 if (stmt->is_do) {
2126
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (!is_const) {
2127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 CHECK_OB((op = _flow(emit, stmt->cond, NULL, !is_while)));
2128 14 op->m_val = index;
2129 } else if ((is_while && stmt->cond->d.prim.d.num) ||
2130 (!is_while && !stmt->cond->d.prim.d.num)) {
2131 const Instr goto_ = emit_add_instr(emit, Goto);
2132 goto_->m_val = index;
2133 }
2134 } else {
2135 20 const Instr goto_ = emit_add_instr(emit, Goto);
2136 20 goto_->m_val = index;
2137
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (op) op->m_val = emit_code_size(emit);
2138 }
2139 34 return GW_OK;
2140 }
2141
2142 35 ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
2143 35 const m_uint index = emit_code_size(emit);
2144 35 emit_push_stack(emit);
2145 35 const m_bool ret = _emit_stmt_flow(emit, stmt, index);
2146 35 emit_pop_stack(emit, index);
2147 35 return ret;
2148 }
2149
2150 4 ANN static m_bool _emit_stmt_for(const Emitter emit, const Stmt_For stmt,
2151 m_uint *action_index) {
2152
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_stmt(emit, stmt->c1));
2153 4 const m_uint index = emit_code_size(emit);
2154
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 DECL_OB(const Instr, op, = emit_flow(emit, stmt->c2->d.stmt_exp.val));
2155
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(scoped_stmt(emit, stmt->body));
2156 4 *action_index = emit_code_size(emit);
2157
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (stmt->c3) {
2158
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 CHECK_BB(emit_exp(emit, stmt->c3));
2159 4 pop_exp(emit, stmt->c3);
2160 }
2161 4 const Instr _goto = emit_add_instr(emit, Goto);
2162 4 _goto->m_val = index;
2163 4 op->m_val = emit_code_size(emit);
2164 4 return GW_OK;
2165 }
2166
2167 4 ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
2168 4 emit_push_stack(emit);
2169 4 m_uint action_index = 0;
2170 4 const m_bool ret = _emit_stmt_for(emit, stmt, &action_index);
2171 4 emit_pop_stack(emit, action_index);
2172 4 return ret;
2173 }
2174
2175 7 ANN static Instr each_op(const Emitter emit, const Looper *loop) {
2176 7 struct Op_Import opi = {
2177 7 .lhs = loop->exp->type,
2178 7 .op = insert_symbol("@each"),
2179 7 .data = (m_uint)loop
2180 };
2181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 CHECK_BO(op_emit(emit, &opi));
2182 7 return loop->instr;
2183 }
2184
2185 13 ANN static inline m_bool roll(const Emitter emit, Looper*const loop) {
2186 13 const Instr instr = loop->roll(emit, loop);
2187 // DECL_OB(const Instr, instr, = each_op(emit, loop)); // maybe check in check.c
2188
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 CHECK_BB(scoped_stmt(emit, loop->stmt));
2189 13 instr->m_val = emit_code_size(emit) + 1; // pass after goto
2190 13 return GW_OK;
2191 }
2192
2193 1 ANN static inline void unroll_init(const Emitter emit, const m_uint n) {
2194 1 emit_memsetimm(emit, emit_local(emit, emit->gwion->type[et_int]), n);
2195 1 }
2196
2197 2 ANN static inline m_bool unroll_run(const Emitter emit,
2198 struct Looper *loop) {
2199 2 const Instr instr = each_op(emit, loop);
2200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 CHECK_BB(scoped_stmt(emit, loop->stmt));
2201
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(instr)
2202 vector_add(&loop->unroll_v, (m_uint)instr);
2203 2 return GW_OK;
2204 }
2205
2206 1 ANN static m_bool _unroll(const Emitter emit, Looper *loop) {
2207 1 scoped_ini(emit);
2208 1 const Instr unroll = emit_add_instr(emit, Unroll);
2209 1 unroll->m_val = loop->offset;
2210 1 const m_uint start = emit_code_size(emit);
2211
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BB(unroll_run(emit, loop));
2212 1 const m_uint end = emit_code_size(emit);
2213
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 for (m_uint i = 1; i < loop->n; ++i) CHECK_BB(unroll_run(emit, loop));
2214 1 unroll->m_val2 = end - start;
2215 1 const Instr unroll2 = emit_add_instr(emit, VM_IN);
2216 1 unroll2->m_val = (m_uint)unroll;
2217 1 scoped_end(emit);
2218 1 return GW_OK;
2219 }
2220
2221 1 ANN static m_bool unroll(const Emitter emit, Looper *loop) {
2222
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(loop->unroll)
2223 1 vector_init(&loop->unroll_v);
2224 1 const m_bool ret = _unroll(emit, loop);
2225
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(loop->unroll) {
2226
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 for(m_uint i = 0; i < vector_size(&loop->unroll_v); i++) {
2227 2 const Instr instr = (Instr)vector_at(&loop->unroll_v, i);
2228 2 instr->m_val = emit_code_size(emit) + 1; // + 2 for arrays
2229 }
2230 1 vector_release(&loop->unroll_v);
2231 }
2232 1 return ret;
2233 }
2234
2235 14 ANN static inline m_bool looper_run(const Emitter emit,
2236 Looper *const loop) {
2237
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1 times.
14 return (!loop->n ? roll : unroll)(emit, loop);
2238 }
2239
2240 6 ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt,
2241 m_uint *end_pc) {
2242 6 const uint n = emit->status.unroll;
2243 6 const m_uint arr_offset = emit_local(emit, emit->gwion->type[et_int]); // array?
2244 const m_uint key_offset = /*!stmt->idx
2245 6 ? */emit_local(emit, emit->gwion->type[et_int])
2246 /*: emit_local(emit, stmt->idx->v->type)*/;
2247 6 const m_uint val_offset = emit_localn(emit, stmt->v->type); // localn ?
2248 6 emit_regtomem(emit, arr_offset, 0);
2249 6 emit_memsetimm(emit, key_offset, -1);
2250 6 stmt->v->from->offset = val_offset;
2251 //value_addref(stmt->v);
2252 6 _nspc_add_value(emit->env->curr, stmt->sym, stmt->v);
2253 6 emit_debug(emit, stmt->v);
2254
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (stmt->idx) {
2255 1 stmt->idx->v->from->offset = key_offset;
2256 1 _nspc_add_value(emit->env->curr, stmt->idx->sym, stmt->idx->v);
2257 //value_addref(stmt->idx->v);
2258 1 emit_debug(emit, stmt->idx->v);
2259 }
2260 6 struct Looper loop = {.exp = stmt->exp,
2261 6 .stmt = stmt->body,
2262 .offset = arr_offset,
2263 .n = n,
2264 .roll = each_op,
2265 .unroll = each_op,
2266 6 .idx = stmt->idx,
2267 .init = false
2268 };
2269
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (n) {
2270 1 loop.offset -= SZ_INT;
2271 1 struct Op_Import opi = {
2272 1 .lhs = loop.exp->type,
2273 1 .op = insert_symbol("@each_init"),
2274 1 .data = (m_uint)&loop
2275 };
2276
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BB(op_emit(emit, &opi));
2277 }
2278 6 const m_uint ini_pc = emit_code_size(emit);
2279
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 CHECK_BB(looper_run(emit, &loop));
2280 6 *end_pc = emit_code_size(emit);
2281 6 const Instr tgt = emit_add_instr(emit, Goto);
2282 6 tgt->m_val = ini_pc;
2283 6 return GW_OK;
2284 }
2285
2286 6 ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) {
2287 6 const uint n = emit->status.unroll;
2288 6 nspc_push_value(emit->gwion->mp, emit->env->curr);
2289
2290
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 CHECK_BB(emit_exp(emit, stmt->exp)); // add ref?
2291 6 emit_regmove(emit, -SZ_INT);
2292
2293
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (n) {
2294 1 unroll_init(emit, n);
2295 1 emit_local(emit, emit->gwion->type[et_int]);
2296 }
2297
2298 6 emit_push_stack(emit);
2299 6 m_uint end_pc = 0;
2300 6 const m_bool ret = _emit_stmt_each(emit, stmt, &end_pc);
2301 6 emit_pop_stack(emit, end_pc);
2302 6 nspc_pop_value(emit->gwion->mp, emit->env->curr);
2303 6 emit->status.unroll = 0;
2304 6 return ret;
2305 }
2306
2307 7 ANN static Instr stmt_loop_roll(const Emitter emit, const Looper *loop) {
2308 7 const Instr eq = emit_add_instr(emit, Repeat);
2309 7 eq->m_val2 = loop->offset;
2310 7 return eq;
2311 }
2312
2313 1 ANN static Instr stmt_loop_roll_idx(const Emitter emit,
2314 const Looper *loop) {
2315 1 const Instr instr = emit_add_instr(emit, RepeatIdx);
2316 1 instr->m_val2 = loop->offset;
2317 1 return instr;
2318 }
2319
2320 8 ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt,
2321 m_uint *index) {
2322 8 const uint n = emit->status.unroll;
2323
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (n) {
2324 unroll_init(emit, n);
2325 emit->status.unroll = 0;
2326 }
2327 8 const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
2328
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (stmt->idx) {
2329 1 emit_memsetimm(emit, emit_local(emit, emit->gwion->type[et_int]), 0);
2330 1 emit_memsetimm(emit, offset, -1);
2331 1 stmt->idx->v->from->offset = offset;
2332 }
2333
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(emit_exp_pop_next(emit, stmt->cond));
2334 8 emit_regmove(emit, -SZ_INT);
2335
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 emit_regtomem(emit, offset + !!stmt->idx * SZ_INT, 0);
2336 8 *index = emit_code_size(emit);
2337 8 struct Looper loop = {.exp = stmt->cond,
2338 8 .stmt = stmt->body,
2339 .offset = offset,
2340 .n = n,
2341 .roll =
2342
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 !stmt->idx ? stmt_loop_roll : stmt_loop_roll_idx};
2343
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(looper_run(emit, &loop));
2344 8 const Instr _goto = emit_add_instr(emit, Goto);
2345 8 _goto->m_val = *index;
2346 8 return GW_OK;
2347 }
2348
2349 8 ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
2350 8 emit_push_stack(emit);
2351 8 m_uint index = 0;
2352 8 const m_bool ret = _emit_stmt_loop(emit, stmt, &index);
2353 8 emit_pop_stack(emit, index);
2354 8 return ret;
2355 }
2356
2357 13 ANN static m_bool emit_type_def(const Emitter emit, const Type_Def tdef) {
2358
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
13 if (tdef->when_def) CHECK_BB(emit_func_def(emit, tdef->when_def));
2359
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 7 times.
13 if (tflag(tdef->type, tflag_cdef))
2360 6 return emit_class_def(emit, tdef->type->info->cdef);
2361 7 return GW_OK;
2362 }
2363
2364 6 ANN static m_bool emit_enum_def(const Emitter emit NUSED, const Enum_Def edef) {
2365 LOOP_OPTIM
2366
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 6 times.
22 for (m_uint i = 0; i < vector_size(&edef->values); ++i) {
2367 16 const Value v = (Value)vector_at(&edef->values, i);
2368 16 *(m_uint *)(v->from->owner->class_data + v->from->offset) = i;
2369 }
2370 6 set_tflag(edef->type, tflag_emit);
2371 6 return GW_OK;
2372 }
2373
2374 1 ANN static m_bool emit_union_def(const Emitter emit NUSED,
2375 const Union_Def udef) {
2376
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (tmpl_base(udef->tmpl)) return GW_OK;
2377 1 set_tflag(udef->type, tflag_emit);
2378 1 return GW_OK;
2379 }
2380
2381 // add a Goto. later the index is set to the ont of the happy path
2382 // maybe this and the function above can use the same machinery as returns or
2383 // breaks
2384 6 ANN static inline void emit_try_goto(const restrict Emitter emit,
2385 const Vector v) {
2386 6 const Instr instr = emit_add_instr(emit, Goto);
2387 6 vector_add(v, (m_uint)instr);
2388 6 }
2389
2390 // set Goto indexes the one of the happy path
2391 3 ANN static inline void try_goto_indexes(const Vector v, const m_uint pc) {
2392
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
9 for (m_uint i = 0; i < vector_size(v); i++) {
2393 6 const Instr instr = (Instr)vector_at(v, i);
2394 6 instr->m_val = pc;
2395 }
2396 3 }
2397
2398 3 ANN static inline m_bool emit_handler_list(const restrict Emitter emit,
2399 const Handler_List handlers,
2400 const Vector v) {
2401 3 emit_push_scope(emit);
2402 3 const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
2403
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 for(uint32_t i = 0; i < handlers->len; i++) {
2404 3 Handler *handler = mp_vector_at(handlers, Handler, i);
2405 3 const Instr instr = emit_add_instr(emit, HandleEffect);
2406 3 instr->m_val = emit->status.effect = offset;
2407 3 instr->m_val2 = (m_uint)handler->xid;
2408
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 CHECK_BB(scoped_stmt(emit, handler->stmt));
2409 3 emit_try_goto(emit, v);
2410 3 instr->m_val = emit_code_size(emit);
2411 }
2412 // emit->status.effect = 0;
2413 3 emit_pop_scope(emit);
2414 3 return GW_OK;
2415 }
2416
2417 3 ANN static inline m_bool emit_stmt_try(const restrict Emitter emit,
2418 const Stmt_Try stmt) {
2419 3 const m_uint top = emit->code->frame->try_top;
2420 3 emit->code->frame->try_top = emit_code_size(emit);
2421 3 (void)emit_add_instr(emit, TryIni);
2422 struct Vector_ v; // store Gotos to the happy path
2423 3 vector_init(&v);
2424
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 CHECK_BB(scoped_stmt(emit, stmt->stmt));
2425 3 emit_try_goto(emit, &v);
2426
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!emit->code->frame->handlers.ptr) map_init(&emit->code->frame->handlers);
2427
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 CHECK_BB(emit_handler_list(emit, stmt->handler, &v));
2428 3 try_goto_indexes(&v, emit_code_size(emit));
2429 3 vector_release(&v);
2430 3 emit->code->frame->try_top = top;
2431 3 (void)emit_add_instr(emit, TryEnd);
2432 3 return GW_OK;
2433 }
2434
2435 1576 ANN static m_bool emit_stmt_exp(const Emitter emit,
2436 const struct Stmt_Exp_ *exp) {
2437
2/2
✓ Branch 0 taken 1567 times.
✓ Branch 1 taken 9 times.
1576 return exp->val ? emit_exp(emit, exp->val) : GW_OK;
2438 }
2439
2440 8 ANN static m_bool emit_case_head(const Emitter emit, const Exp base,
2441 const Exp e, const Symbol op, const Vector v) {
2442
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(emit_exp1(emit, base));
2443
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(emit_exp1(emit, e));
2444 8 const Exp_Binary bin = {.lhs = base, .rhs = e, .op = op};
2445 8 struct Exp_ ebin = { .d = {.exp_binary = bin}, .exp_type = ae_exp_binary, .pos = e->pos };
2446 8 struct Op_Import opi = {.op = op,
2447 8 .lhs = base->type,
2448 8 .rhs = e->type,
2449 8 .data = (uintptr_t)&ebin.d.exp_binary,
2450 .pos = e->pos};
2451
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 CHECK_BB(op_emit(emit, &opi));
2452 8 const Instr instr = emit_add_instr(emit, BranchEqInt);
2453 8 vector_add(v, (vtype)instr);
2454 8 return GW_OK;
2455 }
2456
2457 10 ANN static m_bool emit_case_body(const Emitter emit,
2458 const struct Stmt_Match_ *stmt) {
2459
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 const Instr when = stmt->when ? emit_flow(emit, stmt->when) : NULL;
2460
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
10 if (stmt->when) CHECK_OB(when);
2461
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 CHECK_BB(emit_stmt_list(emit, stmt->list));
2462 10 const Instr instr = emit_add_instr(emit, Goto);
2463 10 vector_add(&emit->env->scope->match->vec, (vtype)instr);
2464
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (when) when->m_val = emit_code_size(emit);
2465 10 return GW_OK;
2466 }
2467
2468 1 ANN static m_bool case_value(const Emitter emit, const Exp base, const Exp e) {
2469 1 const Value v = e->d.prim.value;
2470 1 v->from->offset = emit_local(emit, base->type);
2471 1 emit_regtomem4(emit, v->from->offset, base->type->size);
2472 1 return GW_OK;
2473 }
2474
2475 ANN Symbol case_basic_op(const Env env, const Type base, const Exp e);
2476 #define CASE_PASS (Symbol)1
2477 10 ANN static Symbol case_op(const Emitter emit, const Exp base, const Exp e,
2478 const Vector vec, const uint n) {
2479
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (e->exp_type == ae_exp_primary) {
2480
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (e->d.prim.prim_type == ae_prim_id) {
2481
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (e->d.prim.d.var == insert_symbol("_")) return CASE_PASS;
2482
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!nspc_lookup_value1(emit->env->curr, e->d.prim.d.var)) {
2483
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!n) {
2484
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BO(emit_exp(emit, base));
2485 1 emit_regmove(emit, -base->type->size);
2486 }
2487
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BO(case_value(emit, base, e));
2488 1 return CASE_PASS;
2489 }
2490 }
2491 } else if (isa(base->type, emit->gwion->type[et_union]) > 0 &&
2492 e->exp_type == ae_exp_call) {
2493 const Exp func = e->d.exp_call.func;
2494 if (func->d.prim.prim_type == ae_prim_id) {
2495 const Map map = &base->type->nspc->info->value->map;
2496 for (m_uint i = 0; i < map_size(map); ++i) {
2497 if (VKEY(map, i) == (m_uint)func->d.prim.d.var) {
2498 const Value v = (Value)VVAL(map, i);
2499 if (v) {
2500 if (!n)
2501 CHECK_BO(emit_exp(emit, base));
2502 else
2503 emit_regmove(emit, SZ_INT);
2504 const Instr check = emit_add_instr(emit, UnionCheck);
2505 check->m_val2 = i;
2506 vector_add(vec, (m_uint)check);
2507 emit_unionmember(emit, i, v->type->size, false);
2508 emit_regmove(emit, -v->type->size);
2509 case_op(emit, e->d.exp_call.args, e->d.exp_call.args, vec, i + 1);
2510 return CASE_PASS;
2511 }
2512 }
2513 }
2514 }
2515 }
2516
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (!n) return case_basic_op(emit->env, base->type, e);
2517 emit_regmove(emit, SZ_INT);
2518 CHECK_BO(emit_exp(emit, e));
2519 const Exp_Binary bin = {.lhs = base, .rhs = e, .op = insert_symbol("?=")};
2520 struct Exp_ ebin = {.d = {.exp_binary = bin}, .pos = e->pos };
2521 struct Op_Import opi = {.op = insert_symbol("?="),
2522 .lhs = base->type,
2523 .rhs = e->type,
2524 .data = (uintptr_t)&ebin.d.exp_binary,
2525 .pos = e->pos};
2526 CHECK_BO(op_emit(emit, &opi));
2527 const Instr instr = emit_add_instr(emit, BranchEqInt);
2528 vector_add(vec, (vtype)instr);
2529 return CASE_PASS;
2530 }
2531
2532 10 ANN static m_bool _emit_stmt_match_case(const Emitter emit,
2533 const struct Stmt_Match_ *stmt,
2534 const Vector v) {
2535 10 Exp e = stmt->cond;
2536 10 const Vector cond = &emit->env->scope->match->cond;
2537
3/4
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
20 for (m_uint i = 0; i < vector_size(cond) && e; e = e->next, ++i) {
2538 10 const Exp base = (Exp)vector_at(cond, i);
2539 10 const Symbol op = case_op(emit, base, e, v, 0);
2540
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
10 if (op != CASE_PASS) CHECK_BB(emit_case_head(emit, base, e, op, v));
2541 }
2542
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 CHECK_BB(emit_case_body(emit, stmt));
2543 10 return GW_OK;
2544 }
2545
2546 10 ANN static m_bool emit_stmt_match_case(const Emitter emit,
2547 const struct Stmt_Match_ *stmt) {
2548 10 emit_push_scope(emit);
2549 struct Vector_ v;
2550 10 vector_init(&v);
2551 10 const m_bool ret = _emit_stmt_match_case(emit, stmt, &v);
2552 10 emit_pop_scope(emit);
2553
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
18 for (m_uint i = 0; i < vector_size(&v); ++i) {
2554 8 const Instr instr = (Instr)vector_at(&v, i);
2555 8 instr->m_val = emit_code_size(emit);
2556 }
2557 10 vector_release(&v);
2558 10 return ret;
2559 }
2560
2561 6 ANN static inline void match_unvec(struct Match_ *const match,
2562 const m_uint pc) {
2563 6 const Vector vec = &match->vec;
2564
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 6 times.
16 for (m_uint i = 0; i < vector_size(vec); ++i) {
2565 10 const Instr instr = (Instr)VPTR(vec, i);
2566 10 instr->m_val = pc;
2567 }
2568 6 vector_release(vec);
2569 6 }
2570
2571 6 ANN static m_bool emit_stmt_cases(const Emitter emit, Stmt_List list) {
2572
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 6 times.
16 for(m_uint i = 0; i < list->len; i++) {
2573 10 const Stmt stmt = mp_vector_at(list, struct Stmt_, i);
2574
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 CHECK_BB(emit_stmt_match_case(emit, &stmt->d.stmt_match));
2575 }
2576 6 return GW_OK;
2577 }
2578
2579 6 ANN static m_bool emit_match(const Emitter emit,
2580 const struct Stmt_Match_ *stmt) {
2581
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
6 if (stmt->where) CHECK_BB(emit_stmt(emit, stmt->where));
2582 6 MATCH_INI(emit->env->scope)
2583 6 vector_init(&m.vec);
2584 6 const m_bool ret = emit_stmt_cases(emit, stmt->list);
2585 6 match_unvec(&m, emit_code_size(emit));
2586 6 MATCH_END(emit->env->scope)
2587 6 return ret;
2588 }
2589
2590 6 ANN static m_bool emit_stmt_match(const Emitter emit,
2591 const struct Stmt_Match_ *stmt) {
2592 6 emit_push_scope(emit);
2593 6 const m_bool ret = emit_match(emit, stmt);
2594 6 emit_pop_scope(emit);
2595 6 return ret;
2596 }
2597
2598 6 ANN static m_bool emit_stmt_pp(const Emitter emit,
2599 const struct Stmt_PP_ *stmt) {
2600
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (stmt->pp_type == ae_pp_include)
2601 2 emit->env->name = stmt->data;
2602
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 else if (stmt->pp_type == ae_pp_locale)
2603 2 emit->locale = stmt->exp->d.exp_lambda.def->base->func;
2604
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (stmt->pp_type == ae_pp_pragma) {
2605
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!strncmp(stmt->data, "unroll", strlen("unroll")))
2606 1 emit->status.unroll = strtol(stmt->data + 6, NULL, 10);
2607 }
2608 6 return GW_OK;
2609 }
2610
2611 ANN static m_bool emit_stmt_defer(const Emitter emit,
2612 const struct Stmt_Defer_ *stmt) {
2613 vector_add(&emit->code->frame->defer, (m_uint)stmt->stmt);
2614 return GW_OK;
2615 }
2616
2617 1 ANN static m_bool emit_stmt_retry(const Emitter emit,
2618 const struct Stmt_Index_ *stmt NUSED) {
2619 1 const Instr instr = emit_add_instr(emit, Goto);
2620 1 instr->m_val = emit->code->frame->try_top + 1;
2621 1 return GW_OK;
2622 }
2623
2624 #define emit_stmt_while emit_stmt_flow
2625 #define emit_stmt_until emit_stmt_flow
2626 #define emit_stmt_spread dummy_func
2627
2628 DECL_STMT_FUNC(emit, m_bool, Emitter);
2629
2630 1896 ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt) {
2631
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1889 times.
1896 CHECK_BB(emit_stmt_func[stmt->stmt_type](emit, &stmt->d));
2632
4/4
✓ Branch 0 taken 1572 times.
✓ Branch 1 taken 317 times.
✓ Branch 2 taken 1563 times.
✓ Branch 3 taken 9 times.
1889 if (stmt->stmt_type == ae_stmt_exp && stmt->d.stmt_exp.val)
2633 1563 pop_exp(emit, stmt->d.stmt_exp.val);
2634 1889 return GW_OK;
2635 }
2636
2637 853 ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List l) {
2638
2/2
✓ Branch 0 taken 1791 times.
✓ Branch 1 taken 847 times.
2638 for(m_uint i = 0; i < l->len; i++) {
2639 1791 const Stmt stmt = mp_vector_at(l, struct Stmt_, i);
2640
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1785 times.
1791 CHECK_BB(emit_stmt(emit, stmt));
2641 }
2642 847 return GW_OK;
2643 }
2644
2645 399 ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot *member) {
2646 1197 struct Op_Import opi = {.op = insert_symbol("."),
2647 399 .lhs = member->base->type,
2648 399 .rhs = exp_self(member)->type,
2649 399 .data = (uintptr_t)member,
2650 399 .pos = exp_self(member)->pos};
2651 399 return op_emit(emit, &opi);
2652 }
2653
2654 348 ANN static inline void emit_func_def_init(const Emitter emit, const Func func) {
2655 348 emit_push_code(emit, func->name);
2656
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 343 times.
348 if(mp_vector_len(func->_wait)) {
2657 5 const Instr instr = emit_add_instr(emit, FuncWait);
2658 5 instr->m_val = (m_uint) func;
2659 }
2660 348 }
2661
2662 125 ANN static void emit_func_def_args(const Emitter emit, Arg_List args) {
2663
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 125 times.
297 for(uint32_t i = 0; i < args->len; i++) {
2664 172 Arg *arg = mp_vector_at(args, Arg, i);
2665 172 const Type type = arg->var_decl.value->type;
2666 172 emit->code->stack_depth += type->size;
2667 172 arg->var_decl.value->from->offset = emit_localn(emit, type);
2668 172 emit_debug(emit, arg->var_decl.value);
2669 172 _nspc_add_value(emit->env->curr, insert_symbol(arg->var_decl.value->name), arg->var_decl.value);
2670 }
2671 125 }
2672
2673 347 ANN static m_bool emit_func_def_return(const Emitter emit) {
2674 347 const m_uint val = emit_code_size(emit);
2675
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 347 times.
347 CHECK_BB(emit_defers(emit));
2676 347 emit_return_pc(emit, val);
2677 347 vector_clear(&emit->code->stack_return);
2678 347 const Func f = emit->env->func;
2679
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 346 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
347 if (f->memoize && fflag(f, fflag_pure)) {
2680 1 const Instr instr = emit_add_instr(emit, MemoizeStore);
2681 1 instr->m_val = f->def->stack_depth;
2682 }
2683 347 return GW_OK;
2684 }
2685
2686 7 ANN static VM_Code emit_internal(const Emitter emit, const Func f) {
2687
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (f->def->base->xid == insert_symbol("@dtor"))
2688 2 return emit->env->class_def->nspc->dtor = finalyze(emit, DTOR_EOC);
2689
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 else if (f->def->base->xid == insert_symbol("@gack")) {
2690 2 emit_regmove(emit, -SZ_INT - f->value_ref->from->owner_class->size);
2691 2 const Instr instr = emit_add_instr(emit, RegPushMem);
2692 2 instr->m_val = SZ_INT;
2693 2 f->code = finalyze(emit, FuncReturn);
2694 2 return emit->env->class_def->info->gack = f->code;
2695 }
2696 3 return finalyze(emit, FuncReturn);
2697 }
2698
2699 347 ANN static inline VM_Code _emit_func_def_code(const Emitter emit,
2700 const Func func) {
2701
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 332 times.
347 if(is_new(func->def)) {
2702 15 const Type t = func->value_ref->from->owner_class;
2703
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 8 times.
15 if(!tflag(t, tflag_struct))
2704 7 emit_add_instr(emit, RegPushMem);
2705 else {
2706 8 const Instr instr = emit_add_instr(emit, RegPushMemDeref);
2707 8 instr->m_val2 = t->size;
2708 }
2709 }
2710 687 const VM_Code code = !fbflag(func->def->base, fbflag_internal) ? finalyze(emit, FuncReturn)
2711
2/2
✓ Branch 0 taken 340 times.
✓ Branch 1 taken 7 times.
347 : emit_internal(emit, func);
2712 347 return code;
2713 }
2714
2715 347 ANN static VM_Code emit_func_def_code(const Emitter emit, const Func func) {
2716 347 const VM_Code code = _emit_func_def_code(emit, func);
2717
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 346 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
347 if (func->memoize && fflag(func, fflag_pure)) code->is_memoize = true;
2718 347 code->ret_type = func->def->base->ret_type;
2719 347 return code;
2720 }
2721
2722 348 ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
2723
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 346 times.
348 if (fdef->base->xid == insert_symbol("@dtor")) emit_local(emit, emit->gwion->type[et_int]);
2724
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 223 times.
348 if (fdef->base->args) emit_func_def_args(emit, fdef->base->args);
2725
2/2
✓ Branch 0 taken 344 times.
✓ Branch 1 taken 4 times.
348 if (fdef->d.code) {
2726
1/2
✓ Branch 0 taken 344 times.
✗ Branch 1 not taken.
344 if(!fdef->builtin) {
2727 344 const bool ctor = is_ctor(fdef);
2728
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 131 times.
344 if(!ctor)
2729 213 scoped_ini(emit);
2730 344 const m_bool ret = emit_stmt_list(emit, fdef->d.code);
2731
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 131 times.
344 if(!ctor)
2732 213 scoped_end(emit);
2733
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 343 times.
344 CHECK_BB(ret);
2734 }
2735 else fdef->base->func->code = (VM_Code)vector_at(&fdef->base->func->value_ref->from->owner_class->nspc->vtable, fdef->vt_index);
2736 }
2737 347 emit_func_def_return(emit);
2738 347 return GW_OK;
2739 }
2740
2741 1 ANN static Instr me_top(MemoizeEmitter *me) {
2742 1 emit_memsetimm(me->emit, me->offset, 0); // idx
2743 1 return emit_memsetimm(me->emit, me->offset + SZ_INT, 0); // pc
2744 }
2745
2746 1 ANN static void me_ini(MemoizeEmitter *me) {
2747 1 const Instr ini = emit_add_instr(me->emit, MemoizeIni);
2748 1 ini->m_val = me->offset;
2749 1 ini->m_val2 = me->fdef->stack_depth + me->fdef->base->ret_type->size;
2750 1 }
2751
2752 1 ANN static void me_end(MemoizeEmitter *me, const m_uint pc) {
2753
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 for (m_uint i = 0; i < vector_size(&me->branch); ++i)
2754 1 ((Instr)vector_at(&me->branch, i))->m_val = pc;
2755 1 }
2756
2757 1 ANN static void me_bottom(MemoizeEmitter *me, const m_uint pc) {
2758 1 emit_regpushmem4(me->emit, me->offset, 0);
2759 1 emit_add_instr(me->emit, int_pre_inc);
2760 1 emit_regmove(me->emit, -SZ_INT);
2761 1 const Instr loop = emit_add_instr(me->emit, Goto);
2762 1 loop->m_val = pc;
2763 1 }
2764
2765 1 ANN static void me_ret(MemoizeEmitter *me) {
2766 1 emit_regpushmem(me->emit, (me->offset + SZ_INT) * 2, me->fdef->base->ret_type->size, false);
2767 1 vector_add(&me->emit->code->stack_return, (vtype)emit_add_instr(me->emit, Goto));
2768 1 }
2769
2770 1 ANN static m_bool me_run(MemoizeEmitter *me, const m_uint pc) {
2771 1 me_ini(me);
2772
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (me->fdef->base->args) CHECK_BB(me_arg(me));
2773 1 me_ret(me);
2774 1 me_end(me, emit_code_size(me->emit));
2775 1 me_bottom(me, pc);
2776 1 return GW_OK;
2777 }
2778
2779 1 ANN static m_bool emit_memoize(const Emitter emit, const Func_Def fdef) {
2780 1 MemoizeEmitter me = {.emit = emit, .fdef = fdef, .offset = fdef->stack_depth};
2781 1 const Instr pc = me_top(&me);
2782 1 const m_uint top = emit_code_size(emit);
2783 1 vector_init(&me.branch);
2784 1 const m_bool ret = me_run(&me, top);
2785 1 vector_release(&me.branch);
2786 1 pc->m_val2 = emit_code_size(emit);
2787 1 return ret;
2788 }
2789
2790 348 ANN static m_bool emit_fdef(const Emitter emit, const Func_Def fdef) {
2791 348 const Func f = fdef->base->func;
2792
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 347 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
348 if (f->memoize && fflag(f, fflag_pure))
2793
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BB(emit_memoize(emit, fdef));
2794 348 nspc_push_value(emit->gwion->mp, emit->env->curr); // handle
2795 348 const m_bool ret = emit_func_def_body(emit, fdef);
2796 348 nspc_pop_value(emit->gwion->mp, emit->env->curr); // handle
2797 348 return ret;
2798 }
2799
2800 347 ANN static void emit_fdef_finish(const Emitter emit, const Func_Def fdef) {
2801 347 const Func func = fdef->base->func;
2802 347 func->code = emit_func_def_code(emit, func);
2803
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 346 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
347 if (func->memoize && fflag(func, fflag_pure))
2804 1 func->code->memoize = memoize_ini(emit, func);
2805 347 }
2806
2807 ANN static inline Capture* get_capture(const Emitter emit, const Capture_List captures, const uint32_t i) {
2808 Capture *const cap = mp_vector_at(captures, Capture, i);
2809 emit_localn(emit, cap->temp->type);
2810 return cap;
2811 }
2812
2813 ANN static void emit_lambda_capture(const Emitter emit, const Func_Def fdef) {
2814 for(uint32_t i = 0; i < fdef->captures->len - 1; i++)
2815 (void)get_capture(emit, fdef->captures, i);
2816 const Capture *cap = get_capture(emit, fdef->captures, fdef->captures->len - 1);
2817 const m_uint offset = cap->temp->from->offset + cap->temp->type->size - fdef->stack_depth;
2818 emit_regtomem4(emit, fdef->stack_depth, offset);
2819 }
2820
2821 384 ANN static m_bool _emit_func_def(const Emitter emit, const Func_Def f) {
2822
4/4
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 357 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 26 times.
384 if (tmpl_base(f->base->tmpl) && fbflag(f->base, fbflag_op)) return GW_OK;
2823 383 const Func func = f->base->func;
2824 383 const Func_Def fdef = func->def;
2825 383 const Func former = emit->env->func;
2826
6/6
✓ Branch 0 taken 377 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 351 times.
✓ Branch 4 taken 26 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 350 times.
383 if (func->code || tmpl_base(fdef->base->tmpl) || fflag(func, fflag_emit))
2827 33 return GW_OK;
2828 350 set_fflag(func, fflag_emit);
2829
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 348 times.
350 if(fdef->builtin) {
2830 2 fdef->base->func->code = new_vmcode(emit->gwion->mp, NULL, NULL, func->name, fdef->stack_depth, true, false);
2831 2 fdef->base->func->code->native_func = (m_uint)fdef->d.dl_func_ptr;
2832 2 return GW_OK;
2833 }
2834
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 348 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
348 if ((vflag(func->value_ref, vflag_builtin) &&
2835
3/4
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 311 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 37 times.
348 safe_tflag(emit->env->class_def, tflag_tmpl)) || (fdef->base->tmpl && is_new(f))) {
2836 const Func base =
2837 nspc_lookup_func1(func->value_ref->from->owner, f->base->xid);
2838 builtin_func(emit->gwion, func, (f_xfun)base->code->native_func);
2839 return GW_OK;
2840 }
2841 348 const uint global = GET_FLAG(f->base, global);
2842 348 const m_uint scope =
2843
2/2
✓ Branch 0 taken 347 times.
✓ Branch 1 taken 1 times.
348 !global ? emit->env->scope->depth : env_push_global(emit->env);
2844 348 emit_func_def_init(emit, func);
2845
2/2
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 134 times.
348 if (vflag(func->value_ref, vflag_member)) stack_alloc(emit);
2846 348 emit->env->func = func;
2847 348 emit_push_scope(emit);
2848
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 346 times.
348 if (!strcmp(s_name(fdef->base->xid), "@gack")) {
2849 2 emit_local(emit, emit->gwion->type[et_int]);
2850 2 emit_memsetimm(emit, SZ_INT, 0);
2851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 346 times.
346 } else if(fdef->captures) emit_lambda_capture(emit, fdef);
2852 348 const m_bool ret = scanx_fdef(emit->env, emit, fdef, (_exp_func)emit_fdef);
2853 348 emit_pop_scope(emit);
2854 348 emit->env->func = former;
2855
2/2
✓ Branch 0 taken 347 times.
✓ Branch 1 taken 1 times.
348 if (ret > 0)
2856 347 emit_fdef_finish(emit, fdef);
2857 else
2858 1 emit_pop_code(emit);
2859
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 347 times.
348 if (global) env_pop(emit->env, scope);
2860 348 return ret;
2861 }
2862
2863 384 ANN m_bool emit_func_def(const Emitter emit, const Func_Def fdef) {
2864 384 const uint16_t depth = emit->env->scope->depth;
2865 384 emit->env->scope->depth = 0;
2866 384 const Func locale = emit->locale;
2867 384 const m_bool ret = _emit_func_def(emit, fdef);
2868 384 emit->locale = locale;
2869 384 emit->env->scope->depth = depth;
2870 384 return ret;
2871 }
2872
2873 #define emit_fptr_def dummy_func
2874 #define emit_trait_def dummy_func
2875 #define emit_extend_def dummy_func
2876 #define emit_prim_def dummy_func
2877
2878 840 HANDLE_SECTION_FUNC(emit, m_bool, Emitter);
2879
2880 350 ANN static inline m_bool emit_ast_inner(const Emitter emit, Ast ast) {
2881
2/2
✓ Branch 0 taken 597 times.
✓ Branch 1 taken 345 times.
942 for(m_uint i = 0; i < ast->len; i++) {
2882 597 Section * section = mp_vector_at(ast, Section, i);
2883
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 592 times.
597 CHECK_BB(emit_section(emit, section));
2884 }
2885 345 return emit_defers(emit);
2886 }
2887
2888 ANN Code *emit_class_code(const Emitter emit, const m_str name) {
2889 const m_uint len = strlen(name) + 7;
2890 char c[len];
2891 snprintf(c, len, "class %s", name);
2892 emit_push_code(emit, c);
2893 stack_alloc(emit);
2894 return emit->code;
2895 }
2896
2897 1 ANN static m_bool emit_parent(const Emitter emit, const Class_Def cdef) {
2898 1 const Type parent = cdef->base.type->info->parent;
2899 1 return ensure_emit(emit, parent);
2900 }
2901
2902 13 ANN /*static */ inline m_bool emit_cdef(const Emitter emit, const Type t) {
2903 13 return scanx_cdef(emit->env, emit, t, (_exp_func)emit_class_def,
2904 (_exp_func)emit_union_def);
2905 }
2906
2907 1 ANN static m_bool cdef_parent(const Emitter emit, const Class_Def cdef) {
2908 1 const bool tmpl = !!cdef->base.tmpl;
2909
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 if (tmpl) CHECK_BB(template_push_types(emit->env, cdef->base.tmpl));
2910 1 const m_bool ret = emit_parent(emit, cdef);
2911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (tmpl) nspc_pop_type(emit->gwion->mp, emit->env->curr);
2912 1 return ret;
2913 }
2914
2915 149 ANN static m_bool _emit_class_def(const Emitter emit, const Class_Def cdef) {
2916 149 const Type t = cdef->base.type;
2917 149 set_tflag(t, tflag_emit);
2918 149 const Class_Def c = t->info->cdef;
2919
5/6
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 126 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 22 times.
172 if (c->base.ext && t->info->parent->info->cdef &&
2920 23 !tflag(t->info->parent, tflag_emit)) // ?????
2921
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 CHECK_BB(cdef_parent(emit, c));
2922
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 17 times.
149 if (c->body)
2923 132 return scanx_body(emit->env, c, (_exp_func)emit_section, emit);
2924 17 return GW_OK;
2925 }
2926
2927 160 ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
2928
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 149 times.
160 if (tmpl_base(cdef->base.tmpl)) return GW_OK;
2929
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 149 times.
149 if (tflag(cdef->base.type, tflag_emit)) return GW_OK;
2930 149 const Func locale = emit->locale;
2931 149 const m_bool ret = _emit_class_def(emit, cdef);
2932 149 emit->locale = locale;
2933 149 return ret;
2934 }
2935
2936 5 ANN static inline void emit_free_code(const Emitter emit, Code *code) {
2937
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
5 if (vector_size(&code->instr)) free_code_instr(&code->instr, emit->gwion);
2938 5 free_code(emit->gwion->mp, code);
2939 5 }
2940
2941 5 ANN static VM_Code emit_free_stack(const Emitter emit) {
2942 LOOP_OPTIM
2943
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 for (m_uint i = vector_size(&emit->stack) + 1; --i;)
2944 emit_free_code(emit, (Code *)vector_at(&emit->stack, i - 1));
2945 5 vector_clear(&emit->stack);
2946 5 vector_clear(&emit->info->pure);
2947 5 emit_free_code(emit, emit->code);
2948 5 return NULL;
2949 }
2950
2951 350 ANN m_bool emit_ast(const Env env, Ast *ast) {
2952 350 const Emitter emit = env->gwion->emit;
2953 350 const Func locale = emit->locale;
2954 350 emit->code = new_code(emit, emit->env->name);
2955 350 emit_push_scope(emit);
2956 350 const m_bool ret = emit_ast_inner(emit, *ast);
2957 350 emit_pop_scope(emit);
2958
2/2
✓ Branch 0 taken 345 times.
✓ Branch 1 taken 5 times.
350 if (ret > 0)
2959 345 emit->info->code = finalyze(emit, EOC);
2960 else
2961 5 emit_free_stack(emit);
2962 350 emit->status = (EmitterStatus){};
2963 350 emit->locale = locale;
2964 350 return ret;
2965 }
2966