GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/lib/array.c Lines: 322 347 92.8 %
Date: 2020-09-14 09:03:05 Branches: 97 122 79.5 %

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#include "gwion_util.h"
4
#include "gwion_ast.h"
5
#include "gwion_env.h"
6
#include "vm.h"
7
#include "gwion.h"
8
#include "instr.h"
9
#include "object.h"
10
#include "array.h"
11
#include "emit.h"
12
#include "operator.h"
13
#include "import.h"
14
#include "traverse.h"
15
#include "parse.h"
16
#include "gwi.h"
17
#include "emit.h"
18
19
struct M_Vector_ {
20
  m_bit* ptr;
21
};
22
#define ARRAY_OFFSET SZ_INT * 4
23
#define ARRAY_PTR(array) (array->ptr + ARRAY_OFFSET)
24
#define ARRAY_LEN(array) *(m_uint*)(array->ptr)
25
#define ARRAY_SIZE(array) *(m_uint*)(array->ptr + SZ_INT)
26
#define ARRAY_CAP(array) *(m_uint*)(array->ptr + SZ_INT*2)
27
28
68
ANN m_uint m_vector_size(const M_Vector v) {
29
68
  return ARRAY_LEN(v);
30
}
31
32
503
M_Vector new_m_vector(MemPool p, const m_uint size, const m_uint len) {
33
503
  const M_Vector array = mp_calloc(p, M_Vector);
34
503
  const size_t sz = (ARRAY_OFFSET*SZ_INT) + (len*size);
35
503
  array->ptr   = (m_bit*)xcalloc(1, sz);
36
503
  m_uint cap = 1;
37
2279
  while(cap < len)
38
1273
    cap *= 2;
39
503
  ARRAY_CAP(array)   = cap;
40
503
  ARRAY_SIZE(array)  = size;
41
503
  ARRAY_LEN(array) = len;
42
503
  return array;
43
}
44
45
503
void free_m_vector(MemPool p, M_Vector a) {
46
503
  xfree(a->ptr);
47
503
  mp_free(p, M_Vector, a);
48
503
}
49
50
ANN static inline int is_array(const Type *types, const Type type) {
51
  const Type base = array_base(type);
52
  return isa(base, types[et_object]) > 0;
53
}
54
55
503
static DTOR(array_dtor) {
56
503
  const Type t = unflag_type(o->type_ref);
57
503
  if(*(void**)(o->data + SZ_INT))
58
    xfree(*(void**)(o->data + SZ_INT));
59
503
  struct M_Vector_* a = ARRAY(o);
60
503
  if(!a)
61
    return;
62
503
  if(t->nspc->info->class_data_size) {
63
2526
    for(m_uint i = 0; i < ARRAY_LEN(a); ++i)
64
2072
      (*(f_release**)t->nspc->info->class_data)(shred, array_base(t), ARRAY_PTR(a) + i * ARRAY_SIZE(a));
65
  }
66
503
  free_m_vector(shred->info->mp, a);
67
}
68
69
503
ANN M_Object new_array(MemPool p, const Type t, const m_uint length) {
70
503
  const M_Object a = new_object(p, NULL, t);
71
503
  const m_uint depth = t->array_depth;
72
503
  const m_uint size = depth > 1 ? SZ_INT : array_base(t)->size;
73
503
  ARRAY(a) = new_m_vector(p, size,length);
74
503
  return a;
75
}
76
77
48
ANN void m_vector_get(const M_Vector v, const m_uint i, void* c) {
78
48
  const m_uint size = ARRAY_SIZE(v);
79
48
  memcpy(c, ARRAY_PTR(v) + i * size, size);
80
48
}
81
82
2
ANN void m_vector_add(const M_Vector v, const void* data) {
83
2
  const m_uint size = ARRAY_SIZE(v);
84
2
  if(++ARRAY_LEN(v) >= ARRAY_CAP(v)) {
85
2
    const m_uint cap = ARRAY_CAP(v) *=2;
86
2
    v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size);
87
  }
88
2
  memcpy(ARRAY_PTR(v) + (ARRAY_LEN(v) - 1) * size, data, size);
