GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/emit/emit.c Lines: 1514 1561 97.0 %
Date: 2020-09-22 13:02:15 Branches: 671 864 77.7 %

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 "parser.h"
19
#include "specialid.h"
20
#include "vararg.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, ...) { env_err(emit->env, (a), (b), ## __VA_ARGS__); return GW_ERROR; }
27
#undef ERR_O
28
#define ERR_O(a, b, ...) { env_err(emit->env, (a), (b), ## __VA_ARGS__); return NULL; }
29
30
typedef struct Local_ {
31
  Type type;
32
  m_uint offset;
33
} Local;
34
35
77
static inline void emit_pop(const Emitter emit, const m_uint scope) { env_pop(emit->env, scope); }
36
60
static inline m_uint emit_push(const Emitter emit, const Type type, const Nspc nspc) {
37
60
  return env_push(emit->env, type, nspc);
38
}
39
10
static inline m_uint emit_push_type(const Emitter emit, const Type type) {
40
10
  return env_push_type(emit->env, type);
41
}
42
6
static inline m_uint emit_push_global(const Emitter emit) {
43
6
  return env_push_global(emit->env);
44
}
45
46
860
ANEW static Frame* new_frame(MemPool p) {
47
860
  Frame* frame = mp_calloc(p, Frame);
48
860
  vector_init(&frame->stack);
49
860
  vector_add(&frame->stack, (vtype)NULL);
50
860
  return frame;
51
}
52
53
860
ANN static void free_frame(MemPool p, Frame* a) {
54
  LOOP_OPTIM
55
2828
  for(vtype i = vector_size(&a->stack) + 1; --i;)
56
1108
    if(vector_at(&a->stack, i - 1))
57
248
      mp_free(p, Local, (Local*)vector_at(&a->stack, i - 1));
58
860
  vector_release(&a->stack);
59
860
  mp_free(p, Frame, a);
60
860
}
61
62
1094
ANN static Local* new_local(MemPool p, const Type type) {
63
1094
  Local* local  = mp_calloc(p, Local);
64
1094
  local->type   = type;
65
1094
  return local;
66
}
67
68
1094
ANN static m_uint frame_local(MemPool p, Frame* frame, const Type t) {
69
1094
  Local* local = new_local(p, t);
70
1094
  local->offset = frame->curr_offset;
71
1094
  frame->curr_offset += t->size;
72
1094
  vector_add(&frame->stack, (vtype)local);
73
1094
  return local->offset;
74
}
75
76
1140
ANN static inline void frame_push(Frame* frame) {
77
1140
  vector_add(&frame->stack, (vtype)NULL);
78
1140
}
79
80
7
ANN static void struct_pop(const Emitter emit, const Type type, const m_uint offset) {
81
7
  if(!type->e->tuple)
82
    return;
83
19
  for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) {
84
12
    const Type t = (Type)vector_at(&type->e->tuple->types, i);
85
12
    if(isa(t, emit->gwion->type[et_object]) > 0) {
86
1
      const Instr instr = emit_add_instr(emit, ObjectRelease);
87
1
      instr->m_val = offset + vector_at(&type->e->tuple->offset, i);
88
11
    } else if(GET_FLAG(t, struct))
89
      struct_pop(emit, t, offset + vector_at(&type->e->tuple->offset, i));
90
  }
91
}
92
93
1986
ANN static m_int frame_pop(const Emitter emit) {
94
1986
  Frame *frame = emit->code->frame;
95
1986
  DECL_OB(const Local*, l, = (Local*)vector_pop(&frame->stack))
96
846
  frame->curr_offset -= l->type->size;
97
846
  if(GET_FLAG(l->type, struct)) {
98
7
    struct_pop(emit, l->type, l->offset);
99
7
    return frame_pop(emit);
100
  }
101
839
  return isa(l->type, emit->gwion->type[et_object]) > 0 ? (m_int)l->offset : frame_pop(emit);
102
}
103
104
ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp);
105
ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop);
106
ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list);
107
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member);
108
ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def);
109
110
860
ANEW static Code* new_code(const Emitter emit, const m_str name) {
111
860
  Code* code = mp_calloc(emit->gwion->mp, Code);
112
860
  code->name = code_name_set(emit->gwion->mp, name, emit->env->name);
113
860
  vector_init(&code->instr);
114
860
  vector_init(&code->stack_break);
115
860
  vector_init(&code->stack_cont);
116
860
  vector_init(&code->stack_return);
117
860
  code->frame = new_frame(emit->gwion->mp);
118
860
  return code;
119
}
120
121
860
ANN static void free_code(MemPool p, Code* code) {
122
860
  vector_release(&code->instr);
123
860
  vector_release(&code->stack_break);
124
860
  vector_release(&code->stack_cont);
125
860
  vector_release(&code->stack_return);
126
860
  free_frame(p, code->frame);
127
860
  free_mstr(p, code->name);
128
860
  mp_free(p, Code, code);
129
860
}
130
131
1140
ANN static void emit_pop_scope(const Emitter emit) {
132
  m_int offset;
133
2556
  while((offset = frame_pop(emit)) > -1) {
134
276
    Instr instr = emit_add_instr(emit, ObjectRelease);
135
276
    instr->m_val = (m_uint)offset;
136
  }
137
1140
  vector_pop(&emit->info->pure);
138
1140
}
139
140
442
ANN static inline void emit_push_code(const Emitter emit, const m_str name) {
141
442
  vector_add(&emit->stack, (vtype)emit->code);
142
442
  emit->code = new_code(emit, name);
143
442
}
144
145
ANN static inline void emit_pop_code(const Emitter emit) {
146
  emit->code = (Code*)vector_pop(&emit->stack);
147
}
148
149
1140
ANN static inline void emit_push_scope(const Emitter emit) {
150
1140
  frame_push(emit->code->frame);
151
1140
  vector_add(&emit->info->pure, 0);
152
1140
}
153
154
566
ANN static inline m_uint emit_code_size(const Emitter emit) {
155
566
  return vector_size(&emit->code->instr);
156
}
157
158
1751
ANN m_uint emit_code_offset(const Emitter emit) {
159
1751
  return emit->code->frame->curr_offset;
160
}
161
162
1094
ANN m_uint emit_local(const Emitter emit, const Type t) {
163
1094
  return frame_local(emit->gwion->mp, emit->code->frame, t);
164
}
165
166
ANN void emit_ext_ctor(const Emitter emit, const Type t);
167
168
653
ANN static inline void maybe_ctor(const Emitter emit, const Type t) {
169

653
  if(!is_special(t) && GET_FLAG(t, ctor))
170
160
    emit_ext_ctor(emit, t);
171
653
}
172
173
653
ANN static void emit_pre_ctor(const Emitter emit, const Type type) {
174
653
  if(type->e->parent)
175
445
    emit_pre_ctor(emit, type->e->parent);
176
653
  maybe_ctor(emit, type);
177

653
  if(GET_FLAG(type, typedef) && type->e->parent->array_depth)
178
7
    emit_array_extend(emit, type->e->parent, type->e->def->base.ext->array->exp);
179
653
}
180
181
#define regxxx(name, instr) \
182
ANN static inline Instr reg##name(const Emitter emit, const m_uint sz) { \
183
  const Instr instr = emit_add_instr(emit, Reg##instr); \
184
  instr->m_val = sz; \
185
  return instr; \
186
}
187
1916
regxxx(pop, Pop)
188
52
regxxx(push, Push)
189
1823
regxxx(pushi, PushImm)
190
3037
regxxx(seti, SetImm)
191
192
10
ANN static void struct_expand(const Emitter emit, const Type t) {
193
10
  const Instr instr = emit_add_instr(emit, Reg2RegDeref);
194
10
  instr->m_val = -SZ_INT;
195
10
  instr->m_val2 = t->size;
196
//  regpush(emit, t->size - SZ_INT);
197
10
}
198
199
200
INSTR(ArrayStruct);
201
202
12
ANN static void emit_pre_constructor_array(const Emitter emit, const Type type) {
203
12
  const m_uint start_index = emit_code_size(emit);
204
12
  const Instr top = emit_add_instr(emit, ArrayTop);
205
12
  top->m_val2 = (m_uint)type;
206
12
  if(GET_FLAG(type, struct)) {
207
    const Instr instr = emit_add_instr(emit, ArrayStruct);
208
    instr->m_val = type->size;
209
  }
210
12
  emit_pre_ctor(emit, type);
211
12
  if(!GET_FLAG(type, struct))
212
12
    emit_add_instr(emit, ArrayBottom);
213
  else
214
    regpop(emit, SZ_INT);
215
12
  regpop(emit, SZ_INT);
216
12
  const Instr pc = emit_add_instr(emit, Goto);
217
12
  pc->m_val = start_index;
218
12
  top->m_val = emit_code_size(emit);
219
12
  regpop(emit, SZ_INT*3);
220
12
  emit_add_instr(emit, ArrayPost);
221
12
}
222
223
38
ANN2(1) static m_bool extend_indices(const Emitter emit, Exp e, const m_uint depth) {
224
38
  if(e)
225
38
    CHECK_BB(emit_exp(emit, e))
226
38
  m_uint count = 0;
227
135
  while(e) {
228
59
    ++count;
229
59
    e = e->next;
230
  }
231
38
  for(m_uint i = count; i < depth; ++i)
232
    regpushi(emit, 0);
233
38
  return GW_OK;
234
}
235
236
38
ANEW ANN static ArrayInfo* new_arrayinfo(const Emitter emit, const Type t) {
237
38
  const Type base = array_base(t);
238
38
  ArrayInfo* info = mp_calloc(emit->gwion->mp, ArrayInfo);
239
38
  vector_init(&info->type);
240
59
  for(m_uint i = 1; i < t->array_depth; ++i)
241
21
    vector_add(&info->type, (vtype)array_type(emit->env, base, i));
242
38
  vector_add(&info->type, (vtype)t);
243
38
  info->depth = (m_int)t->array_depth;
244
38
  info->base = base;
245
38
  return info;
246
}
247
248
38
ANN static inline void arrayinfo_ctor(const Emitter emit, ArrayInfo *info) {
249
38
  const Type base = info->base;
250

38
  if(isa(base, emit->gwion->type[et_compound]) > 0 && !GET_FLAG(base, abstract)) {
251
12
    emit_pre_constructor_array(emit, base);
252
//  if(isa(base, emit->gwion->type[et_object]) > 0)
253
12
    info->is_obj = 1;
254
  }
255
38
}
256
257
38
ANN2(1,2) static ArrayInfo* emit_array_extend_inner(const Emitter emit, const Type t, const Exp e) {
258
38
  CHECK_BO(extend_indices(emit, e, t->array_depth))
259
38
  ArrayInfo* info = new_arrayinfo(emit, t);
260
38
  const Instr alloc = emit_add_instr(emit, ArrayAlloc);
261
38
  alloc->m_val = (m_uint)info;
262
38
  arrayinfo_ctor(emit, info);
263
38
  return info;
264
}
265
266
170
ANN void emit_ext_ctor(const Emitter emit, const Type t) {
267
170
  const Instr cpy = emit_add_instr(emit, Reg2Reg);
268
170
  cpy->m_val2 = -SZ_INT;
269
170
  if(t->nspc->pre_ctor) {
270
168
    const Instr set_code = regseti(emit, (m_uint)t->nspc->pre_ctor);
271
168
    set_code->m_val2 = SZ_INT;
272
  } else {
273
2
    const Instr instr = emit_add_instr(emit, SetCtor);
274
2
    instr->m_val = (m_uint)t;
275
  }
276
170
  const m_uint offset = emit_code_offset(emit);
277
170
  const Instr regset = regseti(emit, offset);
278
170
  regset->m_val2 = SZ_INT *2;
279
170
  const Instr push = emit_add_instr(emit, RegPush);
280
170
  push->m_val = SZ_INT *2;
281
170
  const Instr prelude = emit_add_instr(emit, SetCode);
282
170
  prelude->m_val2 = 2;
283
170
  prelude->m_val = SZ_INT;
284
170
  emit_add_instr(emit, Reg2Mem);
285
170
  const Instr next = emit_add_instr(emit, Overflow);
286
170
  next->m_val2 = offset;
287
170
}
288
289
7
ANN m_bool emit_array_extend(const Emitter emit, const Type t, const Exp e) {
290
7
  CHECK_OB(emit_array_extend_inner(emit, t, e))
291
7
  emit_add_instr(emit, PopArrayClass);
292
7
  emit_add_instr(emit, RegAddRef);
293
7
  return GW_OK;
294
}
295
296
239
ANN static inline void emit_notpure(const Emitter emit) {
297
239
  ++VPTR(&emit->info->pure, VLEN(&emit->info->pure) - 1);
298
239
}
299
300
227
ANN2(1,2) m_bool emit_instantiate_object(const Emitter emit, const Type type,
301
      const Array_Sub array, const m_bool is_ref) {
302
227
  emit_notpure(emit);
303
227
  if(type->array_depth) {
304
31
    ArrayInfo* info = emit_array_extend_inner(emit, type, array ? array->exp : NULL);
305
31
    if(info)
306
31
      info->is_ref = is_ref;
307
31
    return info ? GW_OK : GW_ERROR;
308
196
  } else if(!is_ref) {
309
196
    const Instr instr = emit_add_instr(emit, ObjectInstantiate);
310
196
    instr->m_val2 = (m_uint)type;
311
196
    emit_pre_ctor(emit, type);
312
  }
313
196
  return GW_OK;
314
}
315
316
2261
static inline enum Kind kindof(const m_uint size, const uint emit_var) {
317
2261
  if(emit_var)
318
476
    return KIND_ADDR;
319

1785
  return size == SZ_INT ? KIND_INT : size == SZ_FLOAT ? KIND_FLOAT : KIND_OTHER;
320
}
321
322
2261
ANN /*static */Instr emit_kind(Emitter emit, const m_uint size, const uint addr, const f_instr func[]) {
323
2261
  const enum Kind kind = kindof(size, addr);
324
2261
  const Instr instr = emit_add_instr(emit, func[kind]);
325
2261
  instr->m_val2 = size;
326
2261
  return instr;
327
}
328
329
static const f_instr regpushimm[] = { RegPushImm, RegPushImm2, RegPushImm3, RegPushImm4 };
330
static const f_instr regpushmem[] = { RegPushMem, RegPushMem2, RegPushMem3, RegPushMem4 };
331
static const f_instr regpushbase[] = { RegPushBase, RegPushBase2, RegPushBase3, RegPushBase4 };
332
static const f_instr dotstatic[]  = { DotStatic, DotStatic2, DotStatic3, RegPushImm };
333
static const f_instr allocmember[]  = { RegPushImm, RegPushImm2, RegPushImm3, AllocMember4 };
334
static const f_instr allocword[]  = { AllocWord, AllocWord2, AllocWord3, RegPushMem4 };
335
static const f_instr structmember[]  = { StructMember, StructMemberFloat, StructMemberOther, StructMemberAddr };
336
337
ANN Exp symbol_owned_exp(const Gwion gwion, const Symbol *data);
338
144
ANN static m_bool emit_symbol_owned(const Emitter emit, const Symbol *data) {
339
144
  const Exp dot = symbol_owned_exp(emit->gwion, data);
340
144
  dot->info->nspc = prim_exp(data)->info->nspc;
341
144
  const m_bool ret = emit_exp_dot(emit, &dot->d.exp_dot);
342
144
  free_exp(emit->gwion->mp, dot);
343
144
  return ret;
344
}
345
346
167
ANN static m_bool emit_symbol_builtin(const Emitter emit, const Symbol *data) {
347
167
  const Value v = prim_self(data)->value;
348
167
  if(GET_FLAG(v, union)) {
349
7
    const m_uint size = v->type->size;
350
7
    const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), dotstatic);
