GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/emit/emit.c Lines: 1509 1555 97.0 %
Date: 2020-07-24 14:14:26 Branches: 670 862 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
70
static inline void emit_pop(const Emitter emit, const m_uint scope) { env_pop(emit->env, scope); }
36
53
static inline m_uint emit_push(const Emitter emit, const Type type, const Nspc nspc) {
37
53
  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
813
ANEW static Frame* new_frame(MemPool p) {
47
813
  Frame* frame = mp_calloc(p, Frame);
48
813
  vector_init(&frame->stack);
49
813
  vector_add(&frame->stack, (vtype)NULL);
50
813
  return frame;
51
}
52
53
813
ANN static void free_frame(MemPool p, Frame* a) {
54
  LOOP_OPTIM
55
2672
  for(vtype i = vector_size(&a->stack) + 1; --i;)
56
1046
    if(vector_at(&a->stack, i - 1))
57
233
      mp_free(p, Local, (Local*)vector_at(&a->stack, i - 1));
58
813
  vector_release(&a->stack);
59
813
  mp_free(p, Frame, a);
60
813
}
61
62
1014
ANN static Local* new_local(MemPool p, const Type type) {
63
1014
  Local* local  = mp_calloc(p, Local);
64
1014
  local->type   = type;
65
1014
  return local;
66
}
67
68
1014
ANN static m_uint frame_local(MemPool p, Frame* frame, const Type t) {
69
1014
  Local* local = new_local(p, t);
70
1014
  local->offset = frame->curr_offset;
71
1014
  frame->curr_offset += t->size;
72
1014
  vector_add(&frame->stack, (vtype)local);
73
1014
  return local->offset;
74
}
75
76
1070
ANN static inline void frame_push(Frame* frame) {
77
1070
  vector_add(&frame->stack, (vtype)NULL);
78
1070
}
79
80
9
ANN static void struct_pop(const Emitter emit, const Type type, const m_uint offset) {
81
25
  for(m_uint i = 0; i < vector_size(&type->e->tuple->types); ++i) {
82
16
    const Type t = (Type)vector_at(&type->e->tuple->types, i);
83
16
    if(isa(t, emit->gwion->type[et_object]) > 0) {
84
1
      const Instr instr = emit_add_instr(emit, ObjectRelease);
85
1
      instr->m_val = offset + vector_at(&type->e->tuple->offset, i);
86
15
    } else if(GET_FLAG(t, struct))
87
      struct_pop(emit, t, offset + vector_at(&type->e->tuple->offset, i));
88
  }
89
9
}
90
91
1851
ANN static m_int frame_pop(const Emitter emit) {
92
1851
  Frame *frame = emit->code->frame;
93
1851
  DECL_OB(const Local*, l, = (Local*)vector_pop(&frame->stack))
94
781
  frame->curr_offset -= l->type->size;
95
781
  if(GET_FLAG(l->type, struct)) {
96
9
    struct_pop(emit, l->type, l->offset);
97
9
    return frame_pop(emit);
98
  }
99
772
  return isa(l->type, emit->gwion->type[et_object]) > 0 ? (m_int)l->offset : frame_pop(emit);
100
}
101
102
ANN /*static */m_bool emit_exp(const Emitter emit, Exp exp);
103
ANN static m_bool emit_stmt(const Emitter emit, const Stmt stmt, const m_bool pop);
104
ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List list);
105
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member);
106
ANN static m_bool emit_func_def(const Emitter emit, const Func_Def func_def);
107
108
813
ANEW static Code* new_code(const Emitter emit, const m_str name) {
109
813
  Code* code = mp_calloc(emit->gwion->mp, Code);
110
813
  code->name = code_name_set(emit->gwion->mp, name, emit->env->name);
111
813
  vector_init(&code->instr);
112
813
  vector_init(&code->stack_break);
113
813
  vector_init(&code->stack_cont);
114
813
  vector_init(&code->stack_return);
115
813
  code->frame = new_frame(emit->gwion->mp);
116
813
  return code;
117
}
118
119
813
ANN static void free_code(MemPool p, Code* code) {
120
813
  vector_release(&code->instr);
121
813
  vector_release(&code->stack_break);
122
813
  vector_release(&code->stack_cont);
123
813
  vector_release(&code->stack_return);
124
813
  free_frame(p, code->frame);
125
813
  free_mstr(p, code->name);
126
813
  mp_free(p, Code, code);
127
813
}
128
129
1070
ANN static void emit_pop_scope(const Emitter emit) {
130
  m_int offset;
131
2386
  while((offset = frame_pop(emit)) > -1) {
132
246
    Instr instr = emit_add_instr(emit, ObjectRelease);
133
246
    instr->m_val = (m_uint)offset;
134
  }
135
1070
  vector_pop(&emit->info->pure);
136
1070
}
137
138
412
ANN static inline void emit_push_code(const Emitter emit, const m_str name) {
139
412
  vector_add(&emit->stack, (vtype)emit->code);
140
412
  emit->code = new_code(emit, name);
141
412
}
142
143
ANN static inline void emit_pop_code(const Emitter emit) {
144
  emit->code = (Code*)vector_pop(&emit->stack);
145
}
146
147
1070
ANN static inline void emit_push_scope(const Emitter emit) {
148
1070
  frame_push(emit->code->frame);
149
1070
  vector_add(&emit->info->pure, 0);
150
1070
}
151
152
530
ANN static inline m_uint emit_code_size(const Emitter emit) {
153
530
  return vector_size(&emit->code->instr);
154
}
155
156
1742
ANN m_uint emit_code_offset(const Emitter emit) {
157
1742
  return emit->code->frame->curr_offset;
158
}
159
160
1014
ANN m_uint emit_local(const Emitter emit, const Type t) {
161
1014
  return frame_local(emit->gwion->mp, emit->code->frame, t);
162
}
163
164
ANN void emit_ext_ctor(const Emitter emit, const Type t);
165
166
626
ANN static inline void maybe_ctor(const Emitter emit, const Type t) {
167

626
  if(!GET_FLAG(t, nonnull) && GET_FLAG(t, ctor))
168
151
    emit_ext_ctor(emit, t);
169
626
}
170
171
626
ANN static void emit_pre_ctor(const Emitter emit, const Type type) {
172
626
  if(type->e->parent)
173
428
    emit_pre_ctor(emit, type->e->parent);
174
626
  maybe_ctor(emit, type);
175

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

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

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

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

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

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

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

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

14
  if(isa(v->type, emit->gwion->type[et_object]) > 0 && !is_ref)
627
5
    CHECK_BB(decl_static(emit, var_decl, 0))
628

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

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

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


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

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

1186
    emit_kind(emit, v->type->size, !struct_ctor(v) ? emit_addr : 1, exec) : emit_struct_decl(emit, v, !struct_ctor(v) ? emit_addr : 1);
663
606
  instr->m_val = v->from->offset;
664


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

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

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

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


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


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

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

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

619
  if(!GET_FLAG(t, emit) && t->e->def)
742
24
    CHECK_BB(ensure_emit(emit, t))
743
619
  const m_bool global = GET_FLAG(decl->td, global);
744
619
  const m_uint scope = !global ? emit->env->scope->depth : emit_push_global(emit);
745
619
  const m_bool ret = emit_decl(emit, decl);
746
619
  if(global)
747
6
    emit_pop(emit, scope);
748
619
  return ret;
749
}
750
751
18
ANN static m_uint vararg_size(const Exp_Call* exp_call, const Vector kinds) {
752
18
  Exp e = exp_call->args;
753
18
  Arg_List l = exp_call->m_func->def->base->args;
754
18
  m_uint size = 0;
755
84
  while(e) {
756
48
    if(!l) {
757
41
      size += e->info->type->size;
758
41
      vector_add(kinds, (vtype)e->info->type); // ->size
759
    } else
760
7
      l = l->next;
761
48
    e = e->next;
762
  }
763
18
  return size;
764
}
765
766
18
ANN static void emit_func_arg_vararg(const Emitter emit, const Exp_Call* exp_call) {
767
18
  const Instr instr = emit_add_instr(emit, VarargIni);
768
18
  const Vector kinds = new_vector(emit->gwion->mp);
769
18
  if((instr->m_val = vararg_size(exp_call, kinds)))
770
15
    instr->m_val2 = (m_uint)kinds;
771
  else
772
3
    free_vector(emit->gwion->mp, kinds);
773
18
}
774
775
ANN static inline m_uint exp_size(Exp e);
776
260
ANN static inline m_uint exp_totalsize(Exp e) {
777
260
  m_uint size = 0;
778
335
  do size += exp_size(e);
779
335
  while((e = e->next));
780
260
  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
435
ANN static m_bool emit_func_args(const Emitter emit, const Exp_Call* exp_call) {
786
435
  if(exp_call->args) {
787
217
    CHECK_BB(emit_exp(emit, exp_call->args))
788
217
    emit_exp_addref(emit, exp_call->args, -exp_totalsize(exp_call->args));
789
  }
790

435
  if(exp_call->m_func && GET_FLAG(exp_call->m_func->def, variadic))
791
18
    emit_func_arg_vararg(emit, exp_call);
792
435
  return GW_OK;
793
}
794
795
434
ANN static m_bool prepare_call(const Emitter emit, const Exp_Call* exp_call) {
796
434
  CHECK_BB(emit_func_args(emit, exp_call))
797
434
  return emit_exp(emit, exp_call->func);
798
}
799
800
407
ANN static m_bool emit_exp_call(const Emitter emit, const Exp_Call* exp_call) {
801
407
  CHECK_BB(prepare_call(emit, exp_call))
802
407
  if(exp_call->m_func)
803
407
    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
407
  const Exp e = exp_self(exp_call);
810
407
  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

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

443
  if(!f->code || (GET_FLAG(f, ref) && !GET_FLAG(f, builtin))) {
1061

216
    if(GET_FLAG(f, template) && !is_fptr(emit->gwion, f->value_ref->type)) {
1062
76
      if(emit->env->func != f)
1063
33
        CHECK_BO(emit_template_code(emit, f))
1064
      else { // recursive function. (maybe should be used only for global funcs)
1065
10
        const Instr back = (Instr) vector_size(&emit->code->instr) ?
1066
5
            (Instr)vector_back(&emit->code->instr) : emit_add_instr(emit, RegPushImm);
1067
5
        back->opcode = eOP_MAX;
1068
5
        back->execute = SetRecurs;
1069
5
        back->m_val = 0;
1070
      }
1071


70
    } else if(emit->env->func != f && !f->value_ref->from->owner_class && !f->code && !is_fptr(emit->gwion, f->value_ref->type)) {
1072
1
      if(GET_FLAG(f->def, op)) {
1073
        const Instr back = (Instr)vector_back(&emit->code->instr);
1074
        back->m_val = (m_uint)f;
1075
      } else {
1076
// ensure env?
1077
1
        CHECK_BO(emit_func_def(emit, f->def))
1078
1
        const Instr instr = emit_add_instr(emit, RegSetImm);
1079
1
        instr->m_val = (m_uint)f->code;
1080
1
        instr->m_val2 = -SZ_INT;
1081
      }
1082
    }
1083

665
  } else if((f->value_ref->from->owner_class && is_special(emit, f->value_ref->from->owner_class) > 0) ||
1084

566
        !f->value_ref->from->owner_class || (GET_FLAG(f, template) &&
1085
19
        !is_fptr(emit->gwion, f->value_ref->type)))
1086
137
    push_func_code(emit, f);
1087
198
  else if(vector_size(&emit->code->instr)) {
1088
187
    const Instr back = (Instr)vector_back(&emit->code->instr);
1089

187
    if((f_instr)(m_uint)back->opcode == DotFunc || (f_instr)(m_uint)back->opcode == DotStaticFunc)
1090
169
      back->m_val = f->vt_index;
1091
  }
1092

670
  if(vector_size(&emit->code->instr) && GET_FLAG(f, member) &&
1093
251
        is_fptr(emit->gwion, f->value_ref->type)) {
1094
24
    const Instr back = (Instr)vector_back(&emit->code->instr);
1095
24
    m_bit exec = back->opcode;
1096
24
    m_uint val = back->m_val;
1097
24
    m_uint val2 = back->m_val2;
1098
24
    back->opcode = eRegPushMem;
1099
24
    back->m_val = back->m_val2 = 0;
1100
24
    const Instr instr = emit_add_instr(emit, (f_instr)(m_uint)exec);
1101
24
    instr->m_val = val;
1102
24
    instr->m_val2 = val2;
1103

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

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

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

30
  if(GET_FLAG(f, member) && is_fptr(emit->gwion, f->value_ref->type)) {
1215
3
    const m_uint depth = f->def->stack_depth;
1216
3
    regpop(emit, depth -SZ_INT);
1217
3
    const Instr spork = emit_add_instr(emit, SporkMemberFptr);
1218
3
    spork->m_val = depth;
1219
  } else
1220
24
    emit_exp_spork_finish(emit, f->def->stack_depth);
1221
27
  (void)emit_add_instr(emit, SporkEnd);
1222
27
}
1223
1224
52
ANN static Instr spork_ini(const Emitter emit, const struct Sporker *sp) {
1225
52
  if(sp->is_spork) {
1226
45
    const Instr instr = emit_add_instr(emit, SporkIni);
1227
45
    instr->m_val = (m_uint)sp->vm_code;
1228
45
    instr->m_val2 = sp->is_spork;
1229
45
    return instr;
1230
  }
1231
7
  const Func f = !sp->code ? sp->exp->d.exp_call.m_func : NULL;
1232
7
  const Instr instr = emit_add_instr(emit, ForkIni);
1233
7
  instr->m_val = (m_uint)sp->vm_code;
1234
7
  instr->m_val2 = f ? f->def->base->ret_type->size : 0;
1235
7
  return instr;
1236
}
1237
1238
52
ANN Instr emit_exp_spork(const Emitter emit, const Exp_Unary* unary) {
1239
260
  struct Sporker sporker = {
1240
52
    .exp=unary->exp,
1241
52
    .code=unary->code,
1242
52
    .is_spork=(unary->op == insert_symbol("spork")),
1243
52
    .emit_var=exp_getvar(exp_self(unary))
1244
  };
1245
52
  CHECK_OO((sporker.vm_code = spork_prepare(emit, &sporker)))
1246
52
  const Instr ini = spork_ini(emit, &sporker);
1247
52
  (unary->code ? spork_code : spork_func)(emit, &sporker);
1248
52
  return ini;
1249
}
1250
1251
124
ANN static m_bool emit_exp_unary(const Emitter emit, const Exp_Unary* unary) {
1252
124
  const Type t = exp_self(unary)->info->type;
1253
124
  const Type base = get_type(actual_type(emit->gwion, t));
1254

124
  if(base->e->def && !GET_FLAG(base, emit))
1255
    CHECK_BB(ensure_emit(emit, base))
1256
  // no pos ?
1257
124
  struct Op_Import opi = { .op=unary->op, .data=(uintptr_t)unary, .op_type=op_unary };
1258

124
  if(unary->op != insert_symbol("spork") && unary->op != insert_symbol("fork") && unary->exp) {
1259
53
    CHECK_BB(emit_exp_pop_next(emit, unary->exp))
1260
53
    emit_exp_addref1(emit, unary->exp, -exp_size(unary->exp));
1261
53
    opi.rhs = unary->exp->info->type;
1262
  }
1263
124
  return op_emit_bool(emit, &opi);
1264
}
1265
1266
34
ANN static m_bool emit_implicit_cast(const Emitter emit,
1267
    const restrict Exp  from, const restrict Type to) {
1268
34
  const struct Implicit imp = { from, to, from->pos };
1269
  // no pos
1270
68
  struct Op_Import opi = { .op=insert_symbol("@implicit"), .lhs=from->info->type, .rhs=to,
1271
34
    .data=(m_uint)&imp, .op_type=op_implicit };
1272
34
  return op_emit_bool(emit, &opi);
1273
}
1274
1275
81
ANN static Instr _flow(const Emitter emit, const Exp e, const m_bool b) {
1276
81
  CHECK_BO(emit_exp_pop_next(emit, e))
1277
81
  emit_exp_addref1(emit, e, -exp_size(e));
1278
324
  struct Op_Import opi = { .op=insert_symbol(b ? "@conditionnal" : "@unconditionnal"),
1279
243
                           .rhs=e->info->type, .pos=e->pos, .data=(uintptr_t)e, .op_type=op_exp };
1280
81
  const Instr instr = op_emit(emit, &opi);
1281
  assert(instr != (Instr)GW_OK);
1282
81
  return instr;
1283
}
1284
#define emit_flow(emit,b) _flow(emit, b, 1)
1285
1286
7
ANN static m_bool emit_exp_if(const Emitter emit, const Exp_If* exp_if) {
1287
7
  DECL_OB(const Instr, op, = emit_flow(emit, exp_if->cond))
1288

7
  CHECK_BB(emit_exp_pop_next(emit, exp_if->if_exp ?: exp_if->cond))
1289
7
  const Instr op2 = emit_add_instr(emit, Goto);
1290
7
  op->m_val = emit_code_size(emit);
1291
7
  const m_bool ret = emit_exp_pop_next(emit, exp_if->else_exp);
1292
7
  op2->m_val = emit_code_size(emit);
1293
7
  return ret;
1294
}
1295
1296
13
ANN static m_bool emit_lambda(const Emitter emit, const Exp_Lambda * lambda) {
1297
13
  CHECK_BB(emit_func_def(emit, lambda->def))
1298

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

1740
  if(isa(exp->info->type, emit->gwion->type[et_object]) > 0 &&
1343
438
    (exp->info->cast_to ? isa(exp->info->cast_to, emit->gwion->type[et_object]) > 0 : 1)) {
1344
212
    const Instr instr = emit_addref(emit, exp_getvar(exp));
1345
212
    instr->m_val = size;
1346
1302
  } else if(GET_FLAG(exp->info->type, struct)) // check cast_to ?
1347
    struct_addref(emit, exp->info->type, size, 0, exp_getvar(exp));
1348
1514
}
1349
1350
335
ANN2(1) static void emit_exp_addref(const Emitter emit, /* const */Exp exp, m_int size) {
1351
  do {
1352
335
    emit_exp_addref1(emit, exp, size);
1353
335
    size += exp_size(exp);
1354
335
  } while((exp = exp->next));
1355
260
}
1356
1357
5664
ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) {
1358
5664
  Exp exp = e;
1359
  do {
1360
5800
    CHECK_BB(emit_exp_func[exp->exp_type](emit, &exp->d))
1361
5796
    if(exp_getnonnull(exp))
1362
87
      emit_except(emit, exp->info->type);
1363
5796
    if(exp->info->cast_to)
1364
34
      CHECK_BB(emit_implicit_cast(emit, exp, exp->info->cast_to))
1365
5796
  } while((exp = exp->next));
1366
5660
  return GW_OK;
1367
}
1368
1369
34
ANN static m_bool emit_if(const Emitter emit, const Stmt_If stmt) {
1370
34
  DECL_OB(const Instr, op, = emit_flow(emit, stmt->cond))
1371
34
  CHECK_BB(scoped_stmt(emit, stmt->if_body, 1))
1372
34
  const Instr op2 = emit_add_instr(emit, Goto);
1373
34
  op->m_val = emit_code_size(emit);
1374
34
  if(stmt->else_body)
1375
12
    CHECK_BB(scoped_stmt(emit, stmt->else_body, 1))
1376
34
  op2->m_val = emit_code_size(emit);
1377
34
  return GW_OK;
1378
}
1379
1380
34
ANN static m_bool emit_stmt_if(const Emitter emit, const Stmt_If stmt) {
1381
34
  emit_push_scope(emit);
1382
34
  const m_bool ret = emit_if(emit, stmt);
1383
34
  emit_pop_scope(emit);
1384
34
  return ret;
1385
}
1386
1387
371
ANN static m_bool emit_stmt_code(const Emitter emit, const Stmt_Code stmt) {
1388
371
  ++emit->env->scope->depth;
1389
371
  const m_bool ret = stmt->stmt_list ? emit_stmt_list(emit, stmt->stmt_list) : 1;
1390
371
  --emit->env->scope->depth;
1391
371
  return ret;
1392
}
1393
1394
1
ANN static m_bool optimize_taill_call(const Emitter emit, const Exp_Call* e) {
1395
1
  if(e->args) {
1396
1
    emit_func_args(emit, e);
1397
1
    regpop(emit, e->m_func->def->stack_depth);
1398
1
    emit_args(emit, e->m_func);
1399
  }
1400
1
  emit_add_instr(emit, Goto);
1401
1
  return GW_OK;
1402
}
1403
1404
38
ANN static m_bool emit_stmt_return(const Emitter emit, const Stmt_Exp stmt) {
1405
38
  if(stmt->val) {
1406

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

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

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

2520
  if(pop && stmt->stmt_type == ae_stmt_exp && stmt->d.stmt_exp.val) {
1829
1974
    pop_exp(emit, stmt->d.stmt_exp.val);
1830
  }
1831
2520
  return GW_OK;
1832
}
1833
1834
2162
ANN static m_bool emit_stmt_list(const Emitter emit, Stmt_List l) {
1835
2162
  do CHECK_BB(emit_stmt(emit, l->stmt, 1))
1836
2158
  while((l = l->next));
1837
858
  return GW_OK;
1838
}
1839
1840
526
ANN static m_bool emit_exp_dot(const Emitter emit, const Exp_Dot* member) {
1841
2104
  struct Op_Import opi = { .op=insert_symbol("@dot"), .lhs=member->t_base,
1842
1578
    .rhs=exp_self(member)->info->type, .data=(uintptr_t)member, .pos=exp_self(member)->pos, .op_type=op_dot };
1843
526
  return op_emit_bool(emit, &opi);
1844
}
1845
1846
82
ANN static inline void emit_func_def_global(const Emitter emit, const Value value) {
1847
82
  const Instr set_mem = emit_add_instr(emit, MemSetImm);
1848
82
  set_mem->m_val = value->from->offset;
1849
82
  set_mem->m_val2 = (m_uint)value->d.func_ref->code;
1850
82
}
1851
1852
221
ANN static void emit_func_def_init(const Emitter emit, const Func func) {
1853
221
  const Type t = emit->env->class_def;
1854
221
  char c[(t ? strlen(t->name) + 1 : 0) + strlen(func->name) + 6];
1855

221
  sprintf(c, "%s%s%s(...)", t ? t->name : "", t ? "." : "", func->name);
1856
221
  emit_push_code(emit, c);
1857
221
}
1858
1859
157
ANN static void emit_func_def_args(const Emitter emit, Arg_List a) {
1860
  do {
1861
157
    const Type type = a->var_decl->value->type;
1862
157
    emit->code->stack_depth += type->size;
1863
157
    a->var_decl->value->from->offset = emit_local(emit, type);
1864
157
  } while((a = a->next));
1865
122
}
1866
1867
221
ANN static void emit_func_def_ensure(const Emitter emit, const Func_Def fdef) {
1868
221
  const m_uint size = fdef->base->ret_type->size;
1869
221
  if(size) {
1870
68
    const Instr instr = emit_kind(emit, size, 0, regpushimm);
1871
68
    instr->m_val2 = size;
1872
  }
1873
221
  vector_add(&emit->code->stack_return, (vtype)emit_add_instr(emit, Goto));
1874
221
}
1875
1876
221
ANN static void emit_func_def_return(const Emitter emit) {
1877
221
  const m_uint val = emit_code_size(emit);
1878
  LOOP_OPTIM
1879
700
  for(m_uint i = vector_size(&emit->code->stack_return) + 1; --i; ) {
1880
258
    const Instr instr = (Instr)vector_at(&emit->code->stack_return, i-1);
1881
258
    instr->m_val = val;
1882
  }
1883
221
  vector_clear(&emit->code->stack_return);
1884

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

221
  if(emit->info->memoize && GET_FLAG(fdef->base->func, pure))
1980
1
    CHECK_BB(emit_memoize(emit, fdef))
1981
221
  CHECK_BB(emit_func_def_body(emit, fdef))
1982
221
  emit_func_def_return(emit);
1983
221
  return GW_OK;
1984
}
1985
1986
442
static ANN int fdef_is_file_global(const Emitter emit, const Func_Def fdef) {
1987
868
  return isa(fdef->base->func->value_ref->type, emit->gwion->type[et_lambda]) < 0 &&
1988


826
    !emit->env->class_def && !GET_FLAG(fdef, global) && !fdef->base->tmpl &&
1989
166
    !emit->env->scope->depth;
1990
}
1991
1992
221
ANN static void emit_fdef_finish(const Emitter emit, const Func_Def fdef) {
1993
221
  const Func func = fdef->base->func;
1994
221
  func->code = emit_func_def_code(emit, func);
1995
221
  if(fdef_is_file_global(emit, fdef))
1996
82
    emit_func_def_global(emit, func->value_ref);
1997

221
  if(emit->info->memoize && GET_FLAG(func, pure))
1998
1
    func->code->memoize = memoize_ini(emit, func);
1999
221
}
2000
2001
264
ANN static m_bool emit_func_def(const Emitter emit, const Func_Def f) {
2002
264
  const Func func = f->base->func;
2003
264
  const Func_Def fdef = func->def;
2004
264
  const Func former = emit->env->func;
2005

264
  if(func->code || tmpl_base(fdef->base->tmpl))
2006
43
    return GW_OK;
2007

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

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

6
  if(cdef->base.tmpl && cdef->base.tmpl->list)
2063
4
    nspc_pop_type(emit->gwion->mp, emit->env->curr);
2064
6
  return ret;
2065
}
2066
2067
182
ANN static m_bool emit_class_def(const Emitter emit, const Class_Def cdef) {
2068
182
  if(tmpl_base(cdef->base.tmpl))
2069
19
    return GW_OK;
2070
163
  const Type t = cdef->base.type;
2071
163
  if(GET_FLAG(t, emit))
2072
    return GW_OK;
2073
163
  SET_FLAG(t, emit);
2074

163
  if(t->e->owner_class && !GET_FLAG(t->e->owner_class, emit))
2075
    CHECK_BB(ensure_emit(emit, t->e->owner_class))
2076

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