89
2
}
90
91
463
ANN void m_vector_set(const M_Vector v, const m_uint i, const void* data) {
92
463
  const m_uint size = ARRAY_SIZE(v);
93
463
  memcpy(ARRAY_PTR(v) + i * size, data, size);
94
463
}
95
96
2
ANN void m_vector_rem(const M_Vector v, m_uint index) {
97
2
  const m_uint size = ARRAY_SIZE(v);
98
2
  if(index < ARRAY_LEN(v) - 1)
99
2
    memmove(ARRAY_PTR(v) + index * size, ARRAY_PTR(v) + (index + 1) * size,
100
2
      (ARRAY_SIZE(v) - index - 1) *size);
101
2
  --ARRAY_LEN(v);
102
2
  if(ARRAY_LEN(v) < ARRAY_CAP(v) / 2) {
103
1
    const m_uint cap = ARRAY_CAP(v) /= 2;
104
1
    v->ptr = (m_bit*)xrealloc(v->ptr, ARRAY_OFFSET + cap * size);
105
  }
106
2
}
107
108
2
static MFUN(vm_vector_rem) {
109
2
  const m_int index = *(m_int*)(shred->mem + SZ_INT);
110
2
  const M_Vector v = ARRAY(o);
111

2
  if(index < 0 || (m_uint)index >= ARRAY_LEN(v))
112
    return;
113
2
  const Type t = unflag_type(o->type_ref);
114
2
  if(t->nspc->info->class_data_size)
115
2
    (*(f_release**)t->nspc->info->class_data)(shred, array_base(t), ARRAY_PTR(v) + index * ARRAY_SIZE(v));
116
2
  m_vector_rem(v, (vtype)index);
117
}
118
119
1639
ANN m_bit* m_vector_addr(const M_Vector v, const m_uint i) {
120
1639
  return &*(m_bit*)(ARRAY_PTR(v) + i * ARRAY_SIZE(v));
121
}
122
123
14
static MFUN(vm_vector_size) {
124
14
  *(m_uint*)RETURN = ARRAY_LEN(ARRAY(o));
125
14
}
126
127
2
static MFUN(vm_vector_depth) {
128
2
  *(m_uint*)RETURN = o->type_ref->array_depth;
129
2
}
130
131
2
static MFUN(vm_vector_cap) {
132
2
  *(m_uint*)RETURN = ARRAY_CAP(ARRAY(o));
133
2
}
134
135
18
ANN static Type get_array_type(Type t) {
136
51
  while(t->e->d.base_type)
137
15
    t = t->e->d.base_type;
138
18
  return t;
139
}
140
141
#define ARRAY_OPCK                                        \
142
  const Type l = get_array_type(bin->lhs->info->type);    \
143
  const Type r = get_array_type(bin->rhs->info->type);    \
144
  if(isa(l, r) < 0)                                       \
145
    ERR_N(exp_self(bin)->pos, _("array types do not match."))