351
7
    instr->m_val = (m_uint)v->d.ptr;
352
  } else {
353
160
    const m_uint size = v->type->size;
354
160
    const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), regpushimm);
355

160
    if(!exp_getvar(prim_exp(data)) && size == SZ_INT) {
356
166
      if(isa(v->type, emit->gwion->type[et_object]) > 0)
357
34
        instr->m_val = (m_uint)v->d.ptr;
358
49
      else if(v->d.ptr)
359
34
        instr->m_val = *(m_uint*)v->d.ptr;
360
    } else {
361
      assert(v->d.ptr); // instr->m_val = v->d.ptr;
362
77
      memcpy(&instr->m_val, v->d.ptr, v->type->size);
363
    }
364
160
    instr->m_val2 = size;
365
  }
366
167
  return GW_OK;
367
}
368
369
1425
ANN static m_bool _emit_symbol(const Emitter emit, const Symbol *data) {
370
1425
  const Value v = prim_self(data)->value;
371
1425
  if(is_class(emit->gwion, v->type)) {
372
8
    regpushi(emit, (m_uint)actual_type(emit->gwion, v->type));
373
8
    return GW_OK;
374
  }
375
1417
  if(v->from->owner_class)
376
144
    return emit_symbol_owned(emit, data);
377

1273
  if(GET_FLAG(v, builtin) || GET_FLAG(v, union) || GET_FLAG(v, enum))
378
167
    return emit_symbol_builtin(emit, data);
379
1106
  const m_uint size = v->type->size;
380
1106
  const Instr instr = emit_kind(emit, size, exp_getvar(prim_exp(data)), !GET_FLAG(v, global) ? regpushmem : regpushbase);
381
1106
  instr->m_val  = v->from->offset;
382
1106
  return GW_OK;
383
}
384
385
1425
ANN static m_bool emit_symbol(const Emitter emit, const Exp_Primary* prim) {
386
1425
  return _emit_symbol(emit, &prim->d.var);
387
}
388
389
856
ANN static VM_Code finalyze(const Emitter emit, const f_instr exec) {
390
856
  emit_add_instr(emit, exec);
391
856
  const VM_Code code = emit->info->emit_code(emit);
392
856
  free_code(emit->gwion->mp, emit->code);
393
856
  emit->code = (Code*)vector_pop(&emit->stack);
394
856
  return code;
395
}
396
397
12
ANN static m_bool emit_prim_array(const Emitter emit, const Array_Sub *data) {
398
12
  Exp e = (*data)->exp;
399
12
  CHECK_BB(emit_exp(emit, e))
400
12
  m_uint count = 0;
401
39
  do ++count;
402
39
  while((e = e->next));
403
12
  const Type type = (*data)->type;
404
12
  regseti(emit, count);
405
12
  const Instr instr = emit_add_instr(emit, ArrayInit);
406
12
  instr->m_val = (m_uint)type;
407
12
  instr->m_val2 = type->array_depth == 1 ? array_base(type)->size : SZ_INT;
408
12
  emit_gc(emit, -SZ_INT);
409
12
  emit_notpure(emit);
410
12
  return GW_OK;
411
}
412
413
ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e);
414
415
9
ANN static m_bool emit_range(const Emitter emit, Range *range) {
416
9
  if(range->start)
417
8
    CHECK_BB(emit_exp_pop_next(emit, range->start))
418
  else
419
1
    regpushi(emit, 0);
420
9
  if(range->end)
421
7
    CHECK_BB(emit_exp_pop_next(emit, range->end))
422
  else
423
2
    regpushi(emit, -1);
424
9
  return GW_OK;
425
}
426
427
2
ANN static m_bool emit_prim_range(const Emitter emit, Range **data) {
428
2
  Range *range = *data;
429
2
  CHECK_BB(emit_range(emit, range))
430
2
  const Exp e = range->start ?: range->end;
431
2
  const Symbol sym = insert_symbol("@range");
432
6
  struct Op_Import opi = { .op=sym, .rhs=e->info->type,
433
4
    .pos=e->pos, .data=(uintptr_t)prim_exp(data), .op_type=op_exp };
434
2
  CHECK_OB(op_emit(emit, &opi))
435
2
  emit_gc(emit, -SZ_INT);
436
2
  return GW_OK;
437
}
438
439
25
ANN m_bool emit_array_access(const Emitter emit, struct ArrayAccessInfo *const info) {
440
25
  if(GET_FLAG(info->array.type, typedef)) {
441
    info->array.type = info->array.type->e->parent;
442
    return emit_array_access(emit, info);
443
  }
444
  // look mum no pos
445
50
  struct Op_Import opi = { .op=insert_symbol("@array"), .lhs=info->array.exp->info->type, .rhs=info->array.type,
446
25
    .data=(uintptr_t)info, .op_type=op_array };
447
25
  return op_emit(emit, &opi) != (Instr)GW_ERROR ? GW_OK : GW_ERROR;
448
}
449
450
25
ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array* array) {
451
25
  CHECK_BB(emit_exp(emit, array->base))
452
25
  const Exp e = exp_self(array);
453
25
  struct ArrayAccessInfo info = { *array->array, e->info->type, exp_getvar(e) };
454
25
  return emit_array_access(emit, &info);
455
}
456
457
7
ANN static m_bool emit_exp_slice(const Emitter emit, const Exp_Slice* range) {
458
7
  CHECK_BB(emit_exp(emit, range->base))
459
7
  CHECK_BB(emit_range(emit, range->range))
460
7
  const Symbol sym = insert_symbol("@slice");
461
7
  const Exp e = range->range->start ?: range->range->end;
462
21
  struct Op_Import opi = { .op=sym, .lhs=e->info->type, .rhs=range->base->info->type,
463
14
    .pos=e->pos, .data=(uintptr_t)exp_self(range), .op_type=op_exp };
464
7
  CHECK_OB(op_emit(emit, &opi))
465
7
  return GW_OK;
466
}
467
468
1803
ANN static m_bool emit_prim_id(const Emitter emit, const Symbol *data) {
469
1803
  struct SpecialId_ * spid = specialid_get(emit->gwion, *data);
470
1803
  if(spid)
471
378
    return specialid_instr(emit, spid, prim_self(data)) ? GW_OK : GW_ERROR;
472
1425
  return emit_symbol(emit, prim_self(data));
473
}
474
475
575
ANN static m_bool emit_prim_num(const Emitter emit, const m_uint *num) {
476
575
  regpushi(emit, *num);
477
575
  return GW_OK;
478
}
479
480
75
ANN static m_bool emit_prim_float(const Emitter emit, const m_float *fnum) {
481
75
  const Instr instr = emit_add_instr(emit, RegPushImm2);
482
75
  instr->f = *fnum;
483
75
  return GW_OK;
484
}
485
486
15
ANN static m_bool emit_prim_char(const Emitter emit, const m_str *str) {
487
15
  const char c = str2char(emit, *str, prim_pos(str));
488
15
  regpushi(emit, c);
489
15
  return GW_OK;
490
}
491
492
565
ANN static Instr emit_addref(const Emitter emit, const m_bool emit_var) {
493
565
  const f_instr exec = !emit_var ? RegAddRef : RegAddRefAddr;
494
565
  const Instr instr = emit_add_instr(emit, exec);
495
565
  instr->m_val = -SZ_INT;
496
565
  return instr;
497
}
498
499
305
ANN static m_bool emit_prim_str(const Emitter emit, const m_str *str) {
500
305
  char c[strlen(*str) + 1];
501
305
  if(strlen(*str)) {
502
299
    strcpy(c, *str);
503
299
    CHECK_BB(escape_str(emit, c, prim_pos(str)));
504
6
  } else c[0] = '\0';
505
303
  const Value v = prim_self(str)->value;
506
303
  const Symbol sym = insert_symbol(c);
507
303
  if(!v->d.ptr)
508
244
    v->d.ptr = (m_uint*)new_string2(emit->gwion, NULL, s_name(sym));
509
303
  regpushi(emit, (m_uint)v->d.ptr);
510
303
  emit_addref(emit, 0);
511
303
  return GW_OK;
512
}
513
514
#define emit_prim_nil     (void*)dummy_func
515
516
24
ANN static m_bool emit_prim_typeof(const Emitter emit, const Exp *exp) {
517
24
  const Exp e = *exp;
518
24
  if(!e->info->type->array_depth)
519
23
    regpushi(emit, (m_uint)(actual_type(emit->gwion, e->info->type)));
520
  else
521
1
    regpushi(emit, (m_uint)e->info->type);
522
24
  return GW_OK;
523
}
524
525
25
ANN static void interp_multi(const Emitter emit, const Exp e) {
526
25
  Var_Decl_List list = e->d.exp_decl.list;
527
25
  const int emit_var = exp_getvar(e);
528
25
  m_uint offset = 0;
529
50
  while((list = list->next))
530
    offset += !emit_var ? list->self->value->type->size : SZ_INT;
531
25
  if(offset)
532
    regpop(emit, offset);
533
25
}
534
535
1106
ANN static inline void interp_size(const Emitter emit, const Type t) {
536
1106
  const Instr instr = regseti(emit, t->size);
537
1106
  instr->m_val2 = SZ_INT;
538
1106
}
539
540
855
ANN static m_bool emit_interp(const Emitter emit, const Exp exp) {
541
855
  regpushi(emit, 0);
542
855
  Exp e = exp, next = NULL;
543
  do {
544
1108
    next = e->next;
545
1108
    e->next = NULL;
546
1108
    if(emit_exp(emit, e) < 0) {
547
2
      e->next = next;
548
2
      return GW_ERROR;
549
    }
550
1106
    if(e->exp_type == ae_exp_decl) // why only objects?
551
25
      interp_multi(emit, e);
552
1106
    regseti(emit, (m_uint)e->info->type);
553
1106
    interp_size(emit, e->info->type);
554
1106
    const m_bool isobj = isa(e->info->type, emit->gwion->type[et_object]) > 0;
555

1106
    if(isobj && !GET_FLAG(e->info->type, force))
556
483
      emit_add_instr(emit, GackType);
557
1106
    const Instr instr = emit_add_instr(emit, Gack);
558
1106
    instr->m_val = emit_code_offset(emit);
559
1106
  } while((e = e->next = next));
560
853
  return GW_OK;
561
}
562
563
852
ANN static m_bool emit_prim_hack(const Emitter emit, const Exp *exp) {
564
852
  CHECK_BB(emit_interp(emit, *exp))
565

850
  if(!(emit->env->func && emit->env->func->def->base->xid == insert_symbol("@gack")))
566
848
    emit_add_instr(emit, GackEnd);
567
  else {
568
2
    const Instr instr = emit_add_instr(emit, Reg2Mem);
569
2
    instr->m_val = SZ_INT;
570
2
    instr->m_val2 = -SZ_INT;
571
  }
572
850
  return GW_OK;
573
}
574
575
3
ANN static m_bool emit_prim_interp(const Emitter emit, const Exp *exp) {
576
3
  const Exp e = *exp;
577
3
  CHECK_BB(emit_interp(emit, e))
578
3
  const Instr instr = emit_add_instr(emit, GackEnd);
579
3
  instr->m_val = 1;
580
3
  return GW_OK;
581
}
582
583
DECL_PRIM_FUNC(emit, m_bool , Emitter);
584
3673
ANN static m_bool emit_prim(const Emitter emit, Exp_Primary *const prim) {
585
3673
  return emit_prim_func[prim->prim_type](emit, &prim->d);
586
}
587
588
21
ANN static m_bool emit_dot_static_data(const Emitter emit, const Value v, const uint emit_var) {
589
21
  const m_uint size = v->type->size;
590
21
  const Instr instr = emit_kind(emit, size, emit_var, dotstatic);
591
21
  instr->m_val = (m_uint)(v->from->owner->info->class_data + v->from->offset);
592
21
  instr->m_val2 = size;
593
21
  return GW_OK;
594
}
595
596
5
ANN static m_bool decl_static(const Emitter emit, const Var_Decl var_decl, const uint is_ref) {
597
5
  const Value v = var_decl->value;
598
5
  Code* code = emit->code;
599
5
  emit->code = (Code*)vector_back(&emit->stack);
600
5
  CHECK_BB(emit_instantiate_object(emit, v->type, var_decl->array, is_ref))
601
5
  CHECK_BB(emit_dot_static_data(emit, v, 1))
602
5
  emit_add_instr(emit, Assign);
603
5
  (void)emit_addref(emit, 0);
604
5
  regpop(emit, SZ_INT);
605
5
  emit->code = code;
606
5
  return GW_OK;
607
}
608
609
1083
ANN static inline int struct_ctor(const Value v) {
610

1083
  return GET_FLAG(v->type, struct) && v->type->nspc->pre_ctor;
611
}
612
613
10
ANN static void decl_expand(const Emitter emit, const Type t) {
614
10
  struct_expand(emit, t);
615
10
  regpush(emit, t->size - SZ_INT);
616
10
}
617
618
10
ANN static void emit_struct_decl_finish(const Emitter emit, const Type t, const uint emit_addr) {
619
10
  emit->code->frame->curr_offset += t->size + SZ_INT;
620
10
  emit_ext_ctor(emit, t);
621
10
  if(!emit_addr)
622
10
    decl_expand(emit, t);
623
10
  emit->code->frame->curr_offset -= t->size + SZ_INT;
624
10
}
625
626
16
ANN static m_bool emit_exp_decl_static(const Emitter emit, const Var_Decl var_decl, const uint is_ref, const uint emit_addr) {
627
16
  const Value v = var_decl->value;
628

16
  if(isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
629
5
    CHECK_BB(decl_static(emit, var_decl, 0))
630

16
  CHECK_BB(emit_dot_static_data(emit, v, !struct_ctor(v) ? emit_addr : 1))
631
16
  if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */)
632
1
    emit_struct_decl_finish(emit, v->type, emit_addr);
633
16
  return GW_OK;
634
}
635
636
22
ANN static Instr emit_struct_decl(const Emitter emit, const Value v, const m_bool emit_addr) {
637
22
  emit_add_instr(emit, RegPushMem);
638
22
  const Instr instr = emit_kind(emit, v->type->size, emit_addr, structmember);
639
22
  if(!emit_addr)
640
11
    regpush(emit, v->type->size - SZ_INT);
641
22
  return instr;
642
}
643
644
621
ANN static m_bool emit_exp_decl_non_static(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl,
645
  const uint is_ref, const uint emit_var) {
646
621
  const Value v = var_decl->value;
647
621
  const Type type = v->type;
648
621
  const Array_Sub array = var_decl->array;
649

621
  const m_bool is_array = (array && array->exp) /*|| GET_FLAG(decl->td, force)*/;
650
621
  const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
651

621
  const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1;
652


621
  if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref))
653
201
    CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
654
621
  f_instr *exec = (f_instr*)allocmember;
655
621
  if(!GET_FLAG(v, member)) {
656
501
    v->from->offset = emit_local(emit, type);
657
501
    exec = (f_instr*)(allocword);
658
501
    if(GET_FLAG(v, ref)) { // ref or emit_var ?
659
55
      const Instr clean = emit_add_instr(emit, MemSetImm);
660
55
      clean->m_val = v->from->offset;
661
    }
662
  }
663

1370
  const Instr instr = !(SAFE_FLAG(emit->env->class_def, struct) && !emit->env->scope->depth) ?
664

1220
    emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, exec) : emit_struct_decl(emit, v, !struct_ctor(v) ? emit_addr : 1);
665
621
  instr->m_val = v->from->offset;
666


822
  if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref)) {
667
201
    if(!emit_var)
668
201
      emit_add_instr(emit, Assign);
669
    else {
670
      regpop(emit, SZ_INT);
671
      const Instr instr = emit_add_instr(emit, Reg2Reg);
672
      instr->m_val = -SZ_INT;
673
    }
674
201
    const size_t missing_depth = type->array_depth - (array ? array->depth : 0);
675

201
    if(missing_depth && !GET_FLAG(decl->td, force)) {
676
      const Instr push = emit_add_instr(emit, Reg2Reg);
677
      push->m_val = -(missing_depth) * SZ_INT;
678
    }
679
420
  } else if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */)
680
8
    emit_struct_decl_finish(emit, v->type, emit_addr);
681
621
  return GW_OK;
682
}
683
684
6
ANN static m_bool emit_exp_decl_global(const Emitter emit, const Exp_Decl *decl, const Var_Decl var_decl,
685
  const uint is_ref, const uint emit_var) {
686
6
  const Value v = var_decl->value;
687
6
  const Type type = v->type;
688
6
  const Array_Sub array = var_decl->array;
689

6
  const m_bool is_array = array && array->exp;
690
6
  const m_bool is_obj = isa(type, emit->gwion->type[et_object]) > 0;
691

6
  const uint emit_addr = (!is_obj || (is_ref && !is_array)) ? emit_var : 1;
692


6
  if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref))
693
2
    CHECK_BB(emit_instantiate_object(emit, type, array, is_ref))
694
6
  const Instr instr = emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, dotstatic);
695
6
  v->d.ptr = mp_calloc2(emit->gwion->mp, v->type->size);
696
6
  SET_FLAG(v, union);
697
6
  instr->m_val = (m_uint)v->d.ptr;
698
6
  instr->m_val2 = v->type->size;
699


8
  if(is_obj && (is_array || !is_ref) && !GET_FLAG(v, ref)) {
700
2
    const Instr assign = emit_add_instr(emit, Assign);
701
2
    const size_t missing_depth = type->array_depth - (array ? array->depth : 0);
702

2
    if(missing_depth && !GET_FLAG(decl->td, force)) {
703
      const Instr push = emit_add_instr(emit, Reg2Reg);
704
      push->m_val = -(missing_depth) * SZ_INT;
705
    }
706
2
    assign->m_val = emit_var;
707
2
    (void)emit_addref(emit, emit_var);
708
4
  } else if(struct_ctor(v) /* && !GET_FLAG(decl->td, ref) */)
709
1
    emit_struct_decl_finish(emit, v->type, emit_addr);
710
6
  return GW_OK;
711
}
712
713
ANN static m_bool emit_class_def(const Emitter, const Class_Def);
714
ANN static m_bool emit_cdef(const Emitter, const Class_Def);
715
716
28
ANN static inline m_bool ensure_emit(const Emitter emit, const Type t) {
717
56
  struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
718
28
    .scope=emit->env->scope->depth, .flag=ae_flag_emit };
719
28
  return envset_run(&es, t);
720
}
721
722
635
ANN static m_bool emit_decl(const Emitter emit, const Exp_Decl* decl) {
723
635
  const m_bool global = GET_FLAG(decl->td, global);
724
635
  const uint var = exp_getvar(exp_self(decl));
725

635
  const uint ref = GET_FLAG(decl->td, ref) || type_ref(decl->type);
726
635
  Var_Decl_List list = decl->list;
727
  do {
728
643
    const uint r = GET_FLAG(list->self->value, ref) + ref;
729
643
    if(GET_FLAG(decl->td, static))
730
16
      CHECK_BB(emit_exp_decl_static(emit, list->self, r, var))
731
627
    else if(!global)
732
621
      CHECK_BB(emit_exp_decl_non_static(emit, decl, list->self, r, var))
733
    else
734
6
      CHECK_BB(emit_exp_decl_global(emit, decl, list->self, r, var))
735
643
  } while((list = list->next));
736
635
  return GW_OK;
737
}
738
739
635
ANN /*static */m_bool emit_exp_decl(const Emitter emit, const Exp_Decl* decl) {
740
635
  const Type t = get_type(decl->type);
741

635
  if(!GET_FLAG(t, emit) && t->e->def)
742
21
    CHECK_BB(ensure_emit(emit, t))
743
635
  const m_bool global = GET_FLAG(decl->td, global);
744
635
  const m_uint scope = !global ? emit->env->scope->depth : emit_push_global(emit);
745
635
  const m_bool ret = emit_decl(emit, decl);
746
635
  if(global)
747
6
    emit_pop(emit, scope);
748
635
  return ret;
749
}
750
751
24
ANN static m_uint vararg_size(const Exp_Call* exp_call, const Vector kinds) {
752
24
  Exp e = exp_call->args;
753
24
  Arg_List l = exp_call->m_func->def->base->args;
754
24
  m_uint size = 0;
755
102
  while(e) {
756
54
    if(!l) {
757
45
      size += e->info->type->size;
758
45
      vector_add(kinds, (vtype)e->info->type); // ->size
759
    } else
760
9
      l = l->next;
761
54
    e = e->next;
762
  }
763
24
  return size;
764
}
765
766
24
ANN static void emit_func_arg_vararg(const Emitter emit, const Exp_Call* exp_call) {
767
24
  const Instr instr = emit_add_instr(emit, VarargIni);
768
24
  const Vector kinds = new_vector(emit->gwion->mp);
769
24
  if((instr->m_val = vararg_size(exp_call, kinds)))
770
18
    instr->m_val2 = (m_uint)kinds;
771
  else
772
6
    free_vector(emit->gwion->mp, kinds);
773
24
}
774
775
ANN static inline m_uint exp_size(Exp e);
776
278
ANN static inline m_uint exp_totalsize(Exp e) {
777
278
  m_uint size = 0;
778
382
  do size += exp_size(e);
779
382
  while((e = e->next));
780
278
  return size;
781
}
782
ANN static /*inline */void emit_exp_addref1(const Emitter emit, Exp, const m_int size);
783
ANN static /*inline */void emit_exp_addref(const Emitter emit, Exp, const m_int size);
784
785
462
ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call* exp_call) {
786
462
  if(exp_call->args) {
787
235
    CHECK_BB(emit_exp(emit, exp_call->args))
788
235
    emit_exp_addref(emit, exp_call->args, -exp_totalsize(exp_call->args));
789
  }
790

462
  if(exp_call->m_func && GET_FLAG(exp_call->m_func->def->base, variadic))
791
24
    emit_func_arg_vararg(emit, exp_call);
792
462
  return GW_OK;
793
}
794
795
461
ANN static m_bool prepare_call(const Emitter emit, const Exp_Call* exp_call) {
796
461
  CHECK_BB(emit_func_args(emit, exp_call))
797
461
  return emit_exp(emit, exp_call->func);
798
}
799
800
434
ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call* exp_call) {
801
434
  CHECK_BB(prepare_call(emit, exp_call))
802
434
  if(exp_call->m_func)
803
434
    CHECK_OB(emit_exp_call1(emit, exp_call->m_func))
804
  else {
805
    struct Op_Import opi = { .op=insert_symbol("@ctor"), .rhs=exp_call->func->info->type->e->d.base_type,
806
      .data=(uintptr_t)exp_call, .pos=exp_self(exp_call)->pos, .op_type=op_exp };
807
    CHECK_OB(op_emit(emit, &opi))
808
  }
809
434
  const Exp e = exp_self(exp_call);
810
434
  if(exp_getvar(e)) {
811
2
    regpop(emit, exp_self(exp_call)->info->type->size - SZ_INT);
812
2
    const Instr instr = emit_add_instr(emit, Reg2RegAddr);
813
2
    instr->m_val = -SZ_INT;
814
2
    instr->m_val2 = -SZ_INT;
815

432
  } else if(!exp_call->m_func && GET_FLAG(e->info->type, struct))
816
    regpop(emit, SZ_INT);
817
434
  return GW_OK;
818
}
819
820
470
ANN static m_uint get_decl_size(Var_Decl_List a, uint emit_addr) {
821
470
  m_uint size = 0;
822
  do //if(GET_FLAG(a->self->value, used))
823
478
    size += !emit_addr ? a->self->value->type->size : SZ_INT;
824
478
  while((a = a->next));
825
470
  return size;
826
}
827
828
1996
ANN static m_uint pop_exp_size(Exp e) {
829
1996
  const uint emit_addr = exp_getvar(e);
830
1996
  m_uint size = 0;
831
  do { // account for emit_var ?
832
3992
    size += (e->exp_type == ae_exp_decl ?
833
1996
        get_decl_size(e->d.exp_decl.list, emit_addr) : e->info->type->size);
834
1996
  } while((e = e->next));
835
1996
  return size;
836
}
837
838
1996
ANN static inline void pop_exp(const Emitter emit, Exp e) {
839
1996
  const m_uint size = pop_exp_size(e);
840
1996
  if(size)
841
1804
   regpop(emit, size);
842
1996
}
843
844
1235
ANN static inline m_bool emit_exp_pop_next(const Emitter emit, Exp e) {
845
1235
  CHECK_BB(emit_exp(emit, e))
846
1235
  if(e->exp_type == ae_exp_decl) {
847
123
    Var_Decl_List list = e->d.exp_decl.list->next;
848
246
    while(list) {
849
      regpop(emit, !exp_getvar(e) ? list->self->value->type->size : SZ_INT);
850
      list = list->next;
851
    }
852
  }
853
1235
  if(e->next)
854
1
    pop_exp(emit, e->next);
855
1235
  return GW_OK;
856
}
857
858
1259
ANN static inline m_bool op_emit_bool(const Emitter emit, const struct Op_Import* opi) {
859
1259
  DECL_OB(const Instr, instr, = op_emit(emit, opi))
860
1259
  return GW_OK;
861
}
862
863
502
ANN static m_bool emit_exp_binary(const Emitter emit, const Exp_Binary* bin) {
864
502
  const Exp lhs = bin->lhs;
865
502
  const Exp rhs = bin->rhs;
866
1506
  struct Op_Import opi = { .op=bin->op, .lhs=lhs->info->type, .rhs=rhs->info->type,
867
1004
    .pos=exp_self(bin)->pos, .data=(uintptr_t)bin, .op_type=op_binary };
868
502
  CHECK_BB(emit_exp_pop_next(emit, lhs))
869
502
  CHECK_BB(emit_exp_pop_next(emit, rhs))
870
502
  const m_int size = exp_size(rhs);
871
502
  emit_exp_addref1(emit, lhs, -exp_size(lhs) - size);
872
502
  emit_exp_addref1(emit, rhs, -size);
873
502
  return op_emit_bool(emit, &opi);
874
}
875
876
32
ANN static m_bool emit_exp_cast(const Emitter emit, const Exp_Cast* cast) {
877
  // no pos ?
878
64
  struct Op_Import opi = { .op=insert_symbol("$"), .lhs=cast->exp->info->type, .rhs=exp_self(cast)->info->type,
879
32
    .data=(uintptr_t)cast, .op_type=op_cast};
880
32
  CHECK_BB(emit_exp(emit, cast->exp))
881
32
  (void)op_emit(emit, &opi);
882
32
  return GW_OK;
883
}
884
885
35
ANN static m_bool emit_exp_post(const Emitter emit, const Exp_Postfix* post) {
886
  // no pos ?
887
70
  struct Op_Import opi = { .op=post->op, .lhs=post->exp->info->type,
888
35
    .data=(uintptr_t)post, .op_type=op_postfix };
889
35
  CHECK_BB(emit_exp(emit, post->exp))
890
35
  emit_exp_addref(emit, post->exp, -exp_totalsize(post->exp));
891
35
  return op_emit_bool(emit, &opi);
892
}
893
894
23
ANN static inline m_bool traverse_emit_func_def(const Emitter emit, const Func_Def fdef) {
895
23
  if(!fdef->base->ret_type)
896
23
    CHECK_BB(traverse_func_def(emit->env, fdef))
897
20
  return emit_func_def(emit, fdef);
898
}
899
900
23
ANN m_bool traverse_dot_tmpl(const Emitter emit, const struct dottmpl_ *dt) {
901
23
  const m_uint scope = emit->env->scope->depth;
902
23
  struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
903
    .scope=scope, .flag=ae_flag_emit };