146
147
8
static OP_CHECK(opck_array_at) {
148
8
  const Exp_Binary* bin = (Exp_Binary*)data;
149
8
  if(opck_const_rhs(env, data, mut) == env->gwion->type[et_null])
150
1
    return env->gwion->type[et_null];
151
7
  if(bin->lhs->info->type != env->gwion->type[et_null]) {
152
6
    ARRAY_OPCK
153
5
    if(bin->lhs->info->type->array_depth != bin->rhs->info->type->array_depth)
154
1
      ERR_N(exp_self(bin)->pos, _("array depths do not match."))
155
  }
156
5
  if(bin->rhs->exp_type == ae_exp_decl) {
157
3
    SET_FLAG(bin->rhs->d.exp_decl.td, ref);
158

4
    if(bin->rhs->d.exp_decl.list->self->array &&
159
1
          bin->rhs->d.exp_decl.list->self->array->exp)
160
1
      ERR_N(exp_self(bin)->pos, _("do not provide array for 'xxx @=> declaration'."))
161
  }
162
4
  exp_setvar(bin->rhs, 1);
163
4
  return bin->rhs->info->type;
164
}
165
166
3
static OP_CHECK(opck_array_shift) {
167
3
  const Exp_Binary* bin = (Exp_Binary*)data;
168

3
  if(bin->rhs->info->type == env->gwion->type[et_null] &&
169
      bin->lhs->info->type->array_depth > 1)
170
    return bin->lhs->info->type;
171
3
  ARRAY_OPCK
172
3
  if(bin->lhs->info->type->array_depth != bin->rhs->info->type->array_depth + 1)
173
1
    ERR_N(exp_self(bin)->pos, "array depths do not match for '<<'.");
174
2
  return bin->lhs->info->type;
175
}
176
177
2
static OP_EMIT(opem_array_shift) {
178
2
  const Exp_Binary* bin = (Exp_Binary*)data;
179
2
  const Type type = bin->rhs->info->type;
180
2
  const Instr pop = emit_add_instr(emit, RegPop);
181
2
  pop->m_val = type->size;
182
2
  return emit_add_instr(emit, ArrayAppend);
183
}
184
185
// check me. use common ancestor maybe
186
2
static OP_CHECK(opck_array_cast) {
187
2
  const Exp_Cast* cast = (Exp_Cast*)data;
188
2
  Type l = cast->exp->info->type;
189
2
  Type r = exp_self(cast)->info->type;
190
5
  while(!l->e->d.base_type)
191
1
    l = l->e->parent;
192
5
  while(!r->e->d.base_type)
193
1
    r = r->e->parent;
194

2
  if(get_depth(cast->exp->info->type) == get_depth(exp_self(cast)->info->type) && isa(l->e->d.base_type, r->e->d.base_type) > 0)
195
1
    return l;
196
1
  return env->gwion->type[et_null];
197
}
198
199
4
static OP_CHECK(opck_array_slice) {
200
4
  const Exp e = (Exp)data;
201
4
  exp_setmeta(exp_self(e), 1);
202
4
  exp_setnonnull(e->d.exp_slice.base, 1);
203
4
  return e->d.exp_slice.base->info->type;
204
}
205
206
7
static inline m_bool bounds(const M_Vector v, const m_int i) {
207
7
  CHECK_BB(i)
208
7
  return (m_uint)i < ARRAY_LEN(v) ? GW_OK : GW_ERROR;
209
}
210
211
4
static INSTR(ArraySlice) {
212
4
  shred->reg -= SZ_INT *2;
213
4
  const M_Object array = *(M_Object*)REG(-SZ_INT);
214
4
  const M_Vector in = ARRAY(array);
215
4
  const m_int start = *(m_uint*)REG(0);
216
4
  m_int end   = *(m_uint*)REG(SZ_INT);
217
4
  if(end < 0)
218
2
    end = ARRAY_LEN(in) + end;
219
4
  const m_int op    = start < end ? 1 : -1;
220
4
  const m_uint sz    = op > 0 ? end - start : start - end;
221

4
  if(bounds(in, start) < 0 || bounds(in, end) < 0)
222
1
    Except(shred, "OutOfBoundsArraySliceException");
223
3
  const M_Object out = new_array(shred->info->vm->gwion->mp, array->type_ref, sz);
224
6
  for(m_int i = start, j = 0; i != end; i += op, ++j) {
225
3
    m_bit buf[ARRAY_SIZE(in)];
226
3
    m_vector_get(in, i, &buf);
227
3
    m_vector_set(ARRAY(out), j, buf);
228
  }
229
3
  *(M_Object*)REG(-SZ_INT) = out;
230
}
231
232
4
static OP_EMIT(opem_array_slice) {
233
4
  emit_add_instr(emit, ArraySlice);
234
4
  return emit_add_instr(emit, GcAdd);
235
}
236
237
36
static FREEARG(freearg_array) {
238
36
  ArrayInfo* info = (ArrayInfo*)instr->m_val;
239
36
  vector_release(&info->type);
240
36
  mp_free(((Gwion)gwion)->mp, ArrayInfo, info);
241
36
}
242
243
4
static OP_CHECK(opck_not_array) {
244
4
  const Array_Sub array = (Array_Sub)data;
245
4
  if(get_depth(array->type)) {
246
2
    struct Array_Sub_ next = { array->exp, array->type->e->parent, array->depth };
247
2
    return check_array_access(env, &next);
248
  }
249
2
  ERR_O(array->exp->pos, _("array subscripts (%"UINT_F") exceeds defined dimension (%"UINT_F")"),
250
        array->depth, get_depth(array->type))
251
}
252
253
ANN Type check_array_access(const Env env, const Array_Sub array);
254
255
29
static OP_CHECK(opck_array) {
256
29
  const Array_Sub array = (Array_Sub)data;
257
29
  const Type t_int = env->gwion->type[et_int];
258
29
  Exp e = array->exp;
259
43
  do CHECK_BO(check_implicit(env, e, t_int))
260
43
  while((e = e->next));
261
29
  const Type t = array->type;
262
29
  if(t->array_depth >= array->depth)
263
27
    return array_type(env, array_base(t), t->array_depth - array->depth);
264
2
  const Exp curr = take_exp(array->exp, array->type->array_depth);
265
2
  struct Array_Sub_ next = { curr->next, array_base(array->type), array->depth - array->type->array_depth };
266
2
  return check_array_access(env, &next);
267
}
268
269
25
ANN static void array_loop(const Emitter emit, const m_uint depth) {
270
25
  const Instr pre_pop = emit_add_instr(emit, RegPop);
271
25
  pre_pop->m_val = depth * SZ_INT;
272
25
  emit_add_instr(emit, GWOP_EXCEPT);
273
37
  for(m_uint i = 0; i < depth - 1; ++i) {
274
12
    const Instr access = emit_add_instr(emit, ArrayAccess);
275
12
    access->m_val = i * SZ_INT;
276
12
    access->m_val2 = !i ? SZ_INT : 0;
277
12
    const Instr get = emit_add_instr(emit, ArrayGet);
278
12
    get->m_val = i * SZ_INT;
279
12
    get->m_val2 = -SZ_INT;
280
12
    emit_add_instr(emit, GWOP_EXCEPT);
281
  }
282
25
  const Instr post_pop = emit_add_instr(emit, RegPop);
283
25
  post_pop->m_val = SZ_INT;
284
25
  const Instr access = emit_add_instr(emit, ArrayAccess);
285
25
  access->m_val = depth * SZ_INT;
286
25
}
287
288
25
ANN static void array_finish(const Emitter emit, const m_uint depth,
289
		const m_uint size, const m_bool is_var) {
290
25
  const Instr get = emit_add_instr(emit, is_var ? ArrayAddr : ArrayGet);
291
25
  get->m_val = depth * SZ_INT;
292
25
  const Instr push = emit_add_instr(emit, ArrayValid);
293
25
  push->m_val = is_var ? SZ_INT : size;
294
25
}
295
296
25
ANN static inline m_bool array_do(const  Emitter emit, const Array_Sub array, const m_bool is_var) {
297
25
  emit_add_instr(emit, GcAdd);
298
25
  CHECK_BB(emit_exp(emit, array->exp))
299
25
  array_loop(emit, array->depth);
300
25
  array_finish(emit, array->depth, array->type->size, is_var);
301
25
  return GW_OK;
302
}
303
ANN static inline Exp emit_n_exp(const Emitter emit,  struct ArrayAccessInfo *const info) {
304
  const Exp e = take_exp(info->array.exp, info->array.depth);
305
  const Exp next = e->next;
306
  e->next = NULL;
307
  struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.depth };