904
23
  CHECK_BB(envset_push(&es, dt->owner_class, dt->owner))
905
23
  (void)emit_push(emit, dt->owner_class, dt->owner);
906
23
  const m_bool ret = traverse_emit_func_def(emit, dt->def);
907
23
  if(es.run)
908
7
    envset_pop(&es, dt->owner_class);
909
23
  emit_pop(emit, scope);
910
23
  return ret;
911
}
912
913
190
static inline m_bool push_func_code(const Emitter emit, const Func f) {
914
190
  if(!vector_size(&emit->code->instr))
915
10
    return GW_OK;
916
180
  const Instr instr = (Instr)vector_back(&emit->code->instr);
917
180
  if(instr->opcode == eDotTmplVal) {
918
45
    size_t len = strlen(f->name);
919
45
    size_t sz = len - strlen(f->value_ref->from->owner_class->name);
920
45
    char c[sz + 1];
921
45
    memcpy(c, f->name, sz);
922
45
    c[sz] = '\0';
923
45
    struct dottmpl_ *dt = mp_calloc(emit->gwion->mp, dottmpl);
924
45
    dt->name = s_name(insert_symbol(c));
925
45
    dt->vt_index = f->def->base->tmpl->base;
926
45
    dt->tl = cpy_type_list(emit->gwion->mp, f->def->base->tmpl->call);
927
45
    dt->base = f->def;
928
45
    instr->opcode = eOP_MAX;
929
45
    instr->m_val = (m_uint)dt;
930
45
    instr->m_val2 = strlen(c);
931
45
    instr->execute = DotTmpl;
932
45
    return GW_OK;
933
  }
934
135
  instr->opcode = eRegPushImm;
935
135
  instr->m_val = (m_uint)f->code;
936
135
  return GW_OK;
937
}
938
939
37
ANN static m_bool emit_template_code(const Emitter emit, const Func f) {
940
37
  const Value v = f->value_ref;
941
37
  const size_t scope = emit->env->scope->depth;
942
37
  struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
943
    .scope=scope, .flag=ae_flag_emit };
944
37
  CHECK_BB(envset_push(&es, v->from->owner_class, v->from->owner))
945
37
  (void)emit_push(emit, v->from->owner_class, v->from->owner);
946
37
  const m_bool ret = emit_func_def(emit, f->def);
947
37
  if(es.run)
948
17
    envset_pop(&es, v->from->owner_class);
949
37
  emit_pop(emit, scope);
950
37
  return ret > 0 ? push_func_code(emit, f) : GW_ERROR;
951
}
952
953
22
ANN static void tmpl_prelude(const Emitter emit, const Func f) {
954
22
  struct dottmpl_ *dt = (struct dottmpl_*)mp_calloc(emit->gwion->mp, dottmpl);
955
22
  size_t len = strlen(f->name);
956
22
  size_t slen = strlen(f->value_ref->from->owner->name);
957
  assert(len > slen);
958
22
  size_t sz = len - slen;
959
22
  char c[sz + 1];
960
22
  memcpy(c, f->name, sz);
961
22
  c[sz] = '\0';
962
22
  dt->tl = cpy_type_list(emit->gwion->mp, f->def->base->tmpl->call);
963
22
  dt->name = s_name(insert_symbol(c));
964
22
  dt->vt_index = f->def->base->tmpl->base;
965
22
  dt->base = f->def;
966
22
  dt->owner = f->value_ref->from->owner;
967
22
  dt->owner_class = f->value_ref->from->owner_class;
968
22
  const Instr gtmpl = emit_add_instr(emit, GTmpl);
969
22
  gtmpl->m_val = (m_uint)dt;
970
22
  gtmpl->m_val2 = strlen(c);
971
22
}
972
973
475
ANN static Instr get_prelude(const Emitter emit, const Func f) {
974
475
  const Type t = actual_type(emit->gwion, f->value_ref->type);
975
475
  if(is_fptr(emit->gwion, t)) {
976
69
    emit_except(emit, t);
977
69
    if(f->def->base->tmpl)
978
22
      tmpl_prelude(emit, f);
979
  }
980
475
  const Instr instr = emit_add_instr(emit, SetCode);
981
475
  instr->m_val2 = 1;
982
475
  return instr;
983
}
984
985
249
ANN static void emit_args(const Emitter emit, const Func f) {
986
249
  const m_uint member = GET_FLAG(f, member) ? SZ_INT : 0;
987
249
  if((f->def->stack_depth - member) == SZ_INT) {
988
157
    const Instr instr = emit_add_instr(emit, Reg2Mem);
989
157
    instr->m_val = member;
990
  } else {
991
92
    const Instr instr = emit_add_instr(emit, Reg2Mem4);
992
92
    instr->m_val = member;
993
92
    instr->m_val2 = f->def->stack_depth - member;
994
  }
995
249
}
996
997
typedef struct {
998
  const Emitter  emit;
999
  const Func_Def fdef;
1000
  struct Vector_   branch;
1001
  const m_uint   offset;
1002
  m_uint         arg_offset;
1003
} MemoizeEmitter;
1004
1005
2
ANN static Instr me_push(const MemoizeEmitter *me, const m_uint sz) {
1006
2
  const Instr instr = emit_kind(me->emit, sz, 0, regpushmem);
1007
2
  instr->m_val  = me->arg_offset;
1008
2
  return instr;
1009
}
1010
1011
1
static m_bool me_cmp(MemoizeEmitter *me, const Arg_List arg) {
1012
1
  const Emitter emit = me->emit;
1013
1
  const Symbol sym = insert_symbol("==");
1014
1
  struct ExpInfo_ info = { .nspc=me->fdef->base->func->value_ref->from->owner };
1015
1
  struct Exp_ exp = { .info=&info };
1016
3
  struct Op_Import opi = { .op=sym, .lhs=arg->type, .rhs=arg->type,
1017
2
    .pos=me->fdef->pos, .data=(uintptr_t)&exp.d, .op_type=op_binary };
1018
1
  CHECK_BB(op_emit_bool(emit, &opi))
1019
1
  const Instr instr = emit_add_instr(emit, BranchEqInt);
1020
1
  vector_add(&me->branch, (vtype)instr);
1021
1
  return GW_OK;
1022
}
1023
1024
1
ANN static m_bool me_arg(MemoizeEmitter *me) {
1025
1
  Arg_List arg = me->fdef->base->args;
1026
  do {
1027
1
    const m_uint sz = arg->type->size;
1028
1
    (void)me_push(me, sz);
1029
1
    const Instr instr = me_push(me, sz);
1030
1
    instr->m_val  += me->offset + SZ_INT *2;
1031
1
    CHECK_BB(me_cmp(me, arg))
1032
1
    me->arg_offset += arg->type->size;
1033
1
  } while((arg = arg->next));
1034
1
  return GW_OK;
1035
}
1036
1037
475
ANN static Instr emit_call(const Emitter emit, const Func f) {
1038
475
  const Instr prelude = get_prelude(emit, f);
1039
475
  prelude->m_val = f->def->stack_depth;
1040
475
  const m_uint member = GET_FLAG(f, member) ? SZ_INT : 0;
1041
475
  if(member) {
1042
259
    const Instr instr = emit_add_instr(emit, Reg2Mem);
1043
259
    instr->m_val2 = f->def->stack_depth - SZ_INT;
1044
259
    ++prelude->m_val2;
1045
  }
1046
475
  if(f->def->stack_depth - member) {
1047
248
    emit_args(emit, f);
1048
248
    ++prelude->m_val2;
1049
  }
1050
475
  return emit_add_instr(emit, Overflow);
1051
}
1052
1053
475
ANN Instr emit_exp_call1(const Emitter emit, const Func f) {
1054

475
  if(!f->code || (GET_FLAG(f, ref) && !GET_FLAG(f, builtin))) {
1055

248
    if(GET_FLAG(f, template) && !is_fptr(emit->gwion, f->value_ref->type)) {
1056
82
      if(emit->env->func != f)
1057
37
        CHECK_BO(emit_template_code(emit, f))
1058
      else { // recursive function. (maybe should be used only for global funcs)
1059
8
        const Instr back = (Instr) vector_size(&emit->code->instr) ?
1060
4
            (Instr)vector_back(&emit->code->instr) : emit_add_instr(emit, RegPushImm);
1061
4
        back->opcode = eOP_MAX;
1062
4
        back->execute = SetRecurs;
1063
4
        back->m_val = 0;
1064
      }
1065


83
    } else if(emit->env->func != f && !f->value_ref->from->owner_class && !f->code && !is_fptr(emit->gwion, f->value_ref->type)) {
1066
1
      if(GET_FLAG(f->def->base, op)) {
1067
        const Instr back = (Instr)vector_back(&emit->code->instr);
1068
        back->m_val = (m_uint)f;
1069
      } else {
1070
// ensure env?
1071
1
        CHECK_BO(emit_func_def(emit, f->def))
1072
1
        const Instr instr = emit_add_instr(emit, RegSetImm);
1073
1
        instr->m_val = (m_uint)f->code;
1074
1
        instr->m_val2 = -SZ_INT;
1075
      }
1076
    }
1077

697
  } else if((f->value_ref->from->owner_class && GET_FLAG(f->value_ref->from->owner_class, struct)) ||
1078

598
        !f->value_ref->from->owner_class || (GET_FLAG(f, template) &&
1079
27
        !is_fptr(emit->gwion, f->value_ref->type)))
1080
153
    push_func_code(emit, f);
1081
198
  else if(vector_size(&emit->code->instr)) {
1082
187
    const Instr back = (Instr)vector_back(&emit->code->instr);
1083

187
    if((f_instr)(m_uint)back->opcode == DotFunc || (f_instr)(m_uint)back->opcode == DotStaticFunc)
1084
169
      back->m_val = f->vt_index;
1085
  }
1086

720
  if(vector_size(&emit->code->instr) && GET_FLAG(f, member) &&
1087
273
        is_fptr(emit->gwion, f->value_ref->type)) {
1088
28
    const Instr back = (Instr)vector_back(&emit->code->instr);
1089
28
    m_bit exec = back->opcode;
1090
28
    m_uint val = back->m_val;
1091
28
    m_uint val2 = back->m_val2;
1092
28
    back->opcode = eReg2Reg;
1093
28
    back->m_val2 = -SZ_INT;
1094
28
    regpush(emit, SZ_INT);
1095
28
    const Instr instr = emit_add_instr(emit, (f_instr)(m_uint)exec);
1096
28
    instr->m_val = val;
1097
28
    instr->m_val2 = val2;
1098

447
  } else if(f != emit->env->func && !f->code && !is_fptr(emit->gwion, f->value_ref->type)){
1099
    // not yet emitted static func
1100
2
    if(f->value_ref->from->owner_class) {
1101
4
      const Instr instr = vector_size(&emit->code->instr) ?
1102
2
        (Instr)vector_back(&emit->code->instr) : emit_add_instr(emit, SetFunc);
1103
2
      instr->opcode = eOP_MAX;
1104
2
      instr->execute = SetFunc;
1105
2
      instr->m_val = (m_uint)f;
1106
    } else {
1107
      const Instr instr = emit_add_instr(emit, SetFunc);
1108
      instr->m_val = (m_uint)f;
1109
    }
1110
  }
1111
475
  const m_uint offset = emit_code_offset(emit);
1112
475
  regseti(emit, offset);
1113
475
  const Instr instr = emit_call(emit, f);
1114
475
  instr->m_val = f->def->base->ret_type->size;
1115
475
  instr->m_val2 = offset;
1116
475
  return instr;
1117
}
1118
1119
24
ANN static void emit_exp_spork_finish(const Emitter emit, const m_uint depth) {
1120
24
  regpop(emit, depth);
1121
24
  const Instr spork = emit_add_instr(emit, SporkFunc);
1122
24
  spork->m_val = depth + SZ_INT;
1123
24
  spork->m_val2 = -SZ_INT;
1124
24
}
1125
1126
260
static inline void stack_alloc(const Emitter emit) { // maybe vararg could use t_vararg instead
1127
260
  emit_local(emit, emit->gwion->type[et_int]); // hiding the fact it is an object
1128
260
  emit->code->stack_depth += SZ_INT;
1129
260
}
1130
1131
248
static inline void stack_alloc_this(const Emitter emit) {
1132
248
  SET_FLAG(emit->code, member);
1133
248
  stack_alloc(emit);
1134
248
}
1135
1136
372
static m_bool scoped_stmt(const Emitter emit, const Stmt stmt, const m_bool pop) {
1137
372
  ++emit->env->scope->depth;
1138
372
  emit_push_scope(emit);
1139
372
  const Instr gc = emit_add_instr(emit, NoOp);
1140
372
  const m_bool ret = emit_stmt(emit, stmt, pop);
1141
372
  if(ret > 0) {
1142
372
    const m_bool pure = !vector_back(&emit->info->pure);
1143
372
    if(!pure) {
1144
8
      gc->opcode = eGcIni;
1145
8
      emit_add_instr(emit, GcEnd);
1146
    }
1147
  }
1148
372
  emit_pop_scope(emit);
1149
372
  --emit->env->scope->depth;
1150
372
  return ret;
1151
}
1152
1153
#define SPORK_FUNC_PREFIX "spork~func:%i"
1154
#define FORK_FUNC_PREFIX "fork~func:%i"
1155
#define SPORK_CODE_PREFIX "spork~code:%i"
1156
#define FORK_CODE_PREFIX  "fork~code:%i"
1157
1158
53
static void push_spork_code(const Emitter emit, const m_str prefix, const loc_t pos) {
1159
53
  char c[strlen(SPORK_FUNC_PREFIX) + num_digit(pos->first.line) + 1];
1160
53
  sprintf(c, prefix, pos->first.line);
1161
53
  emit_push_code(emit, c);
1162
53
}
1163
1164
27
ANN static m_bool call_spork_func(const Emitter emit, const Exp_Call *exp) {
1165
27
  if(GET_FLAG(exp->m_func, member))
1166
14
    SET_FLAG(emit->code, member);
1167
27
  return emit_exp_call1(emit, exp->m_func) ? GW_OK : GW_ERROR;
1168
}
1169
1170
struct Sporker {
1171
  const Stmt code;
1172
  const Exp  exp;
1173
  VM_Code vm_code;
1174
  const Type type;
1175
  const m_bool emit_var;
1176
  const m_bool is_spork;
1177
};
1178
1179
26
ANN static m_bool spork_prepare_code(const Emitter emit, const struct Sporker *sp) {
1180
26
  emit_add_instr(emit, RegPushImm);
1181
26
  push_spork_code(emit, sp->is_spork ? SPORK_CODE_PREFIX : FORK_CODE_PREFIX, sp->code->pos);
1182

26
  if(SAFE_FLAG(emit->env->func, member))
1183
2
    stack_alloc_this(emit);
1184
26
  return scoped_stmt(emit, sp->code, 0);
1185
}
1186
1187
27
ANN static m_bool spork_prepare_func(const Emitter emit, const struct Sporker *sp) {
1188
27
  push_spork_code(emit, sp->is_spork ? SPORK_FUNC_PREFIX : FORK_CODE_PREFIX, sp->exp->pos);
1189
27
  return call_spork_func(emit, &sp->exp->d.exp_call);
1190
}
1191
1192
53
ANN static VM_Code spork_prepare(const Emitter emit, const struct Sporker *sp) {
1193
53
  if(!sp->code)
1194
27
    CHECK_BO(prepare_call(emit, &sp->exp->d.exp_call))
1195

53
  if((sp->code ? spork_prepare_code : spork_prepare_func)(emit, sp) > 0)
1196
53
    return finalyze(emit, EOC);
1197
  emit_pop_code(emit);
1198
  return NULL;
1199
}
1200
1201
26
ANN void spork_code(const Emitter emit, const struct Sporker *sp) {
1202
26
  const Instr args = emit_add_instr(emit, SporkExp);
1203
26
  args->m_val = emit->code->stack_depth;
1204
26
  const Instr instr = emit_add_instr(emit, SporkEnd);
1205
26
  instr->m_val = sp->emit_var;
1206
26
}
1207
1208
27
ANN void spork_func(const Emitter emit, const struct Sporker *sp) {
1209
27
  const Func f = sp->exp->d.exp_call.m_func;
1210

30
  if(GET_FLAG(f, member) && is_fptr(emit->gwion, f->value_ref->type)) {
1211
3
    regpush(emit, SZ_INT*2);
1212
    // (re-)emit owner
1213
3
    if(sp->exp->d.exp_call.func->exp_type == ae_exp_dot)
1214
1
      emit_exp(emit, sp->exp->d.exp_call.func->d.exp_dot.base);
1215
    else {
1216
      assert(sp->exp->d.exp_call.func->exp_type == ae_exp_primary);
1217
2
      emit_add_instr(emit, RegPushMem);
1218
    }
1219
3
    regpop(emit, SZ_INT*3);
1220
3
    const m_uint depth = f->def->stack_depth;
1221
3
    regpop(emit, depth -SZ_INT);
1222
3
    const Instr spork = emit_add_instr(emit, SporkMemberFptr);
1223
3
    spork->m_val = depth;
1224
  } else
1225
24
    emit_exp_spork_finish(emit, f->def->stack_depth);
1226
27
  (void)emit_add_instr(emit, SporkEnd);
1227
27
}
1228
1229
53
ANN static Instr spork_ini(const Emitter emit, const struct Sporker *sp) {
1230
53
  if(sp->is_spork) {
1231
45
    const Instr instr = emit_add_instr(emit, SporkIni);
1232
45
    instr->m_val = (m_uint)sp->vm_code;
1233
45
    instr->m_val2 = sp->is_spork;
1234
45
    return instr;
1235
  }
1236
8
  regpushi(emit, (m_uint)sp->type);
1237
8
  const Func f = !sp->code ? sp->exp->d.exp_call.m_func : NULL;
1238
8
  const Instr instr = emit_add_instr(emit, ForkIni);
1239
8
  instr->m_val = (m_uint)sp->vm_code;
1240
8
  instr->m_val2 = f ? sp->type->size : 0;
1241
8
  return instr;
1242
}
1243
1244
53
ANN Instr emit_exp_spork(const Emitter emit, const Exp_Unary* unary) {
1245
318
  struct Sporker sporker = {
1246
53
    .exp=unary->exp,
1247
53
    .code=unary->code,
1248
53
    .type=exp_self(unary)->info->type,
1249
53
    .is_spork=(unary->op == insert_symbol("spork")),
1250
53
    .emit_var=exp_getvar(exp_self(unary))
1251
  };
1252
53
  CHECK_OO((sporker.vm_code = spork_prepare(emit, &sporker)))
1253
53
  const Instr ini = spork_ini(emit, &sporker);
1254
53
  (unary->code ? spork_code : spork_func)(emit, &sporker);
1255
53
  return ini;
1256
}
1257
1258
119
ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) {
1259
119
  const Type t = exp_self(unary)->info->type;
1260
119
  const Type base = get_type(actual_type(emit->gwion, t));
1261

119
  if(base->e->def && !GET_FLAG(base, emit))
1262
1
    CHECK_BB(ensure_emit(emit, base))
1263
  // no pos ?
1264
119
  struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary, .op_type=op_unary };
1265

119
  if(unary->op != insert_symbol("spork") && unary->op != insert_symbol("fork") && unary->exp) {
1266
47
    CHECK_BB(emit_exp_pop_next(emit, unary->exp))
1267
47
    emit_exp_addref1(emit, unary->exp, -exp_size(unary->exp));
1268
47
    opi.rhs = unary->exp->info->type;
1269
  }
1270
119
  return op_emit_bool(emit, &opi);
1271
}
1272
1273
39
ANN static m_bool emit_implicit_cast(const Emitter emit,
1274
    const restrict Exp  from, const restrict Type to) {
1275
39
  const struct Implicit imp = { from, to, from->pos };
1276
  // no pos
1277
78
  struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=from->info->type, .rhs=to,
1278
39
    .data=(m_uint)&imp, .op_type=op_implicit };
1279
39
  return op_emit_bool(emit, &opi);
1280
}
1281
1282
85
ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) {
1283
85
  CHECK_BO(emit_exp_pop_next(emit, e))
1284
85
  emit_exp_addref1(emit, e, -exp_size(e));
1285
340
  struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"),
1286
255
                           .rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp };
1287
85
  const Instr instr = op_emit(emit, &opi);
1288
  assert(instr != (Instr)GW_OK);
1289
85
  return instr;
1290
}
1291
#define emit_flow(emit,b) _flow(emit, b, 1)
1292
1293
7
ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) {
1294
7
  DECL_OB(const Instr, op, = emit_flow(emit, exp_if->cond))
1295

7
  CHECK_BB(emit_exp_pop_next(emit, exp_if->if_exp ?: exp_if->cond))
1296
7
  const Instr op2 = emit_add_instr(emit, Goto);
1297
7
  op->m_val = emit_code_size(emit);
1298
7
  const m_bool ret = emit_exp_pop_next(emit, exp_if->else_exp);
1299
7
  op2->m_val = emit_code_size(emit);
1300
7
  return ret;
1301
}
1302
1303
13
ANN static m_bool emit_lambda(const Emitter emit, const Exp_Lambda * lambda) {
1304
13
  CHECK_BB(emit_func_def(emit, lambda->def))
1305

13
  if(GET_FLAG(lambda->def->base, member) && !exp_getvar(exp_self(lambda)))
1306
7
    emit_add_instr(emit, RegPushMem);
1307
13
  regpushi(emit, (m_uint)lambda->def->base->func->code);
1308
13
  return GW_OK;
1309
}
1310
1311
14
ANN static m_bool emit_exp_lambda(const Emitter emit, const Exp_Lambda * lambda) {
1312
14
  if(!lambda->def->base->func) {
1313
1
    regpushi(emit, SZ_INT);
1314
1
    return GW_OK;
1315
  }
1316
26
  struct EnvSet es = { .env=emit->env, .data=emit, .func=(_exp_func)emit_cdef,
1317
13
    .scope=emit->env->scope->depth, .flag=ae_flag_emit };
1318
13
  CHECK_BB(envset_push(&es, lambda->owner, lambda->def->base->func->value_ref->from->owner))
1319
13
  const m_bool ret = emit_lambda(emit, lambda);
1320
13
  if(es.run)
1321
5
    envset_pop(&es, lambda->owner);
1322
13
  return ret;
1323
}
1324
1325
DECL_EXP_FUNC(emit, m_bool, Emitter)
1326
1327
1328
1
ANN static void struct_addref(const Emitter emit, const Type type,
1329
    const m_int size, const m_bool offset, const m_bool emit_var) {
1330
1
  if(!type->e->tuple)
1331
1
    return;
1332
  for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) {
1333
    const Type t = (Type)vector_at(&type->e->tuple->types, i);
1334
    if(isa(t, emit->gwion->type[et_object]) > 0) {
1335
      const Instr instr = emit_addref(emit, emit_var);
1336
      instr->m_val = size;
1337
      instr->m_val2 = vector_at(&type->e->tuple->offset, i);
1338
    } else if(GET_FLAG(t, struct))
1339
      struct_addref(emit, t, size, offset + vector_at(&type->e->tuple->offset, i), emit_var);
1340
  }
1341
}
1342
1343
1907
ANN static inline m_uint exp_size(const Exp e) {
1344
1907
  if(exp_getvar(e))
1345
356
    return SZ_INT;
1346
1551
  const Type type = e->info->cast_to ?: e->info->type;
1347
1551
  return type->size;
1348
}
1349
1350
1525
ANN2(1) static void emit_exp_addref1(const Emitter emit, /* const */Exp exp, m_int size) {
1351

1790
  if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 &&
1352
516
    (exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) {
1353
251
    const Instr instr = emit_addref(emit, exp_getvar(exp));
1354
251
    instr->m_val = size;
1355
1274
  } else if(GET_FLAG(exp->info->type, struct)) // check cast_to ?
1356
1
    struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp));