308
  const m_bool ret = array_do(emit, &partial, 0);
309
  e->next = next;
310
  return ret > 0 ? next : NULL;
311
}
312
313
25
static OP_EMIT(opem_array_access) {
314
25
  struct ArrayAccessInfo *const info = (struct ArrayAccessInfo*)data;
315
25
  if(info->array.type->array_depth >= info->array.depth) {
316
25
    struct Array_Sub_ next = { .exp=info->array.exp, .type=info->type, .depth=info->array.depth };
317
25
    return (Instr)(m_uint)array_do(emit, &next, info->is_var);
318
  }
319
  struct Array_Sub_ partial = { info->array.exp, info->array.type, info->array.type->array_depth };
320
  struct Array_Sub_ next = { info->array.exp, array_base(info->array.type), info->array.depth - info->array.type->array_depth };
321
  info->array = partial;
322
  const Exp exp = emit_n_exp(emit, info);
323
  next.exp = exp;
324
  info->array = next;
325
  return (Instr)(m_uint)(exp ? emit_array_access(emit, info) : GW_ERROR);
326
}
327
328
711
GWION_IMPORT(array) {
329
711
  const Type t_array  = gwi_class_ini(gwi, "@Array", NULL);
330
711
  gwi->gwion->type[et_array] = t_array;
331
711
  gwi_class_xtor(gwi, NULL, array_dtor);
332
711
  GWI_BB(gwi_item_ini(gwi, "@internal", "@array"))
333
711
  GWI_BB(gwi_item_end(gwi, 0, NULL))
334
711
  GWI_BB(gwi_item_ini(gwi, "@internal", "@ctor_data"))
335
711
  GWI_BB(gwi_item_end(gwi, 0, NULL))
336
337
711
  GWI_BB(gwi_func_ini(gwi, "int", "size"))
338
711
  GWI_BB(gwi_func_end(gwi, vm_vector_size, ae_flag_none))
339
711
  GWI_BB(gwi_func_ini(gwi, "int", "depth"))
340
711
  GWI_BB(gwi_func_end(gwi, vm_vector_depth, ae_flag_none))
341
342
711
  GWI_BB(gwi_func_ini(gwi, "int", "cap"))
343
711
  GWI_BB(gwi_func_end(gwi, vm_vector_cap, ae_flag_none))
344
345
711
  GWI_BB(gwi_func_ini(gwi, "int", "remove"))
346
711
  GWI_BB(gwi_func_arg(gwi, "int", "index"))
347
711
  GWI_BB(gwi_func_end(gwi, vm_vector_rem, ae_flag_none))
348
349
711
  GWI_BB(gwi_class_end(gwi))
350
711
  GWI_BB(gwi_oper_ini(gwi, "@Array", "@Array", NULL))
351
711
  GWI_BB(gwi_oper_add(gwi, opck_array_at))
352
711
  GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign))
353
711
  GWI_BB(gwi_oper_ini(gwi, "@null", "@Array", NULL))
354
711
  GWI_BB(gwi_oper_add(gwi, opck_array_at))
355
711
  GWI_BB(gwi_oper_end(gwi, "@=>", ObjectAssign))
356
711
  GWI_BB(gwi_oper_ini(gwi, "nonnull @Array", (m_str)OP_ANY_TYPE, NULL))
357
711
  GWI_BB(gwi_oper_add(gwi, opck_array_shift))
358
711
  GWI_BB(gwi_oper_emi(gwi, opem_array_shift))
359
711
  GWI_BB(gwi_oper_end(gwi, "<<", NULL))
360
711
  GWI_BB(gwi_oper_ini(gwi, "@Array", "@Array", NULL))
361
711
  GWI_BB(gwi_oper_add(gwi, opck_array_cast))
362
711
  GWI_BB(gwi_oper_end(gwi, "$", NULL))
363
711
  GWI_BB(gwi_oper_ini(gwi, "int", "nonnull @Array", "int"))
364
711
  GWI_BB(gwi_oper_add(gwi, opck_array_slice))
365
711
  GWI_BB(gwi_oper_emi(gwi, opem_array_slice))
366
711
  GWI_BB(gwi_oper_end(gwi, "@slice", NULL))
367
711
  GWI_BB(gwi_oper_ini(gwi, "int", (m_str)OP_ANY_TYPE, NULL))
368
711
  GWI_BB(gwi_oper_add(gwi, opck_not_array))
369
711
  GWI_BB(gwi_oper_end(gwi, "@array", NULL))
370
711
  GWI_BB(gwi_oper_ini(gwi, "int", "@Array", NULL))
371
711
  GWI_BB(gwi_oper_add(gwi, opck_array))
372
711
  GWI_BB(gwi_oper_emi(gwi, opem_array_access))
373
711
  GWI_BB(gwi_oper_end(gwi, "@array", NULL))
374
711
  gwi_register_freearg(gwi, ArrayAlloc, freearg_array);
375
711
  return GW_OK;