1357
1525
}
1358
1359
382
ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) {
1360
  do {
1361
382
    emit_exp_addref1(emit, exp, size);
1362
382
    size += exp_size(exp);
1363
382
  } while((exp = exp->next));
1364
278
}
1365
1366
5724
ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) {
1367
5724
  Exp exp = e;
1368
  do {
1369
5889
    CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
1370
5885
    if(exp_getnonnull(exp))
1371
95
      emit_except(emit, exp->info->type);
1372
5885
    if(exp->info->cast_to)
1373
39
      CHECK_BB(emit_implicit_cast(emit, exp, exp->info->cast_to))
1374
5885
  } while((exp = exp->next));
1375
5720
  return GW_OK;
1376
}
1377
1378
38
ANN static m_bool emit_if(const Emitter emit, const Stmt_If stmt) {
1379
38
  DECL_OB(const Instr, op, = emit_flow(emit, stmt->cond))
1380
38
  CHECK_BB(scoped_stmt(emit, stmt->if_body, 1))
1381
38
  const Instr op2 = emit_add_instr(emit, Goto);
1382
38
  op->m_val = emit_code_size(emit);
1383
38
  if(stmt->else_body)
1384
12
    CHECK_BB(scoped_stmt(emit, stmt->else_body, 1))
1385
38
  op2->m_val = emit_code_size(emit);
1386
38
  return GW_OK;
1387
}
1388
1389
38
ANN static m_bool emit_stmt_if(const Emitter emit, const Stmt_If stmt) {
1390
38
  emit_push_scope(emit);
1391
38
  const m_bool ret = emit_if(emit, stmt);
1392
38
  emit_pop_scope(emit);
1393
38
  return ret;
1394
}
1395
1396
396
ANN static m_bool emit_stmt_code(const Emitter emit, const Stmt_Code stmt) {
1397
396
  ++emit->env->scope->depth;
1398
396
  const m_bool ret = stmt->stmt_list ? emit_stmt_list(emit, stmt->stmt_list) : 1;
1399
396
  --emit->env->scope->depth;
1400
396
  return ret;
1401
}
1402
1403
1
ANN static m_bool optimize_taill_call(const Emitter emit, const Exp_Call* e) {
1404
1
  if(e->args) {
1405
1
    emit_func_args(emit, e);
1406
1
    regpop(emit, e->m_func->def->stack_depth);
1407
1
    emit_args(emit, e->m_func);
1408
  }
1409
1
  emit_add_instr(emit, Goto);
1410
1
  return GW_OK;
1411
}
1412
1413
59
ANN static m_bool emit_stmt_return(const Emitter emit, const Stmt_Exp stmt) {
1414
59
  if(stmt->val) {
1415

57
    if(stmt->val->exp_type == ae_exp_call && emit->env->func == stmt->val->d.exp_call.m_func)
1416
1
      return optimize_taill_call(emit, &stmt->val->d.exp_call);
1417
56
    CHECK_BB(emit_exp_pop_next(emit, stmt->val))
1418
  }
1419
58
  vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto));
1420
58
  return GW_OK;
1421
}
1422
1423
9
ANN static inline m_bool emit_stmt_continue(const Emitter emit, const Stmt stmt NUSED) {
1424
9
  vector_add(&emit->code->stack_cont, (vtype)emit_add_instr(emit, Goto));
1425
9
  return GW_OK;
1426
}
1427
1428
8
ANN static inline m_bool emit_stmt_break(const Emitter emit, const Stmt stmt NUSED) {
1429
8
  vector_add(&emit->code->stack_break, (vtype)emit_add_instr(emit, Goto));
1430
8
  return GW_OK;
1431
}
1432
1433
54
ANN static inline void emit_push_stack(const Emitter emit) {
1434
54
  emit_push_scope(emit);
1435
54
  vector_add(&emit->code->stack_cont, (vtype)NULL);
1436
54
  vector_add(&emit->code->stack_break, (vtype)NULL);
1437
54
}
1438
1439
108
ANN static void pop_vector(Vector v, const  m_uint pc) {
1440
  Instr instr;
1441
233
  while((instr = (Instr)vector_pop(v)))
1442
17
    instr->m_val = pc;
1443
108
}
1444
1445
54
ANN static void emit_pop_stack(const Emitter emit, const m_uint index) {
1446
54
  pop_vector(&emit->code->stack_cont, index);
1447
54
  pop_vector(&emit->code->stack_break, emit_code_size(emit));
1448
54
  emit_pop_scope(emit);
1449
54
}
1450
1451
26
ANN static m_bool _emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt, const m_uint index) {
1452
26
  Instr op = NULL;
1453
26
  if(!stmt->is_do)
1454
12
    op = _flow(emit, stmt->cond, stmt_self(stmt)->stmt_type == ae_stmt_while);
1455
26
  CHECK_BB(scoped_stmt(emit, stmt->body, 1))
1456
26
  if(stmt->is_do) {
1457
14
    CHECK_OB((op = _flow(emit, stmt->cond, stmt_self(stmt)->stmt_type != ae_stmt_while)))
1458
14
    op->m_val = index;
1459
  } else {
1460
12
    const Instr goto_ = emit_add_instr(emit, Goto);
1461
12
    goto_->m_val = index;
1462
12
    op->m_val = emit_code_size(emit);
1463
  }
1464
26
  return GW_OK;
1465
}
1466
1467
26
ANN static m_bool emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt) {
1468
26
  const m_uint index = emit_code_size(emit);
1469
26
  emit_push_stack(emit);
1470
26
  const m_bool ret = _emit_stmt_flow(emit, stmt, index);
1471
26
  emit_pop_stack(emit, index);
1472
26
  return ret;
1473
}
1474
1475
18
ANN static m_bool variadic_state(const Emitter emit, const Stmt_VarLoop stmt, const m_uint status) {
1476
18
  regpushi(emit, status);
1477
18
  CHECK_BB(emit_exp(emit, stmt->exp))
1478
18
  const Instr member = emit_add_instr(emit, DotMember4);
1479
18
  member->m_val = SZ_INT;
1480
18
  emit_add_instr(emit, int_r_assign);
1481
18
  regpop(emit, SZ_INT);
1482
18
  return GW_OK;
1483
}
1484
1485
9
ANN static m_bool emit_stmt_varloop(const Emitter emit, const Stmt_VarLoop stmt) {
1486
9
  CHECK_BB(variadic_state(emit, stmt, 1))
1487
9
  CHECK_BB(emit_exp(emit, stmt->exp))
1488
9
  const Instr check = emit_add_instr(emit, VarargCheck);
1489
9
  const Instr member = emit_add_instr(emit, DotMember4);
1490
9
  member->m_val = SZ_INT*2;
1491
9
  const Instr instr = emit_add_instr(emit, BranchEqInt);
1492
9
  const m_uint pc = emit_code_size(emit);
1493
9
  emit_stmt(emit, stmt->body, 1);
1494
9
  CHECK_BB(emit_exp(emit, stmt->exp))
1495
9
  emit_vararg_end(emit, pc);
1496
9
  CHECK_BB(variadic_state(emit, stmt, 0))
1497
9
  check->m_val = instr->m_val = emit_code_size(emit);
1498
9
  return GW_OK;
1499
}
1500
1501
10
ANN static m_bool _emit_stmt_for(const Emitter emit, const Stmt_For stmt, m_uint *action_index) {
1502
10
  CHECK_BB(emit_stmt(emit, stmt->c1, 1))
1503
10
  const m_uint index = emit_code_size(emit);
1504
10
  DECL_OB(const Instr, op, = emit_flow(emit, stmt->c2->d.stmt_exp.val))
1505
10
  CHECK_BB(scoped_stmt(emit, stmt->body, 1))
1506
10
  *action_index = emit_code_size(emit);
1507
10
  if(stmt->c3) {
1508
9
    CHECK_BB(emit_exp(emit, stmt->c3))
1509
9
    pop_exp(emit, stmt->c3);
1510
  }
1511
10
  const Instr _goto = emit_add_instr(emit, Goto);
1512
10
  _goto->m_val = index;
1513
10
  op->m_val = emit_code_size(emit);
1514
10
  return GW_OK;
1515
}
1516
1517
10
ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
1518
10
  emit_push_stack(emit);
1519
10
  m_uint action_index = 0;
1520
10
  const m_bool ret = _emit_stmt_for(emit, stmt, &action_index);
1521
10
  emit_pop_stack(emit, action_index);
1522
10
  return ret;
1523
}
1524
1525
4
ANN static Instr emit_stmt_eachptr_init(const Emitter emit, const Type type) {
1526
4
  const Instr new_obj = emit_add_instr(emit, ObjectInstantiate);
1527
4
  new_obj->m_val2 = (m_uint)type;
1528
4
  (void)emit_addref(emit, 0);
1529
4
  regpop(emit, SZ_INT);
1530
4
  return emit_add_instr(emit, Reg2Mem);
1531
}
1532
1533
11
ANN static m_bool _emit_stmt_each(const Emitter emit, const Stmt_Each stmt, m_uint *end_pc) {
1534
11
  const Instr s1 = emit_add_instr(emit, MemSetImm);
1535
11
  Instr cpy = stmt->is_ptr ? emit_stmt_eachptr_init(emit, stmt->v->type) : NULL;
1536
11
  emit_local(emit, emit->gwion->type[et_int]);
1537
11
  const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
1538
11
  emit_local(emit, emit->gwion->type[et_int]);
1539
11
  stmt->v->from->offset = offset + SZ_INT;
1540
11
  const m_uint ini_pc  = emit_code_size(emit);
1541
11
  emit_except(emit, stmt->exp->info->type);
1542
11
  const Instr loop = emit_add_instr(emit, stmt->is_ptr ? AutoLoopPtr : AutoLoop);
1543
11
  const Instr end = emit_add_instr(emit, BranchEqInt);
1544
11
  const m_bool ret = scoped_stmt(emit, stmt->body, 1);
1545
11
  *end_pc = emit_code_size(emit);
1546
11
  if(stmt->is_ptr) {
1547
4
    loop->m_val2 = (m_uint)stmt->v->type;
1548
4
    cpy->m_val = stmt->v->from->offset;
1549
  }
1550
11
  const Instr tgt = emit_add_instr(emit, Goto);
1551
11
  end->m_val = emit_code_size(emit);
1552
11
  tgt->m_val = ini_pc;
1553
11
  s1->m_val = loop->m_val = offset;
1554
11
  return ret;
1555
}
1556
1557
11
ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) {
1558
11
  CHECK_BB(emit_exp(emit, stmt->exp))
1559
11
  emit_push_stack(emit);
1560
11
  m_uint end_pc = 0;
1561
11
  const m_bool ret = _emit_stmt_each(emit, stmt, &end_pc);
1562
11
  emit_pop_stack(emit, end_pc);
1563
11
  regpop(emit, SZ_INT);
1564
11
  return ret;
1565
}
1566
1567
7
ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt, m_uint *index) {
1568
7
  CHECK_BB(emit_exp_pop_next(emit, stmt->cond))
1569
7
  const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
1570
7
  const Instr tomem = emit_add_instr(emit, Reg2Mem);
1571
7
  tomem->m_val = offset;
1572
7
  tomem->m_val2 = -SZ_INT;
1573
7
  regpop(emit, SZ_INT);
1574
7
  *index = emit_code_size(emit);
1575
7
  const Instr cpy = emit_add_instr(emit, RegPushMem4);
1576
7
  cpy->m_val = offset;
1577
7
  emit_add_instr(emit, int_post_dec);
1578
7
  const Instr op = emit_add_instr(emit, BranchEqInt);
1579
7
  CHECK_BB(scoped_stmt(emit, stmt->body, 1))
1580
7
  const Instr _goto = emit_add_instr(emit, Goto);
1581
7
  _goto->m_val = *index;
1582
7
  op->m_val = emit_code_size(emit);
1583
7
  return GW_OK;
1584
}
1585
1586
7
ANN static m_bool emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt) {
1587
7
  emit_push_stack(emit);
1588
7
  m_uint index = 0;
1589
7
  const m_bool ret = _emit_stmt_loop(emit, stmt, &index);
1590
7
  emit_pop_stack(emit, index);
1591
7
  return ret;
1592
}
1593
1594
8
ANN static m_bool emit_stmt_jump(const Emitter emit, const Stmt_Jump stmt) {
1595
8
  if(!stmt->is_label)
1596
3
    stmt->data.instr = emit_add_instr(emit, Goto);
1597
  else {
1598
    assert(stmt->data.v.ptr);
1599
5
    const m_uint size = vector_size(&stmt->data.v);
1600
5
    if(!size)
1601
//return GW_OK;
1602
1
      ERR_B(stmt_self(stmt)->pos, _("label '%s' defined but not used."), s_name(stmt->name))
1603
    LOOP_OPTIM
1604
11
    for(m_uint i = size + 1; --i;) {
1605
4
      const Stmt_Jump label = (Stmt_Jump)vector_at(&stmt->data.v, i - 1);
1606
4
      if(!label->data.instr)
1607
1
        ERR_B(stmt_self(label)->pos, _("you are trying to use a upper label."))
1608
3
      label->data.instr->m_val = emit_code_size(emit);
1609
    }
1610
  }
1611
6
  return GW_OK;
1612
}
1613
1614
14
ANN static m_bool emit_type_def(const Emitter emit, const Type_Def tdef) {
1615
14
  return tdef->type->e->def ? emit_class_def(emit, tdef->type->e->def) : GW_OK;
1616
}
1617
1618
5
ANN static m_bool emit_enum_def(const Emitter emit, const Enum_Def edef) {
1619
  LOOP_OPTIM
1620
18
  for(m_uint i = 0; i < vector_size(&edef->values); ++i) {
1621
13
    const Value v = (Value)vector_at(&edef->values, i);
1622
13
    if(!emit->env->class_def) {
1623
7
      ALLOC_PTR(emit->gwion->mp, addr, m_uint, i);
1624
7
      v->from->offset = emit_local(emit, emit->gwion->type[et_int]);
1625
7
      v->d.ptr = addr;
1626
    } else
1627
6
      *(m_bit*)(emit->env->class_def->nspc->info->class_data + v->from->offset) = i;
1628
  }
1629
5
  return GW_OK;
1630
}
1631
1632
34
ANN void emit_union_offset(Decl_List l, const m_uint o) {
1633
  do {
1634
34
    Var_Decl_List v = l->self->d.exp_decl.list;
1635
34
    do v->self->value->from->offset = o;
1636
34
    while((v = v->next));
1637
34
  } while((l = l->next));
1638
18
}
1639
1640
10
ANN static inline void union_allocdata(MemPool mp, const Union_Def udef) {
1641
10
  const Nspc nspc = (udef->xid ? udef->value->type : udef->type)->nspc;
1642
10
  nspc_allocdata(mp, nspc);
1643
10
  nspc->info->offset = udef->s;
1644
10
}
1645
1646
18
ANN static m_bool emit_union_def(const Emitter emit, const Union_Def udef) {
1647
18
  if(tmpl_base(udef->tmpl))
1648
3
    return GW_OK;
1649
15
  Decl_List l = udef->l;
1650
15
  m_uint scope = emit->env->scope->depth;
1651
15
  const m_bool global = GET_FLAG(udef, global);
1652
15
  if(udef->xid) {
1653
6
    union_allocdata(emit->gwion->mp, udef);
1654
12
    Type_Decl *type_decl = new_type_decl(emit->gwion->mp,
1655
6
        udef->xid, loc_cpy(emit->gwion->mp, udef->pos));
1656
6
    type_decl->flag = udef->flag;
1657
6
    const Var_Decl var_decl = new_var_decl(emit->gwion->mp, udef->xid, NULL, loc_cpy(emit->gwion->mp, udef->pos));
1658
6
    const Var_Decl_List var_decl_list = new_var_decl_list(emit->gwion->mp, var_decl, NULL);
1659
6
    const Exp exp = new_exp_decl(emit->gwion->mp, type_decl, var_decl_list);
1660
6
    exp->d.exp_decl.type = udef->value->type;
1661
6
    var_decl->value = udef->value;
1662
6
    const m_bool ret = emit_exp_decl(emit, &exp->d.exp_decl);
1663
6
    free_exp(emit->gwion->mp, exp);
1664
6
    CHECK_BB(ret)
1665
6
    if(global) {
1666
1
      const M_Object o = new_object(emit->gwion->mp, NULL, udef->value->type);
1667
1
      udef->value->d.ptr = (m_uint*)o;
1668
1
      SET_FLAG(udef->value, builtin);
1669
1
      UNSET_FLAG(udef->value, union);
1670
    }
1671
6
    scope = emit_push_type(emit, udef->value->type);
1672
9
  } else if(udef->type_xid) {
1673
4
    union_allocdata(emit->gwion->mp, udef);
1674
4
    scope = emit_push_type(emit, udef->type);
1675
5
  } else if(global) {
1676
    // TODO: use mpool allocation
1677
1
    void* ptr = (void*)xcalloc(1, udef->s);
1678
1
    l = udef->l;
1679
1
    udef->value->d.ptr = ptr;
1680
1
    SET_FLAG(udef->value, enum);
1681
1
    SET_FLAG(udef->value, dtor);
1682
    do {
1683
2
      Var_Decl_List list = l->self->d.exp_decl.list;
1684
2
      list->self->value->d.ptr = ptr;
1685
2
      SET_FLAG(list->self->value, union);
1686
2
    } while((l = l->next));
1687
1
    SET_FLAG(udef->l->self->d.exp_decl.list->self->value, enum);
1688
1
    SET_FLAG(udef->l->self->d.exp_decl.list->self->value, dtor);
1689
  }
1690
15
  if(udef->xid)
1691
6
    regpop(emit, SZ_INT);
1692
15
  emit_union_offset(udef->l, udef->o);
1693

15
  if(udef->xid || udef->type_xid || global)
1694
11
    emit_pop(emit, scope);
1695
15
  union_flag(udef, ae_flag_emit);
1696
15
  return GW_OK;
1697
}
1698
1699
2005
ANN static m_bool emit_stmt_exp(const Emitter emit, const struct Stmt_Exp_* exp) {
1700
2005
  return exp->val ? emit_exp(emit, exp->val) : GW_OK;
1701
}
1702
1703
7
ANN static m_bool emit_case_head(const Emitter emit, const Exp base,
1704
    const Exp e, const Symbol op, const Vector v) {
1705
7
  CHECK_BB(emit_exp(emit, base))
1706
7
  CHECK_BB(emit_exp_pop_next(emit, e))
1707
7
  const m_int size = -exp_size(e);
1708
7
  emit_exp_addref(emit, base, -exp_totalsize(base) - size);
1709
7
  emit_exp_addref1(emit, e, -size);
1710
7
  const Exp_Binary bin = { .lhs=base, .rhs=e, .op=op };
1711
7
  struct ExpInfo_ info = { .nspc=e->info->nspc };
1712
7
  struct Exp_ ebin = { .d={.exp_binary=bin}, .info=&info };
1713
21
  struct Op_Import opi = { .op=op, .lhs=base->info->type, .rhs=e->info->type,
1714
14
    .data=(uintptr_t)&ebin.d.exp_binary, .pos=e->pos, .op_type=op_binary };
1715
7
  CHECK_BB(op_emit_bool(emit, &opi))
1716
7
  const Instr instr = emit_add_instr(emit, BranchEqInt);
1717
7
  vector_add(v, (vtype)instr);
1718
7
  return GW_OK;
1719
}
1720
1721
10
ANN static m_bool emit_case_body(const Emitter emit, const struct Stmt_Match_* stmt) {
1722
10
  const Instr when = stmt->when ? emit_flow(emit, stmt->when) : NULL;
1723
10
  if(stmt->when)
1724
4
    CHECK_OB(when)
1725
10
  CHECK_BB(emit_stmt_list(emit, stmt->list))
1726
10
  const Instr instr = emit_add_instr(emit, Goto);
1727
10
  vector_add(&emit->env->scope->match->vec, (vtype)instr);
1728
10
  if(when)
1729
4
    when->m_val = emit_code_size(emit);
1730
10
  return GW_OK;
1731
}
1732
1733
1
ANN static m_bool case_value(const Emitter emit, const Exp base, const Exp e) {
1734
1
  const Value v = e->d.prim.value;
1735
1
  v->from->offset = emit_local(emit, base->info->type);
1736
1
  CHECK_BB(emit_exp(emit, base))
1737
1
  emit_exp_addref(emit, base, -exp_totalsize(base));
1738
1
  regpop(emit, base->info->type->size);
1739
1
  const Instr instr = emit_add_instr(emit, Reg2Mem4);
1740
1
  instr->m_val = v->from->offset;
1741
1
  instr->m_val2 = base->info->type->size;
1742
1
  return GW_OK;
1743
}
1744
1745
1746
#define CASE_PASS (Symbol)1
1747
10
ANN static Symbol case_op(const Emitter emit, const Exp base, const Exp e) {
1748
10
  if(e->exp_type == ae_exp_primary) {
1749
10
    if(e->d.prim.prim_type == ae_prim_id) {
1750
3
      if(e->d.prim.d.var == insert_symbol("_"))
1751
2
        return CASE_PASS;
1752
1
      if(!nspc_lookup_value1(emit->env->curr, e->d.prim.d.var)) {
1753
1
        CHECK_BO(case_value(emit, base, e))
1754
1
        return CASE_PASS;
1755
      }
1756
    }
1757
  }
1758
7
  return insert_symbol("==");
1759
}
1760
1761
10
ANN static m_bool _emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt,
1762
    const Vector v) {
1763
10
  Exp e = stmt->cond;
1764
10
  const Map map = &emit->env->scope->match->map;
1765

20
  for(m_uint i = 0; i < map_size(map) && e; e = e->next, ++i) {
1766
10
    const Exp base = (Exp)VKEY(map, i);
1767
10
    const Symbol op = case_op(emit, base, e);
1768
10
    if(op != CASE_PASS)
1769
7
      CHECK_BB(emit_case_head(emit, base, e, op, v))
1770
  }
1771
10
  CHECK_BB(emit_case_body(emit, stmt))
1772
10
  return GW_OK;
1773
}
1774
1775
10
ANN static m_bool emit_stmt_match_case(const Emitter emit, const struct Stmt_Match_* stmt) {
1776
10
  emit_push_scope(emit);
1777
  struct Vector_ v;
1778
10
  vector_init(&v);
1779
10
  const m_bool ret = _emit_stmt_match_case(emit, stmt, &v);
1780
10
  emit_pop_scope(emit);
1781
17
  for(m_uint i = 0; i < vector_size(&v); ++i) {
1782
7
    const Instr instr = (Instr)vector_at(&v, i);
1783
7
    instr->m_val = emit_code_size(emit);
1784
  }
1785
10
  vector_release(&v);
1786
10
  return ret;
1787
}
1788
1789
6
ANN static inline void match_unvec(struct Match_ *const match , const m_uint pc) {
1790
6
  const Vector vec = &match->vec;
1791
16
  for(m_uint i = 0; i < vector_size(vec); ++i) {
1792
10
    const Instr instr = (Instr)VPTR(vec, i);
1793
10
    instr->m_val = pc;
1794
  }
1795
6
  vector_release(vec);
1796
6
}
1797
1798
10
ANN static m_bool emit_stmt_cases(const Emitter emit, Stmt_List list) {
1799
10
  do CHECK_BB(emit_stmt_match_case(emit, &list->stmt->d.stmt_match))
1800
10
  while((list = list->next));
1801
6
  return GW_OK;
1802
}
1803
1804
6
ANN static m_bool emit_match(const Emitter emit, const struct Stmt_Match_* stmt) {
1805
6
  if(stmt->where)
1806
2
    CHECK_BB(emit_stmt(emit, stmt->where, 1))
1807
6
  MATCH_INI(emit->env->scope)
1808
6
  vector_init(&m.vec);
1809
6
  const m_bool ret = emit_stmt_cases(emit, stmt->list);
1810
6
  match_unvec(&m, emit_code_size(emit));
1811
6
  MATCH_END(emit->env->scope)
1812
6
  return ret;
1813
}
1814
1815
6
ANN static m_bool emit_stmt_match(const Emitter emit, const struct Stmt_Match_* stmt) {
1816
6
  emit_push_scope(emit);
1817
6
  const m_bool ret = emit_match(emit, stmt);
1818
6
  emit_pop_scope(emit);
1819
6
  return ret;
1820
}
1821
1822
4
ANN static m_bool emit_stmt_pp(const Emitter emit, const struct Stmt_PP_* stmt) {
1823
4
  if(stmt->pp_type == ae_pp_pragma) {
1824
1
    if(!strncmp(stmt->data, "memoize", strlen("memoize")))
1825
1
      emit->info->memoize = strtol(stmt->data + 7, NULL, 10);
1826
3
  } else if(stmt->pp_type == ae_pp_include)
1827
3
    emit->env->name = stmt->data;
1828
4
  return GW_OK;
1829
}
1830
1831
#define emit_stmt_while emit_stmt_flow
1832
#define emit_stmt_until emit_stmt_flow
1833
DECL_STMT_FUNC(emit, m_bool , Emitter)
1834
1835
2596
ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop) {
1836
2596
  CHECK_BB(emit_stmt_func[stmt->stmt_type](emit, &stmt->d))
1837

2592
  if(pop && stmt->stmt_type == ae_stmt_exp && stmt->d.stmt_exp.val) {
1838
1986
    pop_exp(emit, stmt->d.stmt_exp.val);
1839
  }
1840
2592
  return GW_OK;
1841
}
1842
1843
2203
ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List l) {
1844
2203
  do CHECK_BB(emit_stmt(emit, l->stmt, 1))
1845
2199
  while((l = l->next));
1846
904
  return GW_OK;
1847
}
1848
1849
556
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) {
1850
2224
  struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
1851
1668
    .rhs=exp_self(member)->info->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos, .op_type=op_dot };
1852
556
  return op_emit_bool(emit, &opi);
1853
}
1854
1855
96
ANN static inline void emit_func_def_global(const Emitter emit, const Value value) {
1856
96
  const Instr set_mem = emit_add_instr(emit, MemSetImm);
1857
96
  set_mem->m_val = value->from->offset;
1858
96
  set_mem->m_val2 = (m_uint)value->d.func_ref->code;
1859
96
}
1860
1861
242
ANN static void emit_func_def_init(const Emitter emit, const Func func) {
1862
242
  const Type t = emit->env->class_def;
1863
242
  char c[(t ? strlen(t->name) + 1 : 0) + strlen(func->name) + 6];
1864

242
  sprintf(c, "%s%s%s(...)", t ? t->name : "", t ? "." : "", func->name);
1865
242
  emit_push_code(emit, c);
1866
242
}
1867
1868
187
ANN static void emit_func_def_args(const Emitter emit, Arg_List a) {
1869
  do {
1870
187
    const Type type = a->var_decl->value->type;
1871
187
    emit->code->stack_depth += type->size;
1872
187
    a->var_decl->value->from->offset = emit_local(emit, type);
1873
187
  } while((a = a->next));
1874
135
}
1875
1876
242
ANN static void emit_func_def_ensure(const Emitter emit, const Func_Def fdef) {
1877
242
  const m_uint size = fdef->base->ret_type->size;
1878
242
  if(size) {
1879
86
    const Instr instr = emit_kind(emit, size, 0, regpushimm);
1880
86
    instr->m_val2 = size;
1881
  }
1882
242
  vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto));