376
}
377
378
INSTR(ArrayStruct) {
379
  const M_Object ref = *(M_Object*)(REG(-SZ_INT * 5));
380
  const m_int idx = (*(m_int*)((shred->reg -SZ_INT * 3)))++;
381
  *(m_bit**)(shred->reg) = m_vector_addr(ARRAY(ref), idx);
382
  shred->reg += SZ_INT; // regpush
383
}
384
385
1619
INSTR(ArrayBottom) {
386
1619
  *(M_Object*)(*(m_uint**)REG(-SZ_INT * 4))[(*(m_int*)REG(-SZ_INT * 3))++] = *(M_Object*)REG(-SZ_INT);
387
1619
}
388
389
12
INSTR(ArrayPost) {
390
12
  xfree(*(m_uint**)REG(0));
391
12
  const M_Object o = *(M_Object*)(REG(-SZ_INT));
392
12
  *(m_uint*)(o->data + SZ_INT) = 0;
393
12
}
394
395
10
INSTR(ArrayInit) {// for litteral array
396
10
  const Type t = (Type)instr->m_val;
397
10
  const m_uint sz = *(m_uint*)REG(0);
398
10
  const m_uint off = instr->m_val2 * sz;
399
10
  POP_REG(shred, off - SZ_INT);
400
10
  const M_Object obj = new_array(shred->info->mp, t, sz);
401
10
  memcpy(ARRAY(obj)->ptr + ARRAY_OFFSET, REG(-SZ_INT), off);
402
10
  *(M_Object*)REG(-SZ_INT) = obj;
403
10
}
404
405
#define TOP -1
406
407
488
ANN static inline M_Object do_alloc_array_object(MemPool p, const ArrayInfo* info, const m_int cap) {
408
488
  struct Vector_ v = info->type;
409
488
  const Type t = (Type)vector_at(&v, (vtype)(-info->depth - 1));
410
488
  return new_array(p, t, (m_uint)cap);
411
}
412
413
331
ANN static inline M_Object do_alloc_array_init(ArrayInfo* info, const m_uint cap,
414
    const M_Object base) {
415
1950
  for(m_uint i = 0; i < cap; ++i)
416
1619
    info->data[(*info->d.idx)++] = (M_Object)m_vector_addr(ARRAY(base), i);
417
331
  return base;
418
}
419
420
ANN static M_Object do_alloc_array(const VM_Shred shred, ArrayInfo* info);
421
123
ANN static M_Object do_alloc_array_loop(const VM_Shred shred, ArrayInfo* info,
422
    const m_uint cap, const M_Object base) {
423
576
  for(m_uint i = 0; i < cap; ++i) {
424
2270
    struct ArrayInfo_ aai = { info->depth + 1, info->type,
425
1816
      info->base, info->data, { info->d.idx } , 0, info->is_obj };
426
454
    const M_Object next = do_alloc_array(shred, &aai);
427
454
    if(!next) {
428
1
      _release(base, shred);
429
1
      return NULL;
430
    }
431
453
    m_vector_set(ARRAY(base), i, &next);
432
  }
433
122
  return base;
434
}
435
436
490
ANN static M_Object do_alloc_array(const VM_Shred shred, ArrayInfo* info) {
437
490
  const m_int cap = *(m_int*)REG(info->depth * SZ_INT);
438
490
  if(cap < 0) {
439
2
    gw_err("[gwion](VM): NegativeArraySize: while allocating arrays...\n");
440
2
    return NULL;
441
  }
442
488
  const M_Object base = do_alloc_array_object(shred->info->mp, info, cap);
443

1184
  return info->depth < TOP ? do_alloc_array_loop(shred, info, (m_uint)cap, base) :
444
696
    info->data ? do_alloc_array_init(info, (m_uint)cap, base) : base;
445
}
446
447
12
ANN static M_Object* init_array(const VM_Shred shred, const ArrayInfo* info, m_uint* num_obj) {
448
12
  m_int curr = -info->depth;
449
49
  while(curr <= TOP) {
450
25
    *num_obj *= *(m_uint*)REG(SZ_INT * curr);
451
25
    ++curr;
452
  }
453
12
  return *num_obj > 0 ? (M_Object*)xcalloc(*num_obj, info->base->size) : NULL;
454
}
455
456
36
INSTR(ArrayAlloc) {
457
36
  const ArrayInfo* info = (ArrayInfo*)instr->m_val;
458
36
  m_uint num_obj = 1;
459
36
  m_int idx = 0;
460

36
  const m_bool is_obj = info->is_obj && !info->is_ref;
461
72
  struct ArrayInfo_ aai = { -info->depth, info->type, info->base,
462
36
         NULL, { &idx }, 0, info->is_obj};
463
36
  if(is_obj)
464
12
    aai.data = init_array(shred, info, &num_obj);
465
36
  const M_Object ref = do_alloc_array(shred, &aai);
466
36
  if(!ref) {
467
2
    gw_err("[Gwion](VM): (note: in shred[id=%" UINT_F ":%s])\n", shred->tick->xid, shred->info->name);
468
2
    vm_shred_exit(shred);
469
2
    return; // TODO make exception vararg
470
  }
471
34
  *(void**)(ref->data + SZ_INT) = aai.data;
472
34
  vector_add(&shred->gc, (m_uint)ref);
473
34
  if(!is_obj) {
474
22
    POP_REG(shred, SZ_INT * (info->depth - 1));
475
22
    *(M_Object*)REG(-SZ_INT) = ref;
476
  } else {
477
12
    POP_REG(shred, SZ_INT * (info->depth - 4));
478
12
    *(M_Object*)REG(-SZ_INT*4) = ref;
479
12
    *(M_Object**)REG(-SZ_INT*3) = aai.data;
480
12
    *(m_uint*) REG(-SZ_INT*2) = 0;
481
12
    *(m_uint*) REG(-SZ_INT) = num_obj;
482
  }
483
}
484