1883
242
}
1884
1885
242
ANN static void emit_func_def_return(const Emitter emit) {
1886
242
  const m_uint val = emit_code_size(emit);
1887
  LOOP_OPTIM
1888
784
  for(m_uint i = vector_size(&emit->code->stack_return) + 1; --i; ) {
1889
300
    const Instr instr = (Instr)vector_at(&emit->code->stack_return, i-1);
1890
300
    instr->m_val = val;
1891
  }
1892
242
  vector_clear(&emit->code->stack_return);
1893

242
  if(emit->info->memoize && GET_FLAG(emit->env->func, pure)) {
1894
1
    const Instr instr = emit_add_instr(emit, MemoizeStore);
1895
1
    instr->m_val = emit->env->func->def->stack_depth;
1896
  }
1897
242
}
1898
1899
11
ANN static VM_Code emit_internal(const Emitter emit, const Func f) {
1900
11
  if(f->def->base->xid == insert_symbol("@dtor")) {
1901
6
    emit->env->class_def->nspc->dtor = f->code = finalyze(emit, DTOR_EOC);
1902
6
    ADD_REF(f->code)
1903
6
    return f->code;
1904
5
  } else if(f->def->base->xid == insert_symbol("@gack")) {
1905
2
    regpop(emit, SZ_INT + f->value_ref->from->owner_class->size);
1906
2
    const Instr instr = emit_add_instr(emit, RegPushMem);
1907
2
    instr->m_val = SZ_INT;
1908
2
    f->code = finalyze(emit, FuncReturn);
1909
2
    return emit->env->class_def->e->gack = f->code;
1910
  }
1911
3
  return finalyze(emit, FuncReturn);
1912
}
1913
1914
242
ANN static VM_Code emit_func_def_code(const Emitter emit, const Func func) {
1915
242
  if(GET_FLAG(func->def->base, typedef))
1916
11
    return emit_internal(emit, func);
1917
  else
1918
231
    return finalyze(emit, FuncReturn);
1919
}
1920
1921
242
ANN static m_bool emit_func_def_body(const Emitter emit, const Func_Def fdef) {
1922
242
  if(fdef->base->args)
1923
135
    emit_func_def_args(emit, fdef->base->args);
1924
242
  if(GET_FLAG(fdef->base, variadic))
1925
12
    stack_alloc(emit);
1926
242
  if(fdef->d.code)
1927
242
    CHECK_BB(scoped_stmt(emit, fdef->d.code, 1))
1928
242
  emit_func_def_ensure(emit, fdef);
1929
242
  return GW_OK;
1930
}
1931
1932
1
ANN static Instr me_top(MemoizeEmitter *me) {
1933
1
  const Instr idx = emit_add_instr(me->emit, MemSetImm);
1934
1
  idx->m_val = me->offset;
1935
1
  const Instr pc = emit_add_instr(me->emit, MemSetImm);
1936
1
  pc->m_val = me->offset + SZ_INT;
1937
1
  return pc;
1938
}
1939
1940
1
ANN static void me_ini(MemoizeEmitter *me) {
1941
1
  const Instr ini = emit_add_instr(me->emit, MemoizeIni);
1942
1
  ini->m_val = me->offset;
1943
1
  ini->m_val2 = me->fdef->stack_depth + me->fdef->base->ret_type->size;
1944
1
}
1945
1946
1
ANN static void me_end(MemoizeEmitter *me, const m_uint pc) {
1947
2
  for(m_uint i = 0; i < vector_size(&me->branch); ++i)
1948
1
	  ((Instr)vector_at(&me->branch, i))->m_val = pc;
1949
1
}
1950
1951
1
ANN static void me_bottom(MemoizeEmitter *me, const m_uint pc) {
1952
1
  const Instr idx = emit_add_instr(me->emit, RegPushMem4);
1953
1
  idx->m_val = me->offset;
1954
1
  emit_add_instr(me->emit, int_pre_inc);
1955
1
  regpop(me->emit, SZ_INT);
1956
1
  const Instr loop = emit_add_instr(me->emit, Goto);
1957
1
  loop->m_val = pc;
1958
1
}
1959
1960
1
ANN static void me_ret(MemoizeEmitter *me) {
1961
1
  const Instr instr = emit_kind(me->emit, me->fdef->base->ret_type->size, 0, regpushmem);
1962
1
  instr->m_val = (me->offset + SZ_INT)*2;
1963
1
  emit_add_instr(me->emit, FuncReturn);
1964
1
}
1965
1966
1
ANN static m_bool me_run(MemoizeEmitter *me, const m_uint pc) {
1967
1
  me_ini(me);
1968
1
  if(me->fdef->base->args)
1969
1
    CHECK_BB(me_arg(me))
1970
1
  me_ret(me);
1971
1
  me_end(me, emit_code_size(me->emit));
1972
1
  me_bottom(me, pc);
1973
1
  return GW_OK;
1974
}
1975
1976
1
ANN static m_bool emit_memoize(const Emitter emit, const Func_Def fdef) {
1977
1
  MemoizeEmitter me = { .emit=emit, .fdef=fdef, .offset=fdef->stack_depth };
1978
1
  const Instr pc = me_top(&me);
1979
1
  const m_uint top = emit_code_size(emit);
1980
1
  vector_init(&me.branch);
1981
1
  const m_bool ret = me_run(&me, top);
1982
1
  vector_release(&me.branch);
1983
1
  pc->m_val2 = emit_code_size(emit);
1984
1
  return ret;
1985
}
1986
1987
242
ANN static m_bool emit_fdef(const Emitter emit, const Func_Def fdef) {
1988

242
  if(emit->info->memoize && GET_FLAG(fdef->base->func, pure))
1989
1
    CHECK_BB(emit_memoize(emit, fdef))
1990
242
  CHECK_BB(emit_func_def_body(emit, fdef))
1991
242
  emit_func_def_return(emit);
1992
242
  return GW_OK;
1993
}
1994
1995
484
static ANN int fdef_is_file_global(const Emitter emit, const Func_Def fdef) {
1996
952
  return isa(fdef->base->func->value_ref->type, emit->gwion->type[et_lambda]) < 0 &&
1997


924
    !emit->env->class_def && !GET_FLAG(fdef->base, global) && !fdef->base->tmpl &&
1998
194
    !emit->env->scope->depth;
1999
}
2000
2001
242
ANN static void emit_fdef_finish(const Emitter emit, const Func_Def fdef) {
2002
242
  const Func func = fdef->base->func;
2003
242
  func->code = emit_func_def_code(emit, func);
2004
242
  if(fdef_is_file_global(emit, fdef))
2005
96
    emit_func_def_global(emit, func->value_ref);
2006

242
  if(emit->info->memoize && GET_FLAG(func, pure))
2007
1
    func->code->memoize = memoize_ini(emit, func);
2008
242
}
2009
2010
287
ANN static m_bool emit_func_def(const Emitter emit, const Func_Def f) {
2011
287
  const Func func = f->base->func;
2012
287
  const Func_Def fdef = func->def;
2013
287
  const Func former = emit->env->func;
2014

287
  if(func->code || tmpl_base(fdef->base->tmpl))
2015
45
    return GW_OK;
2016

242
  if(SAFE_FLAG(emit->env->class_def, builtin) && GET_FLAG(emit->env->class_def, template))
2017
    return GW_OK;
2018
242
  if(fdef_is_file_global(emit, fdef))
2019
96
    func->value_ref->from->offset = emit_local(emit, emit->gwion->type[et_int]);
2020
242
  emit_func_def_init(emit, func);
2021
242
  if(GET_FLAG(func, member))
2022
99
    stack_alloc_this(emit);
2023
242
  emit->env->func = func;
2024
242
  emit_push_scope(emit);
2025
242
  if(!strcmp(s_name(fdef->base->xid), "@gack")) {
2026
2
    emit_local(emit, emit->gwion->type[et_int]);
2027
2
    const Instr instr = emit_add_instr(emit, MemSetImm);
2028
2
    instr->m_val = SZ_INT;
2029
  }
2030
242
  const m_bool ret = scanx_fdef(emit->env, emit, fdef, (_exp_func)emit_fdef);
2031
242
  emit_pop_scope(emit);
2032
242
  emit->env->func = former;
2033
242
  if(ret > 0)
2034
242
    emit_fdef_finish(emit, fdef);
2035
  else
2036
    emit_pop_code(emit);
2037
242
  return ret;
2038
}
2039
2040
#define emit_fptr_def dummy_func
2041
989
HANDLE_SECTION_FUNC(emit, m_bool, Emitter)
2042
2043
147
ANN Code* emit_class_code(const Emitter emit, const m_str name) {
2044
147
  const m_uint len = strlen(name) + 7;
2045
147
  char c[len];
2046
147
  snprintf(c, len, "class %s", name);
2047
147
  emit_push_code(emit, c);
2048
147
  stack_alloc_this(emit);
2049
147
  return emit->code;
2050
}
2051
2052
6
ANN static m_bool emit_parent(const Emitter emit, const Class_Def cdef) {
2053
6
  const Type parent = cdef->base.type->e->parent;
2054
6
  return !GET_FLAG(parent, emit) ? ensure_emit(emit, parent) : GW_OK;
2055
}
2056
2057
28
ANN static inline m_bool emit_cdef(const Emitter emit, const Class_Def cdef) {
2058
28
  return scanx_cdef(emit->env, emit, cdef,
2059
      (_exp_func)emit_class_def, (_exp_func)emit_union_def);
2060
}
2061
2062
147
ANN void emit_class_finish(const Emitter emit, const Nspc nspc) {
2063
147
  nspc->pre_ctor = finalyze(emit, FuncReturn);
2064
147
  SET_FLAG(nspc->pre_ctor, ctor);
2065
147
}
2066
2067
6
ANN static m_bool cdef_parent(const Emitter emit, const Class_Def cdef) {
2068

6
  if(cdef->base.tmpl && cdef->base.tmpl->list)
2069
4
    CHECK_BB(template_push_types(emit->env, cdef->base.tmpl))
2070
6
  const m_bool ret = emit_parent(emit, cdef);
2071

6
  if(cdef->base.tmpl && cdef->base.tmpl->list)
2072
4
    nspc_pop_type(emit->gwion->mp, emit->env->curr);
2073
6
  return ret;
2074
}
2075
2076
189
ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
2077
189
  if(tmpl_base(cdef->base.tmpl))
2078
18
    return GW_OK;
2079
171
  const Type t = cdef->base.type;
2080
171
  if(GET_FLAG(t, emit))
2081
    return GW_OK;
2082
171
  SET_FLAG(t, emit);
2083

171
  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, emit))
2084
    CHECK_BB(ensure_emit(emit, t->e->owner_class))
2085

171
  if(cdef->base.ext && t->e->parent->e->def && !GET_FLAG(t->e->parent, emit))
2086
6
    CHECK_BB(cdef_parent(emit, cdef))
2087
171
  nspc_allocdata(emit->gwion->mp, t->nspc);
2088
171
  if(cdef->body) {
2089
147
    emit_class_code(emit, t->name);
2090
147
    if(scanx_body(emit->env, cdef, (_exp_func)emit_section, emit) > 0)
2091
147
      emit_class_finish(emit, t->nspc);
2092
    else {
2093
      free_code(emit->gwion->mp, emit->code);
2094
      emit_pop_code(emit);
2095
      return GW_ERROR;
2096
    }
2097
  }
2098
171
  return GW_OK;
2099
}
2100
2101
4
ANN static inline void emit_free_code(const Emitter emit, Code* code) {
2102
4
  if(vector_size(&code->instr))
2103
2
    free_code_instr(&code->instr, emit->gwion);
2104
4
  free_code(emit->gwion->mp, code);
2105
4
}
2106
2107
4
ANN static VM_Code emit_free_stack(const Emitter emit) {
2108
  LOOP_OPTIM
2109
8
  for(m_uint i = vector_size(&emit->stack) + 1; --i;)
2110
    emit_free_code(emit, (Code*)vector_at(&emit->stack, i - 1));
2111
4
  vector_clear(&emit->stack);
2112
4
  vector_clear(&emit->info->pure);
2113
4
  emit_free_code(emit, emit->code);
2114
4
  return NULL;
2115
}
2116
2117
712
ANN static inline m_bool emit_ast_inner(const Emitter emit, Ast ast) {
2118
712
  do CHECK_BB(emit_section(emit, ast->section))
2119
708
  while((ast = ast->next));
2120
414
  return GW_OK;
2121
}
2122
2123
418
ANN m_bool emit_ast(const Env env, Ast ast) {
2124
418
  const Emitter emit = env->gwion->emit;
2125
418
  emit->info->memoize = 0;
2126
418
  emit->code = new_code(emit, emit->env->name);
2127
418
  emit_push_scope(emit);
2128
418
  const m_bool ret = emit_ast_inner(emit, ast);
2129
418
  emit_pop_scope(emit);
2130
418
  if(ret > 0)
2131
414
    emit->info->code = finalyze(emit, emit->info->finalyzer);
2132
  else
2133
4
    emit_free_stack(emit);
2134
418
  return ret;
2135
}