• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nickg / nvc / 16099227452

06 Jul 2025 12:45PM UTC coverage: 92.335% (+0.05%) from 92.284%
16099227452

push

github

nickg
Handle underscores in Verilog decimal literals

Fixes #1230

18 of 20 new or added lines in 1 file covered. (90.0%)

598 existing lines in 16 files now uncovered.

71069 of 76969 relevant lines covered (92.33%)

564781.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.21
/src/jit/jit-irgen.c
1
//
2
//  Copyright (C) 2022-2025  Nick Gasson
3
//
4
//  This program is free software: you can redistribute it and/or modify
5
//  it under the terms of the GNU General Public License as published by
6
//  the Free Software Foundation, either version 3 of the License, or
7
//  (at your option) any later version.
8
//
9
//  This program is distributed in the hope that it will be useful,
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
//  GNU General Public License for more details.
13
//
14
//  You should have received a copy of the GNU General Public License
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

18
#include "util.h"
19
#include "cov/cov-api.h"
20
#include "diag.h"
21
#include "jit/jit-ffi.h"
22
#include "jit/jit-ffi.h"
23
#include "jit/jit-priv.h"
24
#include "mask.h"
25
#include "mir/mir-node.h"
26
#include "mir/mir-unit.h"
27
#include "option.h"
28
#include "rt/rt.h"
29
#include "tree.h"
30

31
#include <assert.h>
32
#include <inttypes.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <limits.h>
36

37
typedef struct _irgen_label irgen_label_t;
38
typedef struct _patch_list  patch_list_t;
39

40
#define PATCH_CHUNK_SZ  4
41
#define MAX_STACK_ALLOC 65536
42
#define DEDUP_PREFIX    16384
43

44
struct _patch_list {
45
   patch_list_t *next;
46
   unsigned      count;
47
   unsigned      offsets[PATCH_CHUNK_SZ];
48
};
49

50
struct _irgen_label {
51
   jit_label_t    label;
52
   unsigned       uses;
53
   patch_list_t   patchlist;
54
   irgen_label_t *next;
55
};
56

57
typedef struct {
58
   jit_func_t     *func;
59
   jit_value_t    *vars;
60
   jit_value_t    *params;
61
   jit_reg_t       next_reg;
62
   jit_value_t    *map;
63
   irgen_label_t  *labels;
64
   irgen_label_t **blocks;
65
   mir_unit_t     *mu;
66
   size_t          cpoolptr;
67
   size_t          oldptr;
68
   jit_value_t     statereg;
69
   jit_value_t     contextarg;
70
   mir_value_t     flags;
71
   mir_block_t     curblock;
72
   unsigned        bufsz;
73
   bool            used_tlab;
74
   bool            stateless;
75
   bool            needs_context;
76
} jit_irgen_t;
77

78
////////////////////////////////////////////////////////////////////////////////
79
// IR emission
80

81
static inline jit_value_t jit_value_from_reg(jit_reg_t reg)
2,143,981✔
82
{
83
   jit_value_t value = { .kind = JIT_VALUE_REG, .reg = reg };
2,143,981✔
84
   return value;
2,143,981✔
85
}
86

87
static inline jit_value_t jit_value_from_int64(int64_t immed)
4,907,607✔
88
{
89
   jit_value_t value = { .kind = JIT_VALUE_INT64, .int64 = immed };
4,907,607✔
90
   return value;
4,907,607✔
91
}
92

93
static inline jit_value_t jit_value_from_double(double immed)
30,289✔
94
{
95
   return (jit_value_t){ .kind = JIT_VALUE_DOUBLE, .dval = immed };
30,289✔
96
}
97

98
static inline jit_value_t jit_value_from_cpool_addr(int offset)
44,457✔
99
{
100
   jit_value_t value = { .kind = JIT_ADDR_CPOOL, .int64 = offset };
44,457✔
101
   return value;
44,457✔
102
}
103

104
static inline jit_value_t jit_value_from_loc(const loc_t *loc)
1,731,474✔
105
{
106
   jit_value_t value = { .kind = JIT_VALUE_LOC, .loc = *loc };
1,731,474✔
107
   return value;
1,731,474✔
108
}
109

110
static inline jit_value_t jit_null_ptr(void)
37,056✔
111
{
112
   jit_value_t value = { .kind = JIT_ADDR_ABS, .int64 = 0 };
37,056✔
113
   return value;
37,056✔
114
}
115

116
static inline jit_reg_t jit_value_as_reg(jit_value_t value)
306,901✔
117
{
118
   assert(value.kind == JIT_VALUE_REG);
306,901✔
119
   return value.reg;
306,901✔
120
}
121

122
static inline bool jit_value_is_addr(jit_value_t value)
659,805✔
123
{
124
   switch (value.kind) {
659,805✔
125
   case JIT_ADDR_ABS:
126
   case JIT_ADDR_CPOOL:
127
   case JIT_ADDR_REG:
128
      return true;
129
   default:
571,952✔
130
      return false;
571,952✔
131
   }
132
}
133

134
static jit_value_t jit_addr_from_value(jit_value_t value, int32_t disp)
928,538✔
135
{
136
   switch (value.kind) {
928,538✔
137
   case JIT_VALUE_REG:
435,273✔
138
      return (jit_value_t){
435,273✔
139
         .kind = JIT_ADDR_REG,
140
         .disp = disp,
141
         .reg = value.reg
435,273✔
142
      };
143
   case JIT_VALUE_INT64:
4,062✔
144
   case JIT_ADDR_ABS:
145
      return (jit_value_t){
4,062✔
146
         .kind = JIT_ADDR_ABS,
147
         .int64 = value.int64 + disp
4,062✔
148
      };
149
   case JIT_ADDR_CPOOL:
21,020✔
150
      return (jit_value_t){
21,020✔
151
         .kind = value.kind,
152
         .int64 = value.int64 + disp
21,020✔
153
      };
154
   case JIT_ADDR_REG:
468,183✔
155
      return (jit_value_t){
468,183✔
156
         .kind = JIT_ADDR_REG,
157
         .disp = value.disp + disp,
468,183✔
158
         .reg = value.reg
468,183✔
159
      };
160
   default:
×
161
      fatal_trace("cannot convert value kind %d to address", value.kind);
162
   }
163
}
164

165
static jit_value_t jit_addr_from_cover_tag(uint32_t tag)
3,109✔
166
{
167
   return (jit_value_t){
3,109✔
168
      .kind = JIT_ADDR_COVER,
169
      .int64 = tag,
170
   };
171
}
172

173
static jit_value_t jit_value_from_label(irgen_label_t *l)
266,729✔
174
{
175
   return (jit_value_t){ .kind = JIT_VALUE_LABEL, .label = l->label };
266,729✔
176
}
177

178
static jit_value_t jit_value_from_handle(jit_handle_t handle)
150,973✔
179
{
180
   return (jit_value_t){ .kind = JIT_VALUE_HANDLE, .handle = handle };
150,973✔
181
}
182

183
static jit_value_t jit_value_from_exit(jit_exit_t exit)
180,130✔
184
{
185
   return (jit_value_t){ .kind = JIT_VALUE_EXIT, .exit = exit };
180,130✔
186
}
187

188
static jit_ir_t *irgen_append(jit_irgen_t *g)
5,543,219✔
189
{
190
   if (g->func->nirs == g->bufsz) {
5,543,219✔
191
      g->bufsz = MAX(g->bufsz * 2, 1024);
72,106✔
192
      g->func->irbuf = xrealloc_array(g->func->irbuf, g->bufsz,
72,106✔
193
                                      sizeof(jit_ir_t));
194
   }
195

196
   return &(g->func->irbuf[g->func->nirs++]);
5,543,219✔
197
}
198

199
static jit_reg_t irgen_alloc_reg(jit_irgen_t *g)
1,829,944✔
200
{
201
   if (unlikely(g->next_reg == JIT_REG_INVALID))
1,829,944✔
202
      fatal("unit %s is too big to compile", istr(g->func->name));
×
203
   else
204
      return g->next_reg++;
1,829,944✔
205
}
206

207
static irgen_label_t *irgen_alloc_label(jit_irgen_t *g)
326,207✔
208
{
209
   irgen_label_t *l = xcalloc(sizeof(irgen_label_t));
326,207✔
210
   l->next  = g->labels;
326,207✔
211
   l->label = JIT_LABEL_INVALID;
326,207✔
212

213
   return (g->labels = l);
326,207✔
214
}
215

216
static void irgen_bind_label(jit_irgen_t *g, irgen_label_t *l)
326,207✔
217
{
218
   assert(l->label == JIT_LABEL_INVALID);
326,207✔
219

220
   l->label = g->func->nirs;
326,207✔
221

222
   for (patch_list_t *p = &(l->patchlist); p; p = p->next) {
652,487✔
223
      for (int i = 0; i < p->count; i++) {
556,643✔
224
         jit_ir_t *ir = &(g->func->irbuf[p->offsets[i]]);
230,363✔
225
         if (ir->arg1.kind == JIT_VALUE_LABEL)
230,363✔
226
            ir->arg1.label = l->label;
202,509✔
227
         else if (ir->arg2.kind == JIT_VALUE_LABEL)
27,854✔
228
            ir->arg2.label = l->label;
27,854✔
229
         else
230
            fatal_trace("cannot find label argument to patch");
231
      }
232
   }
233

234
   for (patch_list_t *p = l->patchlist.next, *tmp; p; p = tmp) {
326,280✔
235
      tmp = p->next;
73✔
236
      free(p);
73✔
237
   }
238
}
326,207✔
239

240
static jit_cc_t irgen_get_jit_cc(mir_cmp_t cmp)
50,892✔
241
{
242
   switch (cmp) {
50,892✔
243
   case MIR_CMP_EQ: return JIT_CC_EQ;
244
   case MIR_CMP_NEQ: return JIT_CC_NE;
245
   case MIR_CMP_LT: return JIT_CC_LT;
246
   case MIR_CMP_GT: return JIT_CC_GT;
247
   case MIR_CMP_LEQ: return JIT_CC_LE;
248
   case MIR_CMP_GEQ: return JIT_CC_GE;
249
   default: return JIT_CC_NONE;
250
   }
251
}
252

253
static void irgen_emit_nullary(jit_irgen_t *g, jit_op_t op, jit_cc_t cc,
217,085✔
254
                               jit_reg_t result)
255
{
256
   jit_ir_t *ir = irgen_append(g);
217,085✔
257
   ir->op        = op;
217,085✔
258
   ir->size      = JIT_SZ_UNSPEC;
217,085✔
259
   ir->cc        = cc;
217,085✔
260
   ir->target    = 0;
217,085✔
261
   ir->result    = result;
217,085✔
262
   ir->arg1.kind = JIT_VALUE_INVALID;
217,085✔
263
   ir->arg2.kind = JIT_VALUE_INVALID;
217,085✔
264
}
217,085✔
265

266
static jit_ir_t *irgen_emit_unary(jit_irgen_t *g, jit_op_t op, jit_size_t sz,
1,580,641✔
267
                                  jit_cc_t cc, jit_reg_t result,
268
                                  jit_value_t arg)
269
{
270
   jit_ir_t *ir = irgen_append(g);
1,580,641✔
271
   ir->op        = op;
1,580,641✔
272
   ir->size      = sz;
1,580,641✔
273
   ir->cc        = cc;
1,580,641✔
274
   ir->target    = 0;
1,580,641✔
275
   ir->result    = result;
1,580,641✔
276
   ir->arg1      = arg;
1,580,641✔
277
   ir->arg2.kind = JIT_VALUE_INVALID;
1,580,641✔
278

279
   return ir;
1,580,641✔
280
}
281

282
static jit_ir_t *irgen_emit_binary(jit_irgen_t *g, jit_op_t op, jit_size_t sz,
3,745,493✔
283
                                   jit_cc_t cc, jit_reg_t result,
284
                                   jit_value_t arg1, jit_value_t arg2)
285
{
286
   jit_ir_t *ir = irgen_append(g);
3,745,493✔
287
   ir->op     = op;
3,745,493✔
288
   ir->size   = sz;
3,745,493✔
289
   ir->cc     = cc;
3,745,493✔
290
   ir->target = 0;
3,745,493✔
291
   ir->size   = sz;
3,745,493✔
292
   ir->result = result;
3,745,493✔
293
   ir->arg1   = arg1;
3,745,493✔
294
   ir->arg2   = arg2;
3,745,493✔
295

296
   return ir;
3,745,493✔
297
}
298

299
static void irgen_patch_label(jit_irgen_t *g, jit_ir_t *ir, irgen_label_t *l)
266,729✔
300
{
301
   if (l->label == JIT_LABEL_INVALID) {
266,729✔
302
      patch_list_t *p = &(l->patchlist);
230,363✔
303
      for (; p->count == PATCH_CHUNK_SZ; p = p->next) {
230,884✔
304
         if (p->next == NULL)
521✔
305
            p->next = xcalloc(sizeof(patch_list_t));
73✔
306
      }
307
      p->offsets[p->count++] = ir - g->func->irbuf;
230,363✔
308
   }
309

310
   l->uses++;
266,729✔
311
}
266,729✔
312

313
static jit_value_t j_recv(jit_irgen_t *g, int pos)
274,468✔
314
{
315
   assert(pos < JIT_MAX_ARGS);
274,468✔
316
   jit_reg_t r = irgen_alloc_reg(g);
274,468✔
317
   irgen_emit_unary(g, J_RECV, JIT_SZ_UNSPEC, JIT_CC_NONE, r,
274,468✔
318
                    jit_value_from_int64(pos));
319
   return jit_value_from_reg(r);
274,468✔
320
}
321

322
static void j_send(jit_irgen_t *g, int pos, jit_value_t value)
1,212,646✔
323
{
324
   assert(pos < JIT_MAX_ARGS);
1,212,646✔
325
   irgen_emit_binary(g, J_SEND, JIT_SZ_UNSPEC, JIT_CC_NONE, JIT_REG_INVALID,
1,212,646✔
326
                     jit_value_from_int64(pos), value);
327
}
1,212,646✔
328

329
static void j_ret(jit_irgen_t *g)
116,163✔
330
{
331
   irgen_emit_nullary(g, J_RET, JIT_CC_NONE, JIT_REG_INVALID);
116,163✔
332
   g->flags = MIR_NULL_VALUE;
116,163✔
333
}
116,163✔
334

335
__attribute__((unused))
336
static void j_trap(jit_irgen_t *g)
18,155✔
337
{
338
   irgen_emit_nullary(g, J_TRAP, JIT_CC_NONE, JIT_REG_INVALID);
18,155✔
339
}
18,155✔
340

341
static void j_jump(jit_irgen_t *g, jit_cc_t cc, irgen_label_t *l)
238,875✔
342
{
343
   jit_ir_t *ir = irgen_emit_unary(g, J_JUMP, JIT_SZ_UNSPEC, cc,
238,875✔
344
                                   JIT_REG_INVALID, jit_value_from_label(l));
345
   irgen_patch_label(g, ir, l);
238,875✔
346
}
238,875✔
347

348
static void j_call(jit_irgen_t *g, jit_handle_t handle)
82,427✔
349
{
350
   irgen_emit_unary(g, J_CALL, JIT_SZ_UNSPEC, JIT_CC_NONE,
82,427✔
351
                    JIT_REG_INVALID, jit_value_from_handle(handle));
352
   g->flags = MIR_NULL_VALUE;
82,427✔
353
}
82,427✔
354

355
static jit_value_t j_neg(jit_irgen_t *g, jit_value_t arg)
46,088✔
356
{
357
   jit_reg_t r = irgen_alloc_reg(g);
46,088✔
358
   irgen_emit_unary(g, J_NEG, JIT_SZ_UNSPEC, JIT_CC_NONE, r, arg);
46,088✔
359
   return jit_value_from_reg(r);
46,088✔
360
}
361

362
static jit_value_t j_fneg(jit_irgen_t *g, jit_value_t arg)
7,877✔
363
{
364
   jit_reg_t r = irgen_alloc_reg(g);
7,877✔
365
   irgen_emit_unary(g, J_FNEG, JIT_SZ_UNSPEC, JIT_CC_NONE, r, arg);
7,877✔
366
   return jit_value_from_reg(r);
7,877✔
367
}
368

369
static jit_value_t j_rem(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
1,069✔
370
{
371
   jit_reg_t r = irgen_alloc_reg(g);
1,069✔
372
   irgen_emit_binary(g, J_REM, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
1,069✔
373
   return jit_value_from_reg(r);
1,069✔
374
}
375

376
static jit_value_t j_not(jit_irgen_t *g, jit_value_t arg)
3,745✔
377
{
378
   jit_reg_t r = irgen_alloc_reg(g);
3,745✔
379
   irgen_emit_unary(g, J_NOT, JIT_SZ_UNSPEC, JIT_CC_NONE, r, arg);
3,745✔
380
   return jit_value_from_reg(r);
3,745✔
381
}
382

383
static jit_value_t j_and(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
8,479✔
384
{
385
   jit_reg_t r = irgen_alloc_reg(g);
8,479✔
386
   irgen_emit_binary(g, J_AND, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
8,479✔
387
   return jit_value_from_reg(r);
8,479✔
388
}
389

390
static jit_value_t j_or(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
3,666✔
391
{
392
   jit_reg_t r = irgen_alloc_reg(g);
3,666✔
393
   irgen_emit_binary(g, J_OR, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
3,666✔
394
   return jit_value_from_reg(r);
3,666✔
395
}
396

397
static jit_value_t j_xor(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
72,230✔
398
{
399
   jit_reg_t r = irgen_alloc_reg(g);
72,230✔
400
   irgen_emit_binary(g, J_XOR, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
72,230✔
401
   return jit_value_from_reg(r);
72,230✔
402
}
403

404
static jit_value_t j_asr(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
29,813✔
405
{
406
   jit_reg_t r = irgen_alloc_reg(g);
29,813✔
407
   irgen_emit_binary(g, J_ASR, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
29,813✔
408
   return jit_value_from_reg(r);
29,813✔
409
}
410

411
static jit_value_t j_shl(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
456✔
412
{
413
   jit_reg_t r = irgen_alloc_reg(g);
456✔
414
   irgen_emit_binary(g, J_SHL, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
456✔
415
   return jit_value_from_reg(r);
456✔
416
}
417

418
static jit_value_t j_add(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
166,422✔
419
{
420
   jit_reg_t r = irgen_alloc_reg(g);
166,422✔
421
   irgen_emit_binary(g, J_ADD, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
166,422✔
422
   return jit_value_from_reg(r);
166,422✔
423
}
424

425
static jit_value_t j_adds(jit_irgen_t *g, jit_size_t sz, jit_cc_t cc,
5,294✔
426
                          jit_value_t lhs, jit_value_t rhs)
427
{
428
   jit_reg_t r = irgen_alloc_reg(g);
5,294✔
429
   irgen_emit_binary(g, J_ADD, sz, cc, r, lhs, rhs);
5,294✔
430
   g->flags = MIR_NULL_VALUE;
5,294✔
431
   return jit_value_from_reg(r);
5,294✔
432
}
433

434
static jit_value_t j_fadd(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
499✔
435
{
436
   jit_reg_t r = irgen_alloc_reg(g);
499✔
437
   irgen_emit_binary(g, J_FADD, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
499✔
438
   return jit_value_from_reg(r);
499✔
439
}
440

441
static jit_value_t j_mul(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
99,181✔
442
{
443
   jit_reg_t r = irgen_alloc_reg(g);
99,181✔
444
   irgen_emit_binary(g, J_MUL, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
99,181✔
445
   return jit_value_from_reg(r);
99,181✔
446
}
447

448
static jit_value_t j_muls(jit_irgen_t *g, jit_size_t sz, jit_cc_t cc,
488✔
449
                          jit_value_t lhs, jit_value_t rhs)
450
{
451
   jit_reg_t r = irgen_alloc_reg(g);
488✔
452
   irgen_emit_binary(g, J_MUL, sz, cc, r, lhs, rhs);
488✔
453
   g->flags = MIR_NULL_VALUE;
488✔
454
   return jit_value_from_reg(r);
488✔
455
}
456

457
static jit_value_t j_fmul(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
753✔
458
{
459
   jit_reg_t r = irgen_alloc_reg(g);
753✔
460
   irgen_emit_binary(g, J_FMUL, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
753✔
461
   return jit_value_from_reg(r);
753✔
462
}
463

464
static jit_value_t j_div(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
1,569✔
465
{
466
   jit_reg_t r = irgen_alloc_reg(g);
1,569✔
467
   irgen_emit_binary(g, J_DIV, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
1,569✔
468
   return jit_value_from_reg(r);
1,569✔
469
}
470

471
static jit_value_t j_fdiv(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
453✔
472
{
473
   jit_reg_t r = irgen_alloc_reg(g);
453✔
474
   irgen_emit_binary(g, J_FDIV, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
453✔
475
   return jit_value_from_reg(r);
453✔
476
}
477

478
static jit_value_t j_sub(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
133,711✔
479
{
480
   jit_reg_t r = irgen_alloc_reg(g);
133,711✔
481
   irgen_emit_binary(g, J_SUB, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
133,711✔
482
   return jit_value_from_reg(r);
133,711✔
483
}
484

485
static jit_value_t j_subs(jit_irgen_t *g, jit_size_t sz, jit_cc_t cc,
1,717✔
486
                          jit_value_t lhs, jit_value_t rhs)
487
{
488
   jit_reg_t r = irgen_alloc_reg(g);
1,717✔
489
   irgen_emit_binary(g, J_SUB, sz, cc, r, lhs, rhs);
1,717✔
490
   g->flags = MIR_NULL_VALUE;
1,717✔
491
   return jit_value_from_reg(r);
1,717✔
492
}
493

494
static jit_value_t j_fsub(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
498✔
495
{
496
   jit_reg_t r = irgen_alloc_reg(g);
498✔
497
   irgen_emit_binary(g, J_FSUB, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
498✔
498
   return jit_value_from_reg(r);
498✔
499
}
500

501
static void j_cmp(jit_irgen_t *g, jit_cc_t cc, jit_value_t lhs, jit_value_t rhs)
279,419✔
502
{
503
   irgen_emit_binary(g, J_CMP, JIT_SZ_UNSPEC, cc, JIT_REG_INVALID, lhs, rhs);
279,419✔
504
   g->flags = MIR_NULL_VALUE;
279,419✔
505
}
279,419✔
506

507
static void j_ccmp(jit_irgen_t *g, jit_cc_t cc, jit_value_t lhs, jit_value_t rhs)
26,094✔
508
{
509
   irgen_emit_binary(g, J_CCMP, JIT_SZ_UNSPEC, cc, JIT_REG_INVALID, lhs, rhs);
26,094✔
510
   g->flags = MIR_NULL_VALUE;
26,094✔
511
}
26,094✔
512

513
static void j_fcmp(jit_irgen_t *g, jit_cc_t cc, jit_value_t lhs,
3,666✔
514
                   jit_value_t rhs)
515
{
516
   irgen_emit_binary(g, J_FCMP, JIT_SZ_UNSPEC, cc, JIT_REG_INVALID, lhs, rhs);
3,666✔
517
   g->flags = MIR_NULL_VALUE;
3,666✔
518
}
3,666✔
519

520
static void j_fccmp(jit_irgen_t *g, jit_cc_t cc, jit_value_t lhs,
1,187✔
521
                    jit_value_t rhs)
522
{
523
   irgen_emit_binary(g, J_FCCMP, JIT_SZ_UNSPEC, cc, JIT_REG_INVALID, lhs, rhs);
1,187✔
524
   g->flags = MIR_NULL_VALUE;
1,187✔
525
}
1,187✔
526

527
static jit_value_t j_cset(jit_irgen_t *g)
77,621✔
528
{
529
   jit_reg_t r = irgen_alloc_reg(g);
77,621✔
530
   irgen_emit_nullary(g, J_CSET, JIT_CC_NONE, r);
77,621✔
531
   return jit_value_from_reg(r);
77,621✔
532
}
533

534
static jit_value_t j_uload(jit_irgen_t *g, jit_size_t sz, jit_value_t addr)
31,772✔
535
{
536
   assert(jit_value_is_addr(addr));
31,772✔
537
   jit_reg_t r = irgen_alloc_reg(g);
31,772✔
538
   irgen_emit_unary(g, J_ULOAD, sz, JIT_CC_NONE, r, addr);
31,772✔
539
   return jit_value_from_reg(r);
31,772✔
540
}
541

542
static jit_value_t j_load(jit_irgen_t *g, jit_size_t sz, jit_value_t addr)
323,718✔
543
{
544
   jit_reg_t r = irgen_alloc_reg(g);
323,718✔
545
   irgen_emit_unary(g, J_LOAD, sz, JIT_CC_NONE, r, addr);
323,718✔
546
   return jit_value_from_reg(r);
323,718✔
547
}
548

549
static void j_store(jit_irgen_t *g, jit_size_t sz, jit_value_t value,
244,924✔
550
                    jit_value_t addr)
551
{
552
   assert(!jit_value_is_addr(value));
244,924✔
553
   irgen_emit_binary(g, J_STORE, sz, JIT_CC_NONE, JIT_REG_INVALID, value, addr);
244,924✔
554
}
244,924✔
555

556
static void j_mov(jit_irgen_t *g, jit_reg_t dest, jit_value_t value)
208,858✔
557
{
558
   assert(!jit_value_is_addr(value));
208,858✔
559
   irgen_emit_unary(g, J_MOV, JIT_SZ_UNSPEC, JIT_CC_NONE, dest, value);
208,858✔
560
}
208,858✔
561

562
static jit_value_t j_lea(jit_irgen_t *g, jit_value_t addr)
45,565✔
563
{
564
   assert(jit_value_is_addr(addr));
45,565✔
565
   jit_reg_t r = irgen_alloc_reg(g);
45,565✔
566
   irgen_emit_unary(g, J_LEA, JIT_SZ_UNSPEC, JIT_CC_NONE, r, addr);
45,565✔
567
   return jit_value_from_reg(r);
45,565✔
568
}
569

570
static jit_value_t j_scvtf(jit_irgen_t *g, jit_value_t value)
477✔
571
{
572
   jit_reg_t r = irgen_alloc_reg(g);
477✔
573
   irgen_emit_unary(g, J_SCVTF, JIT_SZ_UNSPEC, JIT_CC_NONE, r, value);
477✔
574
   return jit_value_from_reg(r);
477✔
575
}
576

577
static jit_value_t j_fcvtns(jit_irgen_t *g, jit_value_t value)
170✔
578
{
579
   jit_reg_t r = irgen_alloc_reg(g);
170✔
580
   irgen_emit_unary(g, J_FCVTNS, JIT_SZ_UNSPEC, JIT_CC_NONE, r, value);
170✔
581
   return jit_value_from_reg(r);
170✔
582
}
583

584
static jit_value_t j_csel(jit_irgen_t *g, jit_value_t iftrue,
134,568✔
585
                          jit_value_t iffalse)
586
{
587
   jit_reg_t r = irgen_alloc_reg(g);
134,568✔
588
   irgen_emit_binary(g, J_CSEL, JIT_SZ_UNSPEC, JIT_CC_NONE, r, iftrue, iffalse);
134,568✔
589
   return jit_value_from_reg(r);
134,568✔
590
}
591

592
static jit_value_t j_clamp(jit_irgen_t *g, jit_value_t value)
52,446✔
593
{
594
   jit_reg_t r = irgen_alloc_reg(g);
52,446✔
595
   irgen_emit_unary(g, J_CLAMP, JIT_SZ_UNSPEC, JIT_CC_NONE, r, value);
52,446✔
596
   return jit_value_from_reg(r);
52,446✔
597
}
598

599
#if 0
600
static void macro_copy(jit_irgen_t *g, jit_value_t dest, jit_value_t src,
601
                       jit_reg_t count)
602
{
603
   irgen_emit_binary(g, MACRO_COPY, JIT_SZ_UNSPEC, JIT_CC_NONE,
604
                     count, dest, src);
605
}
606
#endif
607

608
static void macro_move(jit_irgen_t *g, jit_value_t dest, jit_value_t src,
30,603✔
609
                       jit_reg_t count)
610
{
611
   irgen_emit_binary(g, MACRO_MOVE, JIT_SZ_UNSPEC, JIT_CC_NONE,
30,603✔
612
                     count, dest, src);
613
}
30,603✔
614

615
static void macro_bzero(jit_irgen_t *g, jit_value_t dest, jit_reg_t count)
5,236✔
616
{
617
   assert(jit_value_is_addr(dest));
5,236✔
618
   irgen_emit_unary(g, MACRO_BZERO, JIT_SZ_UNSPEC, JIT_CC_NONE,
5,236✔
619
                    count, dest);
620
}
5,236✔
621

622
static void macro_memset(jit_irgen_t *g, jit_size_t sz, jit_value_t dest,
2,305✔
623
                         jit_value_t value, jit_reg_t count)
624
{
625
   assert(jit_value_is_addr(dest));
2,305✔
626
   irgen_emit_binary(g, MACRO_MEMSET, sz, JIT_CC_NONE, count, dest, value);
2,305✔
627
}
2,305✔
628

629
static jit_value_t macro_galloc(jit_irgen_t *g, jit_value_t bytes)
1,546✔
630
{
631
   jit_reg_t r = irgen_alloc_reg(g);
1,546✔
632
   irgen_emit_unary(g, MACRO_GALLOC, JIT_SZ_UNSPEC, JIT_CC_NONE, r, bytes);
1,546✔
633
   return jit_value_from_reg(r);
1,546✔
634
}
635

636
static jit_value_t macro_lalloc(jit_irgen_t *g, jit_value_t bytes)
39,616✔
637
{
638
   jit_reg_t r = irgen_alloc_reg(g);
39,616✔
639
   irgen_emit_unary(g, MACRO_LALLOC, JIT_SZ_UNSPEC, JIT_CC_NONE, r, bytes);
39,616✔
640
   return jit_value_from_reg(r);
39,616✔
641
}
642

643
static jit_value_t macro_salloc(jit_irgen_t *g, size_t size)
22,761✔
644
{
645
   jit_reg_t r = irgen_alloc_reg(g);
22,761✔
646
   jit_value_t arg1 = jit_value_from_int64(g->func->framesz);
22,761✔
647
   jit_value_t arg2 = jit_value_from_int64(size);
22,761✔
648
   irgen_emit_binary(g, MACRO_SALLOC, JIT_SZ_UNSPEC, JIT_CC_NONE,
22,761✔
649
                     r, arg1, arg2);
650
   g->func->framesz += ALIGN_UP(size, 8);
22,761✔
651
   return jit_value_from_reg(r);
22,761✔
652
}
653

654
static void macro_exit(jit_irgen_t *g, jit_exit_t exit)
180,130✔
655
{
656
   irgen_emit_unary(g, MACRO_EXIT, JIT_SZ_UNSPEC, JIT_CC_NONE, JIT_REG_INVALID,
180,130✔
657
                    jit_value_from_exit(exit));
658
   g->flags = MIR_NULL_VALUE;
180,130✔
659
}
180,130✔
660

661
static jit_value_t macro_fexp(jit_irgen_t *g, jit_value_t lhs, jit_value_t rhs)
175✔
662
{
663
   jit_reg_t r = irgen_alloc_reg(g);
175✔
664
   irgen_emit_binary(g, MACRO_FEXP, JIT_SZ_UNSPEC, JIT_CC_NONE, r, lhs, rhs);
175✔
665
   return jit_value_from_reg(r);
175✔
666
}
667

668
static jit_value_t macro_exp(jit_irgen_t *g, jit_size_t sz, jit_cc_t cc,
683✔
669
                             jit_value_t lhs, jit_value_t rhs)
670
{
671
   jit_reg_t r = irgen_alloc_reg(g);
683✔
672
   irgen_emit_binary(g, MACRO_EXP, sz, cc, r, lhs, rhs);
683✔
673
   return jit_value_from_reg(r);
683✔
674
}
675

676
static jit_value_t macro_getpriv(jit_irgen_t *g, jit_handle_t handle)
37,627✔
677
{
678
   jit_reg_t r = irgen_alloc_reg(g);
37,627✔
679
   irgen_emit_unary(g, MACRO_GETPRIV, JIT_SZ_UNSPEC, JIT_CC_NONE, r,
37,627✔
680
                    jit_value_from_handle(handle));
681
   return jit_value_from_reg(r);
37,627✔
682
}
683

684
static void macro_putpriv(jit_irgen_t *g, jit_handle_t handle, jit_value_t ptr)
23,354✔
685
{
686
   irgen_emit_binary(g, MACRO_PUTPRIV, JIT_SZ_UNSPEC, JIT_CC_NONE,
23,354✔
687
                     JIT_REG_INVALID, jit_value_from_handle(handle), ptr);
688
}
23,354✔
689

690
static void macro_case(jit_irgen_t *g, jit_reg_t test, jit_value_t cmp,
27,854✔
691
                       irgen_label_t *l)
692
{
693
   jit_ir_t *ir = irgen_emit_binary(g, MACRO_CASE, JIT_SZ_UNSPEC, JIT_CC_NONE,
27,854✔
694
                                    test, cmp, jit_value_from_label(l));
695
   irgen_patch_label(g, ir, l);
27,854✔
696
}
27,854✔
697

698
static void macro_trim(jit_irgen_t *g)
3,840✔
699
{
700
   irgen_emit_nullary(g, MACRO_TRIM, JIT_CC_NONE, JIT_REG_INVALID);
3,840✔
701
}
3,840✔
702

703
static void macro_reexec(jit_irgen_t *g)
1,306✔
704
{
705
   irgen_emit_nullary(g, MACRO_REEXEC, JIT_CC_NONE, JIT_REG_INVALID);
1,306✔
706
   g->flags = MIR_NULL_VALUE;
1,306✔
707
}
1,306✔
708

709
static void macro_sadd(jit_irgen_t *g, jit_size_t sz, jit_value_t addr,
3,109✔
710
                       jit_value_t addend)
711
{
712
   irgen_emit_binary(g, MACRO_SADD, sz, JIT_CC_NONE, JIT_REG_INVALID,
3,109✔
713
                     addr, addend);
714
}
3,109✔
715

716
static void macro_pack(jit_irgen_t *g, jit_value_t ptr, jit_value_t size)
244✔
717
{
718
   irgen_emit_binary(g, MACRO_PACK, JIT_SZ_UNSPEC, JIT_CC_NONE,
244✔
719
                     JIT_REG_INVALID, ptr, size);
720
}
244✔
721

722
static void macro_unpack(jit_irgen_t *g, jit_value_t abits, jit_value_t bbits)
224✔
723
{
724
   irgen_emit_binary(g, MACRO_UNPACK, JIT_SZ_UNSPEC, JIT_CC_NONE,
224✔
725
                     JIT_REG_INVALID, abits, bbits);
726
}
224✔
727

728
////////////////////////////////////////////////////////////////////////////////
729
// MIR to JIT IR lowering
730

731
static int irgen_slots_for_type(jit_irgen_t *g, mir_type_t type)
463,766✔
732
{
733
   if (mir_is_null(type))
463,766✔
734
      return 1;   // Untyped constants
735

736
   switch (mir_get_class(g->mu, type)) {
438,944✔
737
   case MIR_TYPE_UARRAY:
77,683✔
738
      // Always passed around scalarised
739
      if (mir_get_class(g->mu, mir_get_elem(g->mu, type)) == MIR_TYPE_SIGNAL)
77,683✔
740
         return 2 + mir_get_dims(g->mu, type) * 2;
160✔
741
      else
742
         return 1 + mir_get_dims(g->mu, type) * 2;
77,523✔
743
   case MIR_TYPE_SIGNAL:
744
      // Signal pointer plus offset
745
      return 2;
746
   case MIR_TYPE_CLOSURE:
747
      // Function pointer, context
748
      return 2;
749
   case MIR_TYPE_RESOLUTION:
×
750
      // Closure slots plus nlits, and flags (this is silly)
751
      return 4;
×
752
   case MIR_TYPE_VEC4:
753
      return 2;
754
   default:
345,329✔
755
      // Passed by pointer or fits in 64-bit register
756
      return 1;
345,329✔
757
   }
758
}
759

760
static int irgen_repr_bits(mir_repr_t repr)
592,641✔
761
{
762
   switch (repr) {
592,641✔
763
   case MIR_REPR_U1: return 1;
764
   case MIR_REPR_U8: case MIR_REPR_I8: return 8;
765
   case MIR_REPR_U16: case MIR_REPR_I16: return 16;
766
   case MIR_REPR_U32: case MIR_REPR_I32: return 32;
767
   case MIR_REPR_U64: case MIR_REPR_I64: return 64;
768
   default: return -1;
769
   }
770
}
771

772
static bool irgen_repr_signed(mir_repr_t repr)
77,403✔
773
{
774
   return repr == MIR_REPR_I8 || repr == MIR_REPR_I16
77,403✔
775
      || repr == MIR_REPR_I32 || repr == MIR_REPR_I64;
77,403✔
776
}
777

778
static int irgen_align_of(jit_irgen_t *g, mir_type_t type)
440,359✔
779
{
780
   switch (mir_get_class(g->mu, type)) {
440,359✔
781
   case MIR_TYPE_INT:
177,896✔
782
   case MIR_TYPE_OFFSET:
783
      {
784
         const int bits = irgen_repr_bits(mir_get_repr(g->mu, type));
177,896✔
785
         return ALIGN_UP(bits, 8) / 8;
177,896✔
786
      }
787
   case MIR_TYPE_REAL:
788
   case MIR_TYPE_RECORD:
789
      return sizeof(double);
790
   case MIR_TYPE_POINTER:
791
   case MIR_TYPE_ACCESS:
792
   case MIR_TYPE_UARRAY:
793
   case MIR_TYPE_SIGNAL:
794
   case MIR_TYPE_CONTEXT:
795
   case MIR_TYPE_TRIGGER:
796
   case MIR_TYPE_RESOLUTION:
797
      return sizeof(void *);
798
   case MIR_TYPE_VEC4:
799
   case MIR_TYPE_VEC2:
800
      return sizeof(uint64_t);
801
   case MIR_TYPE_FILE:
1,442✔
802
      return sizeof(uint32_t);
1,442✔
803
   case MIR_TYPE_CARRAY:
61,942✔
804
      return irgen_align_of(g, mir_get_elem(g->mu, type));
61,942✔
805
   default:
×
806
      fatal_trace("cannot handle type %d in irgen_align_of",
807
                  mir_get_class(g->mu, type));
×
808
   }
809
}
810

811
static int irgen_size_bits(jit_irgen_t *g, mir_type_t type)
425,436✔
812
{
813
   switch (mir_get_class(g->mu, type)) {
425,436✔
814
   case MIR_TYPE_INT:
414,745✔
815
   case MIR_TYPE_OFFSET:
816
      return irgen_repr_bits(mir_get_repr(g->mu, type));
414,745✔
817
   case MIR_TYPE_REAL:
818
      return sizeof(double) * 8;
819
   case MIR_TYPE_POINTER:
820
   case MIR_TYPE_ACCESS:
821
   case MIR_TYPE_CONTEXT:
822
   case MIR_TYPE_TRIGGER:
823
      return sizeof(void *) * 8;
824
   case MIR_TYPE_FILE:
×
825
      return sizeof(uint32_t) * 8;
×
826
   default:
×
827
      fatal_trace("cannot handle type %d in irgen_size_bits",
828
                  mir_get_class(g->mu, type));
×
829
   }
830
}
831

832
static int irgen_size_bytes(jit_irgen_t *g, mir_type_t type)
522,202✔
833
{
834
   switch (mir_get_class(g->mu, type)) {
522,202✔
835
   case MIR_TYPE_INT:
270,725✔
836
   case MIR_TYPE_OFFSET:
837
      {
838
         const int bits = irgen_size_bits(g, type);
270,725✔
839
         return ALIGN_UP(bits, 8) / 8;
270,725✔
840
      }
841

842
   case MIR_TYPE_REAL:
843
      return sizeof(double);
844

845
   case MIR_TYPE_CARRAY:
56,461✔
846
      {
847
         mir_type_t elem = mir_get_elem(g->mu, type);
56,461✔
848
         return mir_get_size(g->mu, type) * irgen_size_bytes(g, elem);
56,461✔
849
      }
850

851
   case MIR_TYPE_RECORD:
27,716✔
852
      {
853
         // TODO: cache this
854
         size_t nfields, bytes = 0;
27,716✔
855
         const mir_type_t *fields = mir_get_fields(g->mu, type, &nfields);
27,716✔
856
         for (int i = 0; i < nfields; i++) {
126,333✔
857
            const int fb = irgen_size_bytes(g, fields[i]);
98,617✔
858
            const int align = irgen_align_of(g, fields[i]);
98,617✔
859

860
            bytes = ALIGN_UP(bytes, align);
98,617✔
861
            bytes += fb;
98,617✔
862
         }
863

864
         return ALIGN_UP(bytes, sizeof(double));
27,716✔
865
      }
866

867
   case MIR_TYPE_UARRAY:
23,496✔
868
      {
869
         const int ndims = mir_get_dims(g->mu, type);
23,496✔
870
         if (mir_get_class(g->mu, mir_get_elem(g->mu, type)) == MIR_TYPE_SIGNAL)
23,496✔
871
            return 2*sizeof(void *) + 2 * sizeof(int64_t) * ndims;
7,113✔
872
         else
873
            return sizeof(void *) + 2 * sizeof(int64_t) * ndims;
16,383✔
874
      }
875

876
   case MIR_TYPE_ACCESS:
877
   case MIR_TYPE_POINTER:
878
   case MIR_TYPE_CONTEXT:
879
   case MIR_TYPE_TRIGGER:
880
      return sizeof(void *);
881

882
   case MIR_TYPE_FILE:
1,471✔
883
      return sizeof(uint32_t);
1,471✔
884

885
   case MIR_TYPE_SIGNAL:
108,395✔
886
      return sizeof(void *) + sizeof(int32_t);
108,395✔
887

888
   case MIR_TYPE_RESOLUTION:
6,010✔
889
      return 2*sizeof(void *) + sizeof(int64_t) + sizeof(int32_t);
6,010✔
890

891
   case MIR_TYPE_VEC2:
892
      return sizeof(uint64_t);
893

894
   case MIR_TYPE_VEC4:
20✔
895
      return 2*sizeof(uint64_t);
20✔
896

897
   default:
×
898
      fatal_trace("cannot handle type %d in irgen_size_bytes",
899
                  mir_get_class(g->mu, type));
×
900
   }
901
}
902

903
static jit_size_t irgen_jit_size(jit_irgen_t *g, mir_type_t type)
154,711✔
904
{
905
   const int bits = irgen_size_bits(g, type);
154,711✔
906
   switch (bits) {
154,711✔
907
   case 1:
908
   case 8: return JIT_SZ_8;
909
   case 16: return JIT_SZ_16;
64✔
910
   case 32: return JIT_SZ_32;
63,401✔
911
   case 64: return JIT_SZ_64;
36,143✔
912
   default:
×
913
      fatal_trace("illegal operand size %d", bits);
914
   }
915
}
916

917
static jit_value_t irgen_get_value(jit_irgen_t *g, mir_value_t value)
4,449,362✔
918
{
919
   assert(!mir_is_null(value));
4,449,362✔
920

921
   switch (value.tag) {
4,449,362✔
922
   case MIR_TAG_NODE:
1,502,556✔
923
      assert(g->map[value.id].kind != JIT_VALUE_INVALID);
1,502,556✔
924
      return g->map[value.id];
1,502,556✔
925
   case MIR_TAG_CONST:
2,667,114✔
926
      {
927
         int64_t cval;
2,667,114✔
928
         if (mir_get_const(g->mu, value, &cval))
2,667,114✔
929
            return jit_value_from_int64(cval);
2,667,114✔
930

931
         should_not_reach_here();
932
      }
933
   case MIR_TAG_VAR:
199,389✔
934
      return g->vars[value.id];
199,389✔
935
   case MIR_TAG_PARAM:
80,303✔
936
      return g->params[value.id];
80,303✔
937
   default:
×
938
      DEBUG_ONLY(mir_dump(g->mu));
×
939
      should_not_reach_here();
940
   }
941
}
942

943
static jit_value_t irgen_get_arg(jit_irgen_t *g, mir_value_t n, int arg)
3,902,930✔
944
{
945
   return irgen_get_value(g, mir_get_arg(g->mu, n, arg));
3,902,930✔
946
}
947

948
static unsigned irgen_get_enum(jit_irgen_t *g, mir_value_t n, int arg)
52,104✔
949
{
950
   mir_value_t value = mir_get_arg(g->mu, n, arg);
52,104✔
951
   assert(value.tag == MIR_TAG_ENUM);
52,104✔
952
   return value.id;
52,104✔
953
}
954

955
static int64_t irgen_get_const(jit_irgen_t *g, mir_value_t n, int arg)
301,237✔
956
{
957
   mir_value_t value = mir_get_arg(g->mu, n, arg);
301,237✔
958

959
   int64_t result;
301,237✔
960
   if (mir_get_const(g->mu, value, &result))
301,237✔
961
      return result;
301,237✔
962

963
#ifdef DEBUG
964
   mir_dump(g->mu);
×
965
   fatal_trace("argument %d is not constant", arg);
966
#else
967
   should_not_reach_here();
968
#endif
969
}
970

971
static jit_value_t irgen_lea(jit_irgen_t *g, jit_value_t addr)
95,568✔
972
{
973
   switch (addr.kind) {
95,568✔
974
   case JIT_ADDR_REG:
30,626✔
975
      if (addr.disp == 0)
30,626✔
976
         return jit_value_from_reg(addr.reg);
550✔
977
      else
978
         return j_lea(g, addr);
30,076✔
979
   case JIT_ADDR_CPOOL:
15,489✔
980
      return j_lea(g, addr);
15,489✔
981
   case JIT_ADDR_ABS:
4,161✔
982
      return jit_value_from_int64(addr.int64);
4,161✔
983
   case JIT_VALUE_REG:
45,292✔
984
   case JIT_VALUE_INT64:
985
      return addr;
45,292✔
986
   default:
×
987
      fatal_trace("cannot load address of value kind %d", addr.kind);
988
   }
989
}
990

991
static jit_reg_t irgen_as_reg(jit_irgen_t *g, jit_value_t value)
30,627✔
992
{
993
   switch (value.kind) {
30,627✔
994
   case JIT_VALUE_REG:
28,616✔
995
      return value.reg;
28,616✔
996
   case JIT_ADDR_REG:
4✔
997
   case JIT_ADDR_CPOOL:
998
   case JIT_ADDR_ABS:
999
      return jit_value_as_reg(irgen_lea(g, value));
4✔
1000
   default:
2,007✔
1001
      {
1002
         jit_reg_t r = irgen_alloc_reg(g);
2,007✔
1003
         j_mov(g, r, value);
2,007✔
1004
         return r;
2,007✔
1005
      }
1006
   }
1007
}
1008

1009
static jit_value_t irgen_is_scalar(jit_irgen_t *g, mir_value_t n, int arg)
37,356✔
1010
{
1011
   mir_value_t value = mir_get_arg(g->mu, n, arg);
37,356✔
1012
   return jit_value_from_int64(!mir_is(g->mu, value, MIR_TYPE_POINTER));
37,356✔
1013
}
1014

1015
static jit_value_t irgen_get_context(jit_irgen_t *g)
75,357✔
1016
{
1017
   if (g->statereg.kind != JIT_VALUE_INVALID)
75,357✔
1018
      return j_load(g, JIT_SZ_PTR, jit_addr_from_value(g->statereg, 0));
32,546✔
1019
   else if (g->contextarg.kind != JIT_VALUE_INVALID)
42,811✔
1020
      return g->contextarg;
28,584✔
1021
   else
1022
      return g->params[mir_get_param(g->mu, 0).id];
14,227✔
1023
}
1024

1025
static size_t irgen_append_cpool(jit_irgen_t *g, size_t sz, int align)
44,457✔
1026
{
1027
   if (g->cpoolptr + sz + align - 1 > g->func->cpoolsz) {
44,457✔
1028
      g->func->cpoolsz = MAX(128, MAX((g->func->cpoolsz * 3) / 2,
19,600✔
1029
                                      g->cpoolptr + sz + align - 1));
1030
      g->func->cpool = xrealloc(g->func->cpool, g->func->cpoolsz);
19,600✔
1031
      g->func->owns_cpool = true;
19,600✔
1032
   }
1033

1034
   const size_t result = ALIGN_UP(g->cpoolptr, align);
44,457✔
1035
   g->oldptr = result;
44,457✔
1036
   g->cpoolptr = result + sz;
44,457✔
1037
   return result;
44,457✔
1038
}
1039

1040
static jit_value_t irgen_dedup_cpool(jit_irgen_t *g)
41,865✔
1041
{
1042
   unsigned char *dup = memmem(g->func->cpool, MIN(g->oldptr, DEDUP_PREFIX),
41,865✔
1043
                               g->func->cpool + g->oldptr,
41,865✔
1044
                               g->cpoolptr - g->oldptr);
41,865✔
1045
   if (dup != NULL) {
41,865✔
1046
      g->cpoolptr = g->oldptr;
4,793✔
1047
      return jit_value_from_cpool_addr(dup - g->func->cpool);
4,793✔
1048
   }
1049
   else
1050
      return jit_value_from_cpool_addr(g->oldptr);
37,072✔
1051
}
1052

1053
static void irgen_emit_debuginfo(jit_irgen_t *g, mir_value_t n)
1,731,474✔
1054
{
1055
   jit_value_t arg1 = jit_value_from_loc(mir_get_loc(g->mu, n));
1,731,474✔
1056

1057
   jit_value_t arg2 = {
1,731,474✔
1058
      .kind = JIT_VALUE_VPOS,
1059
      .vpos = { .block = g->curblock.id, .op = n.id }
1,731,474✔
1060
   };
1061

1062
   if (g->func->nirs > 0 && g->func->irbuf[g->func->nirs - 1].op == J_DEBUG) {
1,731,474✔
1063
      jit_ir_t *prev = &(g->func->irbuf[g->func->nirs - 1]);
526,095✔
1064
      prev->arg1 = arg1;
526,095✔
1065
      prev->arg2 = arg2;
526,095✔
1066
   }
1067
   else
1068
      irgen_emit_binary(g, J_DEBUG, JIT_SZ_UNSPEC, JIT_CC_NONE,
1,205,379✔
1069
                        JIT_REG_INVALID, arg1, arg2);
1070
}
1,731,474✔
1071

1072
static ffi_type_t irgen_ffi_type(jit_irgen_t *g, mir_type_t type)
68,228✔
1073
{
1074
   if (mir_is_null(type))
68,228✔
1075
      return FFI_VOID;
1076

1077
   switch (mir_get_class(g->mu, type)) {
68,228✔
1078
   case MIR_TYPE_INT:
22,881✔
1079
   case MIR_TYPE_OFFSET:
1080
      switch (mir_get_repr(g->mu, type)) {
22,881✔
1081
      case MIR_REPR_U1:
1082
      case MIR_REPR_U8:
1083
         return FFI_UINT8;
1084
      case MIR_REPR_I8:
1085
         return FFI_INT8;
1086
      case MIR_REPR_I16:
1087
         return FFI_INT16;
1088
      case MIR_REPR_U16:
1089
         return FFI_UINT16;
1090
      case MIR_REPR_I32:
1091
         return FFI_INT32;
1092
      case MIR_REPR_U32:
1093
         return FFI_UINT32;
1094
      default:
1095
         return FFI_INT64;
1096
      }
1097
   case MIR_TYPE_REAL:
1098
      return FFI_FLOAT;
1099
   case MIR_TYPE_CARRAY:
28,411✔
1100
   case MIR_TYPE_RECORD:
1101
   case MIR_TYPE_POINTER:
1102
   case MIR_TYPE_CONTEXT:
1103
   case MIR_TYPE_ACCESS:
1104
   case MIR_TYPE_LOCUS:
1105
   case MIR_TYPE_CONVERSION:
1106
      return FFI_POINTER;
28,411✔
1107
   case MIR_TYPE_FILE:
×
1108
      return FFI_UINT32;
×
1109
   case MIR_TYPE_UARRAY:
15,364✔
1110
      return FFI_UARRAY;
15,364✔
1111
   case MIR_TYPE_SIGNAL:
375✔
1112
      return FFI_SIGNAL;
375✔
1113
   default:
×
1114
      fatal_trace("cannot handle type %d in irgen_ffi_type",
1115
                  mir_get_class(g->mu, type));
×
1116
   }
1117
}
1118

1119
static jit_handle_t irgen_get_handle(jit_irgen_t *g, mir_value_t n, int arg)
109,679✔
1120
{
1121
   ident_t func = mir_get_name(g->mu, mir_get_arg(g->mu, n, arg));
109,679✔
1122
   jit_handle_t handle = jit_lazy_compile(g->func->jit, func);
109,679✔
1123
   if (handle == JIT_HANDLE_INVALID)
109,679✔
1124
      fatal_at(mir_get_loc(g->mu, n), "missing definition for %s", istr(func));
×
1125

1126
   return handle;
109,679✔
1127
}
1128

1129
static jit_value_t irgen_state_ptr(jit_irgen_t *g)
24,097✔
1130
{
1131
   assert(g->statereg.kind != JIT_VALUE_INVALID);
24,097✔
1132
   return jit_addr_from_value(g->statereg, 2 * sizeof(void *));
24,097✔
1133
}
1134

1135
static jit_value_t irgen_pcall_ptr(jit_irgen_t *g)
3,252✔
1136
{
1137
   assert(g->statereg.kind != JIT_VALUE_INVALID);
3,252✔
1138
   return jit_addr_from_value(g->statereg, 1 * sizeof(void *));
3,252✔
1139
}
1140

1141
static void irgen_op_null(jit_irgen_t *g, mir_value_t n)
5,700✔
1142
{
1143
   switch (mir_get_class(g->mu, mir_get_type(g->mu, n))) {
5,700✔
1144
   case MIR_TYPE_POINTER:
4,892✔
1145
   case MIR_TYPE_ACCESS:
1146
   case MIR_TYPE_CONTEXT:
1147
      g->map[n.id] = jit_null_ptr();
4,892✔
1148
      break;
4,892✔
1149
   case MIR_TYPE_FILE:
808✔
1150
      g->map[n.id] = jit_value_from_int64(0);
808✔
1151
      break;
808✔
1152
   default:
×
1153
      should_not_reach_here();
1154
   }
1155
}
5,700✔
1156

1157
static void irgen_op_const(jit_irgen_t *g, mir_value_t n)
10,051✔
1158
{
1159
   int64_t cval;
10,051✔
1160
   if (mir_get_const(g->mu, n, &cval))
10,051✔
1161
      g->map[n.id] = jit_value_from_int64(cval);
10,051✔
1162
   else
1163
      should_not_reach_here();
1164
}
10,051✔
1165

1166
static void irgen_op_const_real(jit_irgen_t *g, mir_value_t n)
29,794✔
1167
{
1168
   double val;
29,794✔
1169
   if (mir_get_const_real(g->mu, n, &val))
29,794✔
1170
      g->map[n.id] = jit_value_from_double(val);
29,794✔
1171
   else
1172
      should_not_reach_here();
1173
}
29,794✔
1174

1175
static void irgen_op_const_vec(jit_irgen_t *g, mir_value_t n)
2,240✔
1176
{
1177
   uint64_t abits, bbits;
2,240✔
1178
   mir_get_bits(g->mu, n, &abits, &bbits);
2,240✔
1179

1180
   if (mir_is(g->mu, n, MIR_TYPE_VEC2)) {
2,240✔
1181
      assert(bbits == 0);
1,060✔
1182
      g->map[n.id] = jit_value_from_int64(abits);
1,060✔
1183
   }
1184
   else {
1185
      // Registers must be contiguous
1186
      jit_reg_t areg = irgen_alloc_reg(g);
1,180✔
1187
      j_mov(g, areg, jit_value_from_int64(abits));
1,180✔
1188
      jit_reg_t breg = irgen_alloc_reg(g);
1,180✔
1189
      j_mov(g, breg, jit_value_from_int64(bbits));
1,180✔
1190

1191
      g->map[n.id] = jit_value_from_reg(areg);
1,180✔
1192
   }
1193
}
2,240✔
1194

1195
static void irgen_copy_const(jit_irgen_t *g, unsigned char *p,
2,161,779✔
1196
                             jit_value_t value, int bytes)
1197
{
1198
   switch (value.kind) {
2,161,779✔
1199
   case JIT_VALUE_INT64:
2,139,652✔
1200
      switch (bytes) {
2,139,652✔
1201
      case 1: *(uint8_t *)p = (uint8_t)value.int64; break;
2,122,605✔
1202
      case 2: *(uint16_t *)p = (uint16_t)value.int64; break;
16✔
1203
      case 4: *(uint32_t *)p = (uint32_t)value.int64; break;
13,228✔
1204
      case 8: *(uint64_t *)p = (uint64_t)value.int64; break;
3,803✔
1205
      default:
×
1206
         fatal_trace("cannot handle value size %d", bytes);
1207
      }
1208
      break;
1209

1210
   case JIT_VALUE_DOUBLE:
20,111✔
1211
      assert(bytes == sizeof(double));
20,111✔
1212
      *(double *)p = value.dval;
20,111✔
1213
      break;
20,111✔
1214

1215
   case JIT_ADDR_CPOOL:
1,876✔
1216
      assert(value.int64 >= 0 && value.int64 + bytes <= g->func->cpoolsz);
1,876✔
1217
      memcpy(p, g->func->cpool + value.int64, bytes);
1,876✔
1218
      break;
1219

1220
   case JIT_ADDR_ABS:
140✔
1221
      assert(value.int64 == 0);
140✔
1222
      switch (bytes) {
140✔
1223
      case sizeof(void *): *(uintptr_t *)p = (uintptr_t)value.int64; break;
132✔
1224
      case 0: break;
1225
      default: should_not_reach_here();
1226
      }
1227
      break;
1228

1229
   default:
×
1230
      fatal_trace("cannot handle value kind %d", value.kind);
1231
   }
1232
}
2,161,779✔
1233

1234
static void irgen_op_const_array(jit_irgen_t *g, mir_value_t n)
41,596✔
1235
{
1236
   mir_type_t type = mir_get_type(g->mu, n);
41,596✔
1237
   mir_type_t elem = mir_get_elem(g->mu, type);
41,596✔
1238

1239
   const int elemsz = irgen_size_bytes(g, elem);
41,596✔
1240
   const int align = irgen_align_of(g, elem);
41,596✔
1241
   const int count = mir_get_size(g->mu, type);
41,596✔
1242

1243
   if (count > 0) {
41,596✔
1244
      const size_t offset = irgen_append_cpool(g, elemsz * count, align);
41,518✔
1245

1246
      unsigned char *p = g->func->cpool + offset;
41,518✔
1247
      for (int i = 0; i < count; i++, p += elemsz) {
2,169,752✔
1248
         jit_value_t elem = irgen_get_arg(g, n, i);
2,128,234✔
1249
         irgen_copy_const(g, p, elem, elemsz);
2,128,234✔
1250
      }
1251

1252
      g->map[n.id] = irgen_dedup_cpool(g);
41,518✔
1253
   }
1254
   else
1255
      g->map[n.id] = jit_null_ptr();
78✔
1256
}
41,596✔
1257

1258
static void irgen_op_const_rep(jit_irgen_t *g, mir_value_t n)
347✔
1259
{
1260
   mir_type_t elem = mir_get_elem(g->mu, mir_get_type(g->mu, n));
347✔
1261

1262
   const int count = irgen_get_const(g, n, 1);
347✔
1263
   jit_value_t value = irgen_get_arg(g, n, 0);
347✔
1264

1265
   const int elemsz = irgen_size_bytes(g, elem);
347✔
1266
   const int align = irgen_align_of(g, elem);
347✔
1267

1268
   const size_t offset = irgen_append_cpool(g, elemsz * count, align);
347✔
1269

1270
   unsigned char *p = g->func->cpool + offset;
347✔
1271
   for (int i = 0; i < count; i++, p += elemsz)
27,037✔
1272
      irgen_copy_const(g, p, value, elemsz);
26,690✔
1273

1274
   g->map[n.id] = irgen_dedup_cpool(g);
347✔
1275
}
347✔
1276

1277
static void irgen_op_const_record(jit_irgen_t *g, mir_value_t n)
2,592✔
1278
{
1279
   mir_type_t type = mir_get_type(g->mu, n);
2,592✔
1280

1281
   size_t nfields;
2,592✔
1282
   const mir_type_t *fields = mir_get_fields(g->mu, type, &nfields);
2,592✔
1283

1284
   const int sz = irgen_size_bytes(g, type);
2,592✔
1285
   const int align = irgen_align_of(g, type);
2,592✔
1286
   const size_t offset = irgen_append_cpool(g, sz, align);
2,592✔
1287

1288
   unsigned char *p = g->func->cpool + offset;
2,592✔
1289
   for (int i = 0; i < nfields; i++) {
9,447✔
1290
      jit_value_t elem = irgen_get_arg(g, n, i);
6,855✔
1291

1292
      const int bytes = irgen_size_bytes(g, fields[i]);
6,855✔
1293
      const int align = irgen_align_of(g, fields[i]);
6,855✔
1294

1295
      while (p != ALIGN_UP(p, align))
9,061✔
1296
         *p++ = 0;   // Pad to field alignment
2,206✔
1297

1298
      irgen_copy_const(g, p, elem, bytes);
6,855✔
1299
      p += bytes;
6,855✔
1300
   }
1301
   assert(g->func->cpool + offset + sz - p < sizeof(double));
2,592✔
1302

1303
   g->map[n.id] = jit_value_from_cpool_addr(offset);
2,592✔
1304
}
2,592✔
1305

1306
static void irgen_op_address_of(jit_irgen_t *g, mir_value_t n)
43,197✔
1307
{
1308
   // No-op
1309
   g->map[n.id] = irgen_get_arg(g, n, 0);
43,197✔
1310
}
43,197✔
1311

1312
static void irgen_op_copy(jit_irgen_t *g, mir_value_t n)
30,603✔
1313
{
1314
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
30,603✔
1315
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
30,603✔
1316

1317
   mir_type_t elem = mir_get_type(g->mu, n);
30,603✔
1318

1319
   jit_value_t bytes;
30,603✔
1320
   if (mir_count_args(g->mu, n) > 2) {
30,603✔
1321
      jit_value_t arg2 = irgen_get_arg(g, n, 2);
28,596✔
1322

1323
      const int scale = irgen_size_bytes(g, elem);
28,596✔
1324
      bytes = j_mul(g, arg2, jit_value_from_int64(scale));
28,596✔
1325
   }
1326
   else
1327
      bytes = jit_value_from_int64(irgen_size_bytes(g, elem));
2,007✔
1328

1329
   jit_value_t dest = jit_addr_from_value(arg0, 0);
30,603✔
1330
   jit_value_t src = jit_addr_from_value(arg1, 0);
30,603✔
1331

1332
   macro_move(g, dest, src, irgen_as_reg(g, bytes));
30,603✔
1333
}
30,603✔
1334

1335
static void irgen_op_set(jit_irgen_t *g, mir_value_t n)
7,541✔
1336
{
1337
   jit_value_t base   = irgen_get_arg(g, n, 0);
7,541✔
1338
   jit_value_t value  = irgen_get_arg(g, n, 1);
7,541✔
1339
   jit_value_t length = irgen_get_arg(g, n, 2);
7,541✔
1340

1341
   mir_type_t type = mir_get_type(g->mu, n);
7,541✔
1342

1343
   jit_value_t addr = jit_addr_from_value(base, 0);
7,541✔
1344
   jit_value_t scale = jit_value_from_int64(irgen_size_bytes(g, type));
7,541✔
1345
   jit_value_t bytes = j_mul(g, length, scale);
7,541✔
1346

1347
   jit_reg_t bytes_r = jit_value_as_reg(bytes);
7,541✔
1348

1349
   if (value.kind == JIT_VALUE_INT64 && value.int64 == 0)
7,541✔
1350
      macro_bzero(g, addr, bytes_r);
5,236✔
1351
   else if (value.kind == JIT_VALUE_DOUBLE) {
2,305✔
1352
      jit_value_t bits = jit_value_from_int64(value.int64);
328✔
1353
      macro_memset(g, irgen_jit_size(g, type), addr, bits, bytes_r);
328✔
1354
   }
1355
   else
1356
      macro_memset(g, irgen_jit_size(g, type), addr, value, bytes_r);
1,977✔
1357
}
7,541✔
1358

1359
static void irgen_send_args(jit_irgen_t *g, mir_value_t n, int first)
92,978✔
1360
{
1361
   const int nargs = mir_count_args(g->mu, n);
92,978✔
1362

1363
   jit_value_t spill = { .kind = JIT_VALUE_INVALID };
92,978✔
1364
   int32_t spilloff = 0;
92,978✔
1365

1366
   for (int i = 0, pslot = first; i < nargs; i++) {
319,915✔
1367
      mir_value_t arg = mir_get_arg(g->mu, n, i);
226,937✔
1368
      if (arg.tag == MIR_TAG_LINKAGE || arg.tag == MIR_TAG_BLOCK)
226,937✔
1369
         continue;   // Skip function name and resume block
49,746✔
1370

1371
      int slots = irgen_slots_for_type(g, mir_get_type(g->mu, arg));
177,191✔
1372

1373
      if (pslot + slots >= JIT_MAX_ARGS - 1) {
177,191✔
1374
         // Large number of arguments spill to the heap
1375
         if (spill.kind == JIT_VALUE_INVALID) {
24✔
1376
            size_t size = slots * sizeof(jit_scalar_t);
4✔
1377
            for (int j = i + 1; j < nargs; j++) {
24✔
1378
               mir_type_t type = mir_get_type(g->mu, mir_get_arg(g->mu, n, j));
20✔
1379
               size += irgen_slots_for_type(g, type) * sizeof(jit_scalar_t);
20✔
1380
            }
1381

1382
            spill = macro_lalloc(g, jit_value_from_int64(size));
4✔
1383
            j_send(g, JIT_MAX_ARGS - 1, spill);
4✔
1384
            pslot = JIT_MAX_ARGS;
4✔
1385
            g->used_tlab = true;
4✔
1386
         }
1387

1388
         jit_reg_t base = irgen_as_reg(g, irgen_get_value(g, arg));
24✔
1389
         for (int j = 0; j < slots; j++, spilloff += sizeof(jit_scalar_t)) {
124✔
1390
            jit_value_t ptr = jit_addr_from_value(spill, spilloff);
100✔
1391
            j_store(g, JIT_SZ_64, jit_value_from_reg(base + j), ptr);
100✔
1392
         }
1393
      }
1394
      else if (slots > 1) {
177,167✔
1395
         jit_reg_t base = jit_value_as_reg(irgen_get_value(g, arg));
53,899✔
1396
         for (int j = 0; j < slots; j++)
215,650✔
1397
            j_send(g, pslot++, jit_value_from_reg(base + j));
161,751✔
1398
      }
1399
      else
1400
         j_send(g, pslot++, irgen_get_value(g, arg));
123,268✔
1401
   }
1402
}
92,978✔
1403

1404
static void irgen_op_return(jit_irgen_t *g, mir_value_t n)
85,155✔
1405
{
1406
   switch (mir_get_kind(g->mu)) {
85,155✔
1407
   case MIR_UNIT_PROCESS:
14,050✔
1408
      if (g->statereg.kind != JIT_VALUE_INVALID) {
14,050✔
1409
         // Set up for first call to process after reset
1410
         jit_value_t ptr = irgen_state_ptr(g);
5,005✔
1411
         j_store(g, JIT_SZ_32, jit_value_from_int64(1), ptr);
5,005✔
1412
         j_send(g, 0, g->statereg);
5,005✔
1413
      }
1414
      else
1415
         j_send(g, 0, jit_null_ptr());   // Stateless process
9,045✔
1416
      break;
1417

1418
   case MIR_UNIT_PROCEDURE:
273✔
1419
      j_send(g, 0, jit_null_ptr());
273✔
1420
      macro_trim(g);
273✔
1421
      break;
273✔
1422

1423
   case MIR_UNIT_INSTANCE:
24,059✔
1424
   case MIR_UNIT_PROTECTED:
1425
   case MIR_UNIT_PACKAGE:
1426
      j_send(g, 0, g->statereg);
24,059✔
1427
      break;
24,059✔
1428

1429
   case MIR_UNIT_PROPERTY:
1,388✔
1430
      if (mir_count_args(g->mu, n) > 0)
1,388✔
1431
         irgen_send_args(g, n, 1);
296✔
1432

1433
      if (g->statereg.kind != JIT_VALUE_INVALID)
1,388✔
1434
         j_send(g, 0, g->statereg);
108✔
1435
      else
1436
         j_send(g, 0, jit_null_ptr());   // Stateless property
1,280✔
1437
      break;
1438

1439
   case MIR_UNIT_FUNCTION:
45,385✔
1440
   case MIR_UNIT_THUNK:
1441
      if (mir_count_args(g->mu, n) > 0)
45,385✔
1442
         irgen_send_args(g, n, 0);
43,002✔
1443
      else
1444
         j_send(g, 0, jit_null_ptr());  // Procedure compiled as function
2,383✔
1445

1446
      if (g->used_tlab) {
45,385✔
1447
         const mir_mem_t mem = mir_get_mem(g->mu, mir_get_arg(g->mu, n, 0));
9,667✔
1448
         if (mem <= MIR_MEM_CONST)
9,667✔
1449
            macro_trim(g);
3,567✔
1450
         else if (mem == MIR_MEM_STACK) {
6,100✔
1451
            mir_dump(g->mu);
×
1452
            fatal_trace("returning pointer to stack allocation");
1453
         }
1454
      }
1455
      break;
1456
   }
1457

1458
   j_ret(g);
85,155✔
1459
}
85,155✔
1460

1461
static void irgen_op_not(jit_irgen_t *g, mir_value_t n)
3,545✔
1462
{
1463
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
3,545✔
1464
   g->map[n.id] = j_not(g, arg0);
3,545✔
1465
}
3,545✔
1466

1467
static void irgen_op_and(jit_irgen_t *g, mir_value_t n)
6,005✔
1468
{
1469
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
6,005✔
1470
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
6,005✔
1471

1472
   g->map[n.id] = j_and(g, arg0, arg1);
6,005✔
1473
}
6,005✔
1474

1475
static void irgen_op_or(jit_irgen_t *g, mir_value_t n)
2,766✔
1476
{
1477
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
2,766✔
1478
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
2,766✔
1479

1480
   g->map[n.id] = j_or(g, arg0, arg1);
2,766✔
1481
}
2,766✔
1482

1483
static void irgen_op_xor(jit_irgen_t *g, mir_value_t n)
149✔
1484
{
1485
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
149✔
1486
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
149✔
1487

1488
   g->map[n.id] = j_xor(g, arg0, arg1);
149✔
1489
}
149✔
1490

1491
static void irgen_op_trap_add(jit_irgen_t *g, mir_value_t n)
5,294✔
1492
{
1493
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
5,294✔
1494
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
5,294✔
1495
   jit_value_t locus = irgen_get_arg(g, n, 2);
5,294✔
1496

1497
   mir_type_t type = mir_get_type(g->mu, n);
5,294✔
1498
   jit_size_t sz = irgen_jit_size(g, type);
5,294✔
1499
   mir_repr_t repr = mir_get_repr(g->mu, type);
5,294✔
1500

1501
   jit_cc_t cc = irgen_repr_signed(repr) ? JIT_CC_O : JIT_CC_C;
5,294✔
1502
   g->map[n.id] = j_adds(g, sz, cc, arg0, arg1);
5,294✔
1503

1504
   irgen_label_t *l_pass = irgen_alloc_label(g);
5,294✔
1505
   j_jump(g, JIT_CC_F, l_pass);
5,294✔
1506

1507
   j_send(g, 0, arg0);
5,294✔
1508
   j_send(g, 1, arg1);
5,294✔
1509
   j_send(g, 2, locus);
5,294✔
1510
   macro_exit(g, JIT_EXIT_OVERFLOW);
5,294✔
1511

1512
   irgen_bind_label(g, l_pass);
5,294✔
1513
}
5,294✔
1514

1515
static void irgen_op_add(jit_irgen_t *g, mir_value_t n)
19,312✔
1516
{
1517
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
19,312✔
1518
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
19,312✔
1519

1520
   if (mir_is(g->mu, n, MIR_TYPE_REAL))
19,312✔
1521
      g->map[n.id] = j_fadd(g, arg0, arg1);
499✔
1522
   else
1523
      g->map[n.id] = j_add(g, arg0, arg1);
18,813✔
1524
}
19,312✔
1525

1526
static void irgen_op_trap_mul(jit_irgen_t *g, mir_value_t n)
488✔
1527
{
1528
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
488✔
1529
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
488✔
1530
   jit_value_t locus = irgen_get_arg(g, n, 2);
488✔
1531

1532
   mir_type_t type = mir_get_type(g->mu, n);
488✔
1533
   jit_size_t sz = irgen_jit_size(g, type);
488✔
1534
   mir_repr_t repr = mir_get_repr(g->mu, type);
488✔
1535

1536
   jit_cc_t cc = irgen_repr_signed(repr) ? JIT_CC_O : JIT_CC_C;
488✔
1537
   g->map[n.id] = j_muls(g, sz, cc, arg0, arg1);
488✔
1538

1539
   irgen_label_t *l_pass = irgen_alloc_label(g);
488✔
1540
   j_jump(g, JIT_CC_F, l_pass);
488✔
1541

1542
   j_send(g, 0, arg0);
488✔
1543
   j_send(g, 1, arg1);
488✔
1544
   j_send(g, 2, locus);
488✔
1545
   macro_exit(g, JIT_EXIT_OVERFLOW);
488✔
1546

1547
   irgen_bind_label(g, l_pass);
488✔
1548
}
488✔
1549

1550
static void irgen_op_mul(jit_irgen_t *g, mir_value_t n)
3,932✔
1551
{
1552
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
3,932✔
1553
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
3,932✔
1554

1555
   if (mir_is(g->mu, n, MIR_TYPE_REAL))
3,932✔
1556
      g->map[n.id] = j_fmul(g, arg0, arg1);
753✔
1557
   else
1558
      g->map[n.id] = j_mul(g, arg0, arg1);
3,179✔
1559
}
3,932✔
1560

1561
static void irgen_op_div(jit_irgen_t *g, mir_value_t n)
2,022✔
1562
{
1563
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
2,022✔
1564
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
2,022✔
1565

1566
   if (mir_is(g->mu, n, MIR_TYPE_REAL))
2,022✔
1567
      g->map[n.id] = j_fdiv(g, arg0, arg1);
453✔
1568
   else
1569
      g->map[n.id] = j_div(g, arg0, arg1);
1,569✔
1570
}
2,022✔
1571

1572
static void irgen_op_exp(jit_irgen_t *g, mir_value_t n)
175✔
1573
{
1574
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
175✔
1575
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
175✔
1576

1577
   if (mir_is(g->mu, n, MIR_TYPE_REAL))
175✔
1578
      g->map[n.id] = macro_fexp(g, arg0, arg1);
175✔
1579
   else
UNCOV
1580
      g->map[n.id] = macro_exp(g, JIT_SZ_UNSPEC, JIT_CC_NONE, arg0, arg1);
×
1581
}
175✔
1582

1583
static void irgen_op_trap_exp(jit_irgen_t *g, mir_value_t n)
683✔
1584
{
1585
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
683✔
1586
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
683✔
1587
   jit_value_t locus = irgen_get_arg(g, n, 2);
683✔
1588

1589
   mir_type_t type = mir_get_type(g->mu, n);
683✔
1590
   jit_size_t sz = irgen_jit_size(g, type);
683✔
1591
   mir_repr_t repr = mir_get_repr(g->mu, type);
683✔
1592

1593
   jit_cc_t cc = irgen_repr_signed(repr) ? JIT_CC_O : JIT_CC_C;
683✔
1594
   g->map[n.id] = macro_exp(g, sz, cc, arg0, arg1);
683✔
1595

1596
   irgen_label_t *l_pass = irgen_alloc_label(g);
683✔
1597
   j_jump(g, JIT_CC_F, l_pass);
683✔
1598

1599
   j_send(g, 0, arg0);
683✔
1600
   j_send(g, 1, arg1);
683✔
1601
   j_send(g, 2, locus);
683✔
1602
   macro_exit(g, JIT_EXIT_OVERFLOW);
683✔
1603

1604
   irgen_bind_label(g, l_pass);
683✔
1605
}
683✔
1606

1607
static void irgen_op_sub(jit_irgen_t *g, mir_value_t n)
37,824✔
1608
{
1609
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
37,824✔
1610
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
37,824✔
1611

1612
   if (mir_is(g->mu, n, MIR_TYPE_REAL))
37,824✔
1613
      g->map[n.id] = j_fsub(g, arg0, arg1);
498✔
1614
   else
1615
      g->map[n.id] = j_sub(g, arg0, arg1);
37,326✔
1616
}
37,824✔
1617

1618
static void irgen_op_trap_sub(jit_irgen_t *g, mir_value_t n)
1,717✔
1619
{
1620
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
1,717✔
1621
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
1,717✔
1622
   jit_value_t locus = irgen_get_arg(g, n, 2);
1,717✔
1623

1624
   mir_type_t type = mir_get_type(g->mu, n);
1,717✔
1625
   jit_size_t sz = irgen_jit_size(g, type);
1,717✔
1626
   mir_repr_t repr = mir_get_repr(g->mu, type);
1,717✔
1627

1628
   jit_cc_t cc = irgen_repr_signed(repr) ? JIT_CC_O : JIT_CC_C;
1,717✔
1629
   g->map[n.id] = j_subs(g, sz, cc, arg0, arg1);
1,717✔
1630

1631
   irgen_label_t *l_pass = irgen_alloc_label(g);
1,717✔
1632
   j_jump(g, JIT_CC_F, l_pass);
1,717✔
1633

1634
   j_send(g, 0, arg0);
1,717✔
1635
   j_send(g, 1, arg1);
1,717✔
1636
   j_send(g, 2, locus);
1,717✔
1637
   macro_exit(g, JIT_EXIT_OVERFLOW);
1,717✔
1638

1639
   irgen_bind_label(g, l_pass);
1,717✔
1640
}
1,717✔
1641

1642
static void irgen_op_neg(jit_irgen_t *g, mir_value_t n)
9,187✔
1643
{
1644
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
9,187✔
1645

1646
   if (mir_is_integral(g->mu, n))
9,187✔
1647
      g->map[n.id] = j_neg(g, arg0);
1,805✔
1648
   else
1649
      g->map[n.id] = j_fneg(g, arg0);
7,382✔
1650
}
9,187✔
1651

1652
static void irgen_op_trap_neg(jit_irgen_t *g, mir_value_t n)
343✔
1653
{
1654
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
343✔
1655
   jit_value_t locus = irgen_get_arg(g, n, 1);
343✔
1656

1657
   int64_t cmp;
343✔
1658
   switch (irgen_jit_size(g, mir_get_type(g->mu, n))) {
343✔
1659
   case JIT_SZ_8: cmp = INT8_MIN; break;
1660
   case JIT_SZ_16: cmp = INT16_MIN; break;
1661
   case JIT_SZ_32: cmp = INT32_MIN; break;
1662
   case JIT_SZ_64: cmp = INT64_MIN; break;
1663
   default: cmp = 0;
1664
   }
1665

1666
   irgen_label_t *cont = irgen_alloc_label(g);
343✔
1667
   j_cmp(g, JIT_CC_GT, arg0, jit_value_from_int64(cmp));
343✔
1668
   j_jump(g, JIT_CC_T, cont);
343✔
1669

1670
   j_send(g, 0, arg0);
343✔
1671
   j_send(g, 1, jit_value_from_int64(0));
343✔
1672
   j_send(g, 2, locus);
343✔
1673
   macro_exit(g, JIT_EXIT_OVERFLOW);
343✔
1674

1675
   irgen_bind_label(g, cont);
343✔
1676
   g->map[n.id] = j_neg(g, arg0);
343✔
1677
}
343✔
1678

1679
static void irgen_op_abs(jit_irgen_t *g, mir_value_t n)
986✔
1680
{
1681
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
986✔
1682

1683
   if (mir_is(g->mu, n, MIR_TYPE_REAL)) {
986✔
1684
      jit_value_t neg = j_fneg(g, arg0);
495✔
1685
      j_fcmp(g, JIT_CC_LT, arg0, jit_value_from_double(0.0));
495✔
1686
      g->map[n.id] = j_csel(g, neg, arg0);
495✔
1687
   }
1688
   else {
1689
      jit_value_t neg = j_neg(g, arg0);
491✔
1690
      j_cmp(g, JIT_CC_LT, arg0, jit_value_from_int64(0));
491✔
1691
      g->map[n.id] = j_csel(g, neg, arg0);
491✔
1692
   }
1693
}
986✔
1694

1695
static void irgen_op_mod(jit_irgen_t *g, mir_value_t n)
188✔
1696
{
1697
   jit_value_t numer = irgen_get_arg(g, n, 0);
188✔
1698
   jit_value_t denom = irgen_get_arg(g, n, 1);
188✔
1699

1700
   // Calculate the following:
1701
   //
1702
   //   long r = numer % denom;
1703
   //   if ((r > 0 && denom < 0) || (r < 0 && denom > 0))
1704
   //      r = r + denom;
1705

1706
   jit_value_t r = j_rem(g, numer, denom);
188✔
1707

1708
   irgen_label_t *l1 = irgen_alloc_label(g);
188✔
1709
   irgen_label_t *l2 = irgen_alloc_label(g);
188✔
1710

1711
   jit_value_t zero = jit_value_from_int64(0);
188✔
1712

1713
   j_cmp(g, JIT_CC_GT, r, zero);
188✔
1714
   j_ccmp(g, JIT_CC_LT, denom, zero);
188✔
1715
   j_jump(g, JIT_CC_T, l1);
188✔
1716

1717
   j_cmp(g, JIT_CC_LT, r, zero);
188✔
1718
   j_ccmp(g, JIT_CC_GT, denom, zero);
188✔
1719
   j_jump(g, JIT_CC_F, l2);
188✔
1720

1721
   irgen_bind_label(g, l1);
188✔
1722

1723
   jit_value_t r2 = j_add(g, r, denom);
188✔
1724
   j_mov(g, jit_value_as_reg(r), r2);
188✔
1725

1726
   irgen_bind_label(g, l2);
188✔
1727

1728
   g->map[n.id] = r;
188✔
1729
}
188✔
1730

1731
static void irgen_op_rem(jit_irgen_t *g, mir_value_t n)
881✔
1732
{
1733
   jit_value_t arg0 = irgen_get_arg(g, n, 0);
881✔
1734
   jit_value_t arg1 = irgen_get_arg(g, n, 1);
881✔
1735

1736
   g->map[n.id] = j_rem(g, arg0, arg1);
881✔
1737
}
881✔
1738

1739
static void irgen_op_cmp(jit_irgen_t *g, mir_value_t n)
50,892✔
1740
{
1741
   mir_value_t arg1 = mir_get_arg(g->mu, n, 1);
50,892✔
1742
   jit_value_t left = irgen_get_value(g, arg1);
50,892✔
1743
   jit_value_t right = irgen_get_arg(g, n, 2);
50,892✔
1744

1745
   jit_cc_t cc = irgen_get_jit_cc(irgen_get_enum(g, n, 0));
50,892✔
1746

1747
   if (mir_is(g->mu, arg1, MIR_TYPE_REAL))
50,892✔
1748
      j_fcmp(g, cc, left, right);
1,984✔
1749
   else
1750
      j_cmp(g, cc, left, right);
48,908✔
1751

1752
   g->map[n.id] = j_cset(g);
50,892✔
1753
   g->flags = n;
50,892✔
1754
}
50,892✔
1755

1756
static jit_value_t irgen_load_addr(jit_irgen_t *g, mir_type_t type,
174,892✔
1757
                                   jit_value_t ptr)
1758
{
1759
   jit_value_t addr = jit_addr_from_value(ptr, 0);
174,892✔
1760

1761
   switch (mir_get_class(g->mu, type)) {
174,892✔
1762
   case MIR_TYPE_OFFSET:
69,221✔
1763
   case MIR_TYPE_INT:
1764
      if (irgen_repr_signed(mir_get_repr(g->mu, type)))
69,221✔
1765
         return j_load(g, irgen_jit_size(g, type), addr);
37,449✔
1766
      else
1767
         return j_uload(g, irgen_jit_size(g, type), addr);
31,772✔
1768

1769
   case MIR_TYPE_REAL:
5,033✔
1770
      return j_load(g, JIT_SZ_64, addr);
5,033✔
1771

1772
   case MIR_TYPE_ACCESS:
5,874✔
1773
   case MIR_TYPE_POINTER:
1774
   case MIR_TYPE_CONTEXT:
1775
   case MIR_TYPE_TRIGGER:
1776
      return j_load(g, JIT_SZ_PTR, addr);
5,874✔
1777

1778
   case MIR_TYPE_FILE:
8✔
1779
      return j_load(g, JIT_SZ_32, addr);
8✔
1780

1781
   case MIR_TYPE_SIGNAL:
67,902✔
1782
      {
1783
         jit_value_t shared = j_load(g, JIT_SZ_PTR, addr);
67,902✔
1784
         addr = jit_addr_from_value(addr, sizeof(void *));
67,902✔
1785
         j_load(g, JIT_SZ_32, addr);   // Offset
67,902✔
1786
         return shared;
67,902✔
1787
      }
1788

1789
   case MIR_TYPE_UARRAY:
26,834✔
1790
      {
1791
         const int slots = irgen_slots_for_type(g, mir_get_elem(g->mu, type));
26,834✔
1792
         jit_value_t base = j_load(g, JIT_SZ_PTR, addr);
26,834✔
1793
         addr = jit_addr_from_value(addr, sizeof(void *));
26,834✔
1794
         for (int i = 1; i < slots; i++) {
30,363✔
1795
            j_load(g, JIT_SZ_PTR, addr);
3,529✔
1796
            addr = jit_addr_from_value(addr, sizeof(void *));
3,529✔
1797
         }
1798

1799
         const int ndims = mir_get_dims(g->mu, type);
26,834✔
1800
         for (int i = 0; i < 2*ndims; i++) {
81,380✔
1801
            j_load(g, JIT_SZ_64, addr);
54,546✔
1802
            addr = jit_addr_from_value(addr, sizeof(int64_t));
54,546✔
1803
         }
1804

1805
         return base;
26,834✔
1806
      }
1807

UNCOV
1808
   case MIR_TYPE_RESOLUTION:
×
1809
      {
UNCOV
1810
         jit_value_t base = j_load(g, JIT_SZ_PTR, addr);  // Function pointer
×
1811
         addr = jit_addr_from_value(addr, sizeof(void *));
×
UNCOV
1812
         j_load(g, JIT_SZ_PTR, addr);   // Context
×
1813
         addr = jit_addr_from_value(addr, sizeof(void *));
×
1814
         j_load(g, JIT_SZ_64, addr);   // Literals
×
1815
         addr = jit_addr_from_value(addr, sizeof(int64_t));
×
1816
         j_load(g, JIT_SZ_32, addr);   // Flags
×
1817
         return base;
×
1818
      }
1819

1820
   case MIR_TYPE_VEC2:
×
UNCOV
1821
      return j_load(g, JIT_SZ_64, addr);
×
1822

1823
   case MIR_TYPE_VEC4:
20✔
1824
      {
1825
         jit_value_t base = j_load(g, JIT_SZ_64, addr);
20✔
1826
         addr = jit_addr_from_value(addr, sizeof(uint64_t));
20✔
1827
         j_load(g, JIT_SZ_PTR, addr);
20✔
1828
         return base;
20✔
1829
      }
1830

UNCOV
1831
   default:
×
UNCOV
1832
      mir_dump(g->mu);
×
1833
      fatal_trace("cannot load type kind %d", mir_get_class(g->mu, type));
1834
   }
1835
}
1836

1837
static void irgen_op_load(jit_irgen_t *g, mir_value_t n)
174,892✔
1838
{
1839
   jit_value_t addr = irgen_get_arg(g, n, 0);
174,892✔
1840
   mir_type_t type = mir_get_type(g->mu, n);
174,892✔
1841

1842
   g->map[n.id] = irgen_load_addr(g, type, addr);
174,892✔
1843
}
174,892✔
1844

1845
static void irgen_store_addr(jit_irgen_t *g, mir_type_t type,
121,145✔
1846
                             jit_value_t value, jit_value_t ptr)
1847
{
1848
   jit_value_t addr = jit_addr_from_value(ptr, 0);
121,145✔
1849

1850
   if (jit_value_is_addr(value))
121,145✔
1851
      value = irgen_lea(g, value);   // Storing an address
2,975✔
1852

1853
   switch (mir_get_class(g->mu, type)) {
121,145✔
1854
   case MIR_TYPE_OFFSET:
74,616✔
1855
   case MIR_TYPE_INT:
1856
   case MIR_TYPE_ACCESS:
1857
   case MIR_TYPE_POINTER:
1858
   case MIR_TYPE_CONTEXT:
1859
   case MIR_TYPE_REAL:
1860
   case MIR_TYPE_TRIGGER:
1861
      j_store(g, irgen_jit_size(g, type), value, addr);
74,616✔
1862
      break;
74,616✔
1863

1864
   case MIR_TYPE_FILE:
1,471✔
1865
      j_store(g, JIT_SZ_32, value, addr);
1,471✔
1866
      break;
1,471✔
1867

1868
   case MIR_TYPE_UARRAY:
12,804✔
1869
      {
1870
         const int slots = irgen_slots_for_type(g, mir_get_elem(g->mu, type));
12,804✔
1871
         jit_reg_t base = jit_value_as_reg(value);
12,804✔
1872
         for (int i = 0; i < slots; i++) {
27,347✔
1873
            j_store(g, JIT_SZ_PTR, jit_value_from_reg(base + i), addr);
14,543✔
1874
            addr = jit_addr_from_value(addr, sizeof(void *));
14,543✔
1875
         }
1876

1877
         const int ndims = mir_get_dims(g->mu, type);
12,804✔
1878
         for (int i = 0; i < 2*ndims; i++) {
38,984✔
1879
            j_store(g, JIT_SZ_64, jit_value_from_reg(base + slots + i), addr);
26,180✔
1880
            addr = jit_addr_from_value(addr, sizeof(int64_t));
26,180✔
1881
         }
1882
      }
1883
      break;
1884

1885
   case MIR_TYPE_SIGNAL:
26,164✔
1886
      {
1887
         jit_reg_t base = jit_value_as_reg(value);
26,164✔
1888
         j_store(g, JIT_SZ_PTR, value, addr);
26,164✔
1889
         addr = jit_addr_from_value(addr, sizeof(void *));
26,164✔
1890
         j_store(g, JIT_SZ_32, jit_value_from_reg(base + 1), addr);
26,164✔
1891
      }
1892
      break;
26,164✔
1893

1894
   case MIR_TYPE_RESOLUTION:
6,010✔
1895
      {
1896
         jit_reg_t base = jit_value_as_reg(value);
6,010✔
1897
         j_store(g, JIT_SZ_PTR, value, addr);  // Function pointer
6,010✔
1898
         addr = jit_addr_from_value(addr, sizeof(void *));
6,010✔
1899
         j_store(g, JIT_SZ_PTR, jit_value_from_reg(base + 1), addr);  // Context
6,010✔
1900
         addr = jit_addr_from_value(addr, sizeof(void *));
6,010✔
1901
         j_store(g, JIT_SZ_64, jit_value_from_reg(base + 2), addr);  // Literals
6,010✔
1902
         addr = jit_addr_from_value(addr, sizeof(int64_t));
6,010✔
1903
         j_store(g, JIT_SZ_32, jit_value_from_reg(base + 3), addr);  // Flags
6,010✔
1904
      }
1905
      break;
6,010✔
1906

UNCOV
1907
   case MIR_TYPE_VEC2:
×
UNCOV
1908
      j_store(g, JIT_SZ_64, value, addr);
×
UNCOV
1909
      break;
×
1910

1911
   case MIR_TYPE_VEC4:
80✔
1912
      {
1913
         jit_reg_t base = jit_value_as_reg(value);
80✔
1914
         j_store(g, JIT_SZ_64, value, addr);
80✔
1915
         addr = jit_addr_from_value(addr, sizeof(uint64_t));
80✔
1916
         j_store(g, JIT_SZ_PTR, jit_value_from_reg(base + 1), addr);
80✔
1917
      }
1918
      break;
80✔
1919

UNCOV
1920
   default:
×
1921
      fatal_trace("cannot store type kind %d", mir_get_class(g->mu, type));
1922
   }
1923
}
121,145✔
1924

1925
static void irgen_op_store(jit_irgen_t *g, mir_value_t n)
121,145✔
1926
{
1927
   jit_value_t addr = irgen_get_arg(g, n, 0);
121,145✔
1928
   jit_value_t value = irgen_get_arg(g, n, 1);
121,145✔
1929
   mir_type_t type = mir_get_type(g->mu, n);
121,145✔
1930

1931
   irgen_store_addr(g, type, value, addr);
121,145✔
1932
}
121,145✔
1933

1934
static void irgen_op_locus(jit_irgen_t *g, mir_value_t n)
102,021✔
1935
{
1936
   g->map[n.id] = (jit_value_t){
204,042✔
1937
      .kind  = JIT_VALUE_LOCUS,
1938
      .locus = mir_get_locus(g->mu, n),
102,021✔
1939
   };
1940
}
102,021✔
1941

1942
static void irgen_op_wrap(jit_irgen_t *g, mir_value_t n)
42,882✔
1943
{
42,882✔
1944
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
42,882✔
1945
   jit_value_t ptr = irgen_lea(g, irgen_get_value(g, arg0));
42,882✔
1946

1947
   mir_type_t type = mir_get_type(g->mu, arg0);
42,882✔
1948

1949
   const int ndims = mir_count_args(g->mu, n) / 3;
42,882✔
1950
   const int slots = irgen_slots_for_type(g, type);
42,882✔
1951

1952
   // Registers must be contiguous
1953
   jit_reg_t base = irgen_alloc_reg(g);
42,882✔
1954
   j_mov(g, base, ptr);
42,882✔
1955
   for (int i = 1; i < slots; i++) {
44,556✔
1956
      jit_reg_t slot = irgen_alloc_reg(g);
1,674✔
1957
      j_mov(g, slot, jit_value_from_reg(jit_value_as_reg(ptr) + i));
1,674✔
1958
   }
1959
   jit_reg_t dims[ndims * 2];
42,882✔
1960
   for (int i = 0; i < ndims * 2; i++)
129,772✔
1961
      dims[i] = irgen_alloc_reg(g);
86,890✔
1962

1963
   for (int i = 0; i < ndims; i++) {
86,327✔
1964
      jit_value_t left  = irgen_get_arg(g, n, (i * 3) + 1);
43,445✔
1965
      jit_value_t right = irgen_get_arg(g, n, (i * 3) + 2);
43,445✔
1966
      jit_value_t dir   = irgen_get_arg(g, n, (i * 3) + 3);
43,445✔
1967

1968
      jit_value_t diff_up   = j_sub(g, right, left);
43,445✔
1969
      jit_value_t diff_down = j_sub(g, left, right);
43,445✔
1970

1971
      j_cmp(g, JIT_CC_EQ, dir, jit_value_from_int64(RANGE_DOWNTO));
43,445✔
1972
      jit_value_t diff    = j_csel(g, diff_down, diff_up);
43,445✔
1973
      jit_value_t length  = j_add(g, diff, jit_value_from_int64(1));
43,445✔
1974
      jit_value_t clamped = j_clamp(g, length);
43,445✔
1975
      jit_value_t mask    = j_neg(g, dir);
43,445✔
1976
      jit_value_t signlen = j_xor(g, mask, clamped);
43,445✔
1977

1978
      j_mov(g, dims[i*2], left);
43,445✔
1979
      j_mov(g, dims[i*2 + 1], signlen);
43,445✔
1980
   }
1981

1982
   g->map[n.id] = jit_value_from_reg(base);
42,882✔
1983
}
42,882✔
1984

1985
static void irgen_op_uarray_right(jit_irgen_t *g, mir_value_t n)
18,279✔
1986
{
1987
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
18,279✔
1988
   jit_reg_t base = jit_value_as_reg(irgen_get_value(g, arg0));
18,279✔
1989

1990
   mir_type_t elem = mir_get_elem(g->mu, mir_get_type(g->mu, arg0));
18,279✔
1991

1992
   const int dim = irgen_get_const(g, n, 1);
18,279✔
1993
   const int slots = irgen_slots_for_type(g, elem);
18,279✔
1994

1995
   jit_value_t left   = jit_value_from_reg(base + slots + dim*2);
18,279✔
1996
   jit_value_t length = jit_value_from_reg(base + slots + 1 + dim*2);
18,279✔
1997
   jit_value_t diff   = j_add(g, left, length);
18,279✔
1998
   j_cmp(g, JIT_CC_LT, length, jit_value_from_int64(0));
18,279✔
1999

2000
   jit_value_t adj = j_csel(g, jit_value_from_int64(2),
18,279✔
2001
                            jit_value_from_int64(-1));
2002

2003
   g->map[n.id] = j_add(g, diff, adj);
18,279✔
2004
}
18,279✔
2005

2006
static void irgen_op_uarray_left(jit_irgen_t *g, mir_value_t n)
22,146✔
2007
{
2008
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
22,146✔
2009
   jit_reg_t base = jit_value_as_reg(irgen_get_value(g, arg0));
22,146✔
2010

2011
   mir_type_t elem = mir_get_elem(g->mu, mir_get_type(g->mu, arg0));
22,146✔
2012

2013
   const int dim = irgen_get_const(g, n, 1);
22,146✔
2014
   const int slots = irgen_slots_for_type(g, elem);
22,146✔
2015

2016
   g->map[n.id] = jit_value_from_reg(base + slots + dim*2);
22,146✔
2017
}
22,146✔
2018

2019
static void irgen_op_uarray_dir(jit_irgen_t *g, mir_value_t n)
22,059✔
2020
{
2021
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
22,059✔
2022
   jit_reg_t base = jit_value_as_reg(irgen_get_value(g, arg0));
22,059✔
2023

2024
   mir_type_t elem = mir_get_elem(g->mu, mir_get_type(g->mu, arg0));
22,059✔
2025

2026
   const int dim = irgen_get_const(g, n, 1);
22,059✔
2027
   const int slots = irgen_slots_for_type(g, elem);
22,059✔
2028

2029
   jit_value_t length = jit_value_from_reg(base + slots + 1 + dim*2);
22,059✔
2030
   j_cmp(g, JIT_CC_LT, length, jit_value_from_int64(0));
22,059✔
2031

2032
   STATIC_ASSERT(RANGE_DOWNTO == 1);
22,059✔
2033

2034
   g->map[n.id] = j_cset(g);
22,059✔
2035
   g->flags = n;
22,059✔
2036
}
22,059✔
2037

2038
static void irgen_op_uarray_len(jit_irgen_t *g, mir_value_t n)
28,600✔
2039
{
2040
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
28,600✔
2041
   jit_reg_t base = jit_value_as_reg(irgen_get_value(g, arg0));
28,600✔
2042

2043
   mir_type_t elem = mir_get_elem(g->mu, mir_get_type(g->mu, arg0));
28,600✔
2044

2045
   const int dim = irgen_get_const(g, n, 1);
28,600✔
2046
   const int slots = irgen_slots_for_type(g, elem);
28,600✔
2047

2048
   jit_value_t length = jit_value_from_reg(base + slots + 1 + dim*2);
28,600✔
2049
   jit_value_t mask = j_asr(g, length, jit_value_from_int64(63));
28,600✔
2050
   g->map[n.id] = j_xor(g, mask, length);
28,600✔
2051
}
28,600✔
2052

2053
static void irgen_op_unwrap(jit_irgen_t *g, mir_value_t n)
34,641✔
2054
{
2055
   jit_value_t base = irgen_get_arg(g, n, 0);
34,641✔
2056
   g->map[n.id] = base;
34,641✔
2057
}
34,641✔
2058

2059
static void irgen_op_array_ref(jit_irgen_t *g, mir_value_t n)
49,069✔
2060
{
2061
   if (mir_is_signal(g->mu, n)) {
49,069✔
2062
      jit_value_t shared = irgen_get_arg(g, n, 0);
9,367✔
2063
      jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
9,367✔
2064

2065
      jit_value_t arg1 = irgen_get_arg(g, n, 1);
9,367✔
2066

2067
      if (arg1.kind == JIT_VALUE_INT64 && arg1.int64 == 0)
9,367✔
2068
         g->map[n.id] = shared;
2,166✔
2069
      else {
2070
         jit_reg_t new = irgen_alloc_reg(g);
7,201✔
2071
         j_mov(g, new, shared);
7,201✔
2072
         g->map[n.id] = jit_value_from_reg(new);
7,201✔
2073

2074
         // Offset must be next sequential register
2075
         j_add(g, offset, arg1);
7,201✔
2076
      }
2077
   }
2078
   else {
2079
      assert(mir_is(g->mu, n, MIR_TYPE_POINTER));
39,702✔
2080
      mir_type_t elem = mir_get_elem(g->mu, mir_get_type(g->mu, n));
39,702✔
2081
      const int scale = irgen_size_bytes(g, elem);
39,702✔
2082

2083
      jit_value_t arg0 = irgen_get_arg(g, n, 0);
39,702✔
2084
      jit_value_t arg1 = irgen_get_arg(g, n, 1);
39,702✔
2085

2086
      if (arg1.kind == JIT_VALUE_INT64)
39,702✔
2087
         g->map[n.id] = jit_addr_from_value(arg0, arg1.int64 * scale);
9,623✔
2088
      else {
2089
         jit_value_t scaled = j_mul(g, arg1, jit_value_from_int64(scale));
30,079✔
2090
         jit_value_t addr = irgen_lea(g, arg0);
30,079✔
2091
         g->map[n.id] = j_add(g, addr, scaled);
30,079✔
2092
      }
2093
   }
2094
}
49,069✔
2095

2096
static void irgen_op_record_ref(jit_irgen_t *g, mir_value_t n)
48,397✔
2097
{
2098
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
48,397✔
2099
   mir_type_t rtype = mir_get_elem(g->mu, mir_get_type(g->mu, arg0));
48,397✔
2100
   assert(mir_get_class(g->mu, rtype) == MIR_TYPE_RECORD);
48,397✔
2101

2102
   const int field = irgen_get_const(g, n, 1);
48,397✔
2103

2104
   size_t nfields;
48,397✔
2105
   const mir_type_t *ftypes = mir_get_fields(g->mu, rtype, &nfields);
48,397✔
2106
   assert(field < nfields);
48,397✔
2107

2108
   // TODO: cache field offsets somewhere? This duplicates irgen_size_bytes
2109
   int offset = 0;
2110
   for (int i = 0; i < field; i++) {
158,878✔
2111
      const int fb = irgen_size_bytes(g, ftypes[i]);
110,481✔
2112
      const int align = irgen_align_of(g, ftypes[i]);
110,481✔
2113

2114
      offset = ALIGN_UP(offset, align);
110,481✔
2115
      offset += fb;
110,481✔
2116
   }
2117

2118
   const int align = irgen_align_of(g, ftypes[field]);
48,397✔
2119
   offset = ALIGN_UP(offset, align);
48,397✔
2120

2121
   jit_value_t rptr = irgen_get_value(g, arg0);
48,397✔
2122
   g->map[n.id] = jit_addr_from_value(rptr, offset);
48,397✔
2123
}
48,397✔
2124

2125
static void irgen_op_context_upref(jit_irgen_t *g, mir_value_t n)
15,822✔
2126
{
2127
   const int hops = irgen_get_const(g, n, 0);
15,822✔
2128

2129
   if (hops == 0) {
15,822✔
2130
      assert(g->statereg.kind != JIT_VALUE_INVALID);
3,526✔
2131
      g->map[n.id] = g->statereg;
3,526✔
2132
   }
2133
   else {
2134
      jit_value_t context = irgen_get_context(g);
12,296✔
2135

2136
      for (int i = 1; i < hops; i++)
12,673✔
2137
         context = j_load(g, JIT_SZ_PTR, jit_addr_from_value(context, 0));
377✔
2138

2139
      g->map[n.id] = context;
12,296✔
2140
   }
2141
}
15,822✔
2142

2143
static void irgen_op_var_upref(jit_irgen_t *g, mir_value_t n)
63,061✔
2144
{
2145
   jit_value_t context = irgen_get_context(g);
63,061✔
2146

2147
   const int hops = irgen_get_const(g, n, 0);
63,061✔
2148
   const int nth = irgen_get_const(g, n, 2);
63,061✔
2149
   ident_t unit_name = mir_get_name(g->mu, mir_get_arg(g->mu, n, 1));
63,061✔
2150

2151
   for (int i = 1; i < hops; i++)
77,369✔
2152
      context = j_load(g, JIT_SZ_PTR, jit_addr_from_value(context, 0));
14,308✔
2153

2154
   // TODO: maybe we should cache these somewhere?
2155
   jit_handle_t handle = jit_lazy_compile(g->func->jit, unit_name);
63,061✔
2156
   jit_func_t *cf = jit_get_func(g->func->jit, handle);
63,061✔
2157

2158
   // Handle potential circular dependency
2159
   // TODO: it would be better to avoid this entirely
2160
   const link_tab_t *tab = load_acquire(&(cf->linktab));
63,061✔
2161
   if (tab == NULL) {
63,061✔
2162
      jit_fill_irbuf(cf);
1✔
2163
      tab = load_acquire(&(cf->linktab));
1✔
2164
      assert(tab);
1✔
2165
   }
2166

2167
   assert(nth < cf->nvars);
63,061✔
2168
   const int offset = tab[nth].offset;
63,061✔
2169

2170
   g->map[n.id] = jit_addr_from_value(context, offset);
63,061✔
2171
}
63,061✔
2172

2173
static void irgen_op_cast(jit_irgen_t *g, mir_value_t n)
73,899✔
2174
{
2175
   mir_value_t arg = mir_get_arg(g->mu, n, 0);
73,899✔
2176

2177
   mir_type_t result_type = mir_get_type(g->mu, n);
73,899✔
2178
   mir_class_t result_kind = mir_get_class(g->mu, result_type);
73,899✔
2179

2180
   if (result_kind == MIR_TYPE_REAL && mir_is_integral(g->mu, arg))
73,899✔
2181
      g->map[n.id] = j_scvtf(g, irgen_get_value(g, arg));
477✔
2182
   else if (result_kind == MIR_TYPE_INT && mir_is(g->mu, arg, MIR_TYPE_REAL))
73,422✔
2183
      g->map[n.id] = j_fcvtns(g, irgen_get_value(g, arg));
170✔
2184
   else if ((result_kind == MIR_TYPE_INT || result_kind == MIR_TYPE_OFFSET)
73,252✔
2185
            && mir_is_integral(g->mu, arg)) {
72,476✔
2186
      // No sign extension or truncation is necessary as integer
2187
      // registers are always 64 bits wide
2188
      g->map[n.id] = irgen_get_value(g, arg);
72,472✔
2189
   }
2190
   else if (result_kind == MIR_TYPE_REAL) {
780✔
2191
      // Reals are always represented with IEEE doubles
UNCOV
2192
      assert(mir_is(g->mu, arg, MIR_TYPE_REAL));
×
UNCOV
2193
      g->map[n.id] = irgen_get_value(g, arg);
×
2194
   }
2195
   else if (result_kind == MIR_TYPE_ACCESS) {
780✔
2196
      // Casting away opaqueness
2197
      assert(mir_is(g->mu, arg, MIR_TYPE_ACCESS));
432✔
2198
      g->map[n.id] = irgen_get_value(g, arg);
432✔
2199
   }
2200
   else if (result_kind == MIR_TYPE_VEC4) {
348✔
2201
      mir_type_t arg_type = mir_get_type(g->mu, arg);
340✔
2202

2203
      jit_value_t abits = irgen_get_value(g, arg), bbits;
340✔
2204
      if (mir_get_class(g->mu, arg_type) == MIR_TYPE_VEC4)
340✔
2205
         bbits = jit_value_from_reg(jit_value_as_reg(abits) + 1);
264✔
2206
      else
2207
         bbits = jit_value_from_int64(0);
76✔
2208

2209
      const int result_size = mir_get_size(g->mu, result_type);
340✔
2210
      const int arg_size = mir_get_size(g->mu, result_type);
340✔
2211
      assert(result_size <= 64); // TODO
340✔
2212
      assert(arg_size <= 64); // TODO
340✔
2213

2214
      if (result_size < arg_size) {
340✔
UNCOV
2215
         uint64_t mask = ~UINT64_C(0);
×
UNCOV
2216
         if (result_size < 64) mask >>= 64 - result_size;
×
2217

2218
         g->map[n.id] = j_and(g, abits, jit_value_from_int64(mask));
×
2219
         j_and(g, bbits, jit_value_from_int64(mask));
×
2220
      }
2221
      else if (bbits.kind != JIT_VALUE_REG) {
340✔
2222
         jit_reg_t areg = irgen_alloc_reg(g), breg = irgen_alloc_reg(g);
76✔
2223
         j_mov(g, areg, abits);
76✔
2224
         j_mov(g, breg, bbits);
76✔
2225
         g->map[n.id] = jit_value_from_reg(areg);
76✔
2226
      }
2227
      else
2228
         g->map[n.id] = abits;  // No-op  (TODO: sign extend)
264✔
2229
   }
2230
   else if (result_kind == MIR_TYPE_VEC2 && mir_is(g->mu, arg, MIR_TYPE_VEC4)) {
8✔
2231
      g->map[n.id] = irgen_get_value(g, arg);  // No-op  (TODO: sign extend)
4✔
2232
   }
2233
   else if ((result_kind == MIR_TYPE_INT || result_kind == MIR_TYPE_OFFSET)
4✔
2234
            && mir_is_vector(g->mu, arg))
4✔
2235
      g->map[n.id] = irgen_get_value(g, arg);  // No-op (take A-bits)
4✔
2236
   else {
UNCOV
2237
      mir_dump(g->mu);
×
2238
      fatal_trace("unhandled cast");
2239
   }
2240
}
73,899✔
2241

2242
static void irgen_op_range_null(jit_irgen_t *g, mir_value_t n)
4,326✔
2243
{
2244
   jit_value_t left  = irgen_get_arg(g, n, 0);
4,326✔
2245
   jit_value_t right = irgen_get_arg(g, n, 1);
4,326✔
2246

2247
   irgen_label_t *l_downto = irgen_alloc_label(g);
4,326✔
2248
   irgen_label_t *l_after  = irgen_alloc_label(g);
4,326✔
2249

2250
   mir_value_t arg2 = mir_get_arg(g->mu, n, 2);
4,326✔
2251
   if (!mir_equals(arg2, g->flags)) {
4,326✔
2252
      jit_value_t dir = irgen_get_value(g, arg2);
2,348✔
2253
      j_cmp(g, JIT_CC_EQ, dir, jit_value_from_int64(RANGE_DOWNTO));
2,348✔
2254
   }
2255

2256
   j_jump(g, JIT_CC_T, l_downto);
4,326✔
2257

2258
   j_cmp(g, JIT_CC_GT, left, right);
4,326✔
2259
   j_jump(g, JIT_CC_NONE, l_after);
4,326✔
2260

2261
   irgen_bind_label(g, l_downto);
4,326✔
2262

2263
   j_cmp(g, JIT_CC_GT, right, left);
4,326✔
2264

2265
   irgen_bind_label(g, l_after);
4,326✔
2266

2267
   g->map[n.id] = j_cset(g);
4,326✔
2268
   g->flags = n;
4,326✔
2269
}
4,326✔
2270

2271
static void irgen_op_range_length(jit_irgen_t *g, mir_value_t n)
9,001✔
2272
{
2273
   jit_value_t left  = irgen_get_arg(g, n, 0);
9,001✔
2274
   jit_value_t right = irgen_get_arg(g, n, 1);
9,001✔
2275

2276
   mir_value_t arg2 = mir_get_arg(g->mu, n, 2);
9,001✔
2277

2278
   jit_value_t diff;
9,001✔
2279
   int64_t dconst;
9,001✔
2280
   if (mir_get_const(g->mu, arg2, &dconst)) {
9,001✔
2281
      jit_value_t high = dconst == RANGE_TO ? right : left;
8,511✔
2282
      jit_value_t low = dconst == RANGE_TO ? left : right;
8,511✔
2283

2284
      diff = j_sub(g, high, low);
8,511✔
2285
   }
2286
   else {
2287
      irgen_label_t *l_downto = irgen_alloc_label(g);
490✔
2288
      irgen_label_t *l_after  = irgen_alloc_label(g);
490✔
2289
      if (!mir_equals(arg2, g->flags)) {
490✔
2290
         jit_value_t dir = irgen_get_value(g, arg2);
205✔
2291
         j_cmp(g, JIT_CC_EQ, dir, jit_value_from_int64(RANGE_DOWNTO));
205✔
2292
      }
2293

2294
      j_jump(g, JIT_CC_T, l_downto);
490✔
2295

2296
      jit_value_t diff_up = j_sub(g, right, left);
490✔
2297
      j_jump(g, JIT_CC_NONE, l_after);
490✔
2298

2299
      irgen_bind_label(g, l_downto);
490✔
2300

2301
      jit_value_t diff_down = j_sub(g, left, right);
490✔
2302

2303
      irgen_bind_label(g, l_after);
490✔
2304

2305
      diff = j_csel(g, diff_down, diff_up);
490✔
2306
   }
2307

2308
   jit_value_t length = j_add(g, diff, jit_value_from_int64(1));
9,001✔
2309
   jit_value_t clamped = j_clamp(g, length);
9,001✔
2310

2311
   g->map[n.id] = clamped;
9,001✔
2312
}
9,001✔
2313

2314
static void irgen_op_cond(jit_irgen_t *g, mir_value_t n)
46,425✔
2315
{
2316
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
46,425✔
2317
   if (!mir_equals(arg0, g->flags)) {
46,425✔
2318
      jit_value_t test = irgen_get_value(g, arg0);
11,326✔
2319
      j_cmp(g, JIT_CC_NE, test, jit_value_from_int64(0));
11,326✔
2320
   }
2321

2322
   mir_block_t t0 = mir_cast_block(mir_get_arg(g->mu, n, 1));
46,425✔
2323
   mir_block_t t1 = mir_cast_block(mir_get_arg(g->mu, n, 2));
46,425✔
2324

2325
   if (t0.id == g->curblock.id + 1)
46,425✔
2326
      j_jump(g, JIT_CC_F, g->blocks[t1.id]);
15,007✔
2327
   else if (t1.id == g->curblock.id + 1)
31,418✔
2328
      j_jump(g, JIT_CC_T, g->blocks[t0.id]);
16,423✔
2329
   else {
2330
      j_jump(g, JIT_CC_T, g->blocks[t0.id]);
14,995✔
2331
      j_jump(g, JIT_CC_NONE, g->blocks[t1.id]);
14,995✔
2332
   }
2333
}
46,425✔
2334

2335
static void irgen_op_case(jit_irgen_t *g, mir_value_t n)
961✔
2336
{
2337
   jit_value_t value = irgen_get_arg(g, n, 0);
961✔
2338
   jit_reg_t reg = jit_value_as_reg(value);
961✔
2339
   mir_block_t def = mir_cast_block(mir_get_arg(g->mu, n, 1));
961✔
2340

2341
   const int nargs = mir_count_args(g->mu, n);
961✔
2342
   for (int i = 2; i < nargs; i += 2) {
10,390✔
2343
      jit_value_t cmp = irgen_get_arg(g, n, i);
9,429✔
2344
      mir_block_t b = mir_cast_block(mir_get_arg(g->mu, n, i + 1));
9,429✔
2345
      irgen_label_t *l = g->blocks[b.id];
9,429✔
2346
      macro_case(g, reg, cmp, l);
9,429✔
2347
   }
2348

2349
   j_jump(g, JIT_CC_NONE, g->blocks[def.id]);
961✔
2350
}
961✔
2351

2352
static void irgen_op_select(jit_irgen_t *g, mir_value_t n)
18,038✔
2353
{
2354
   jit_value_t iftrue  = irgen_get_arg(g, n, 1);
18,038✔
2355
   jit_value_t iffalse = irgen_get_arg(g, n, 2);
18,038✔
2356

2357
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
18,038✔
2358
   if (!mir_equals(arg0, g->flags)) {
18,038✔
2359
      jit_value_t test = irgen_get_arg(g, n, 0);
12,032✔
2360
      j_cmp(g, JIT_CC_NE, test, jit_value_from_int64(0));
12,032✔
2361
   }
2362

2363
   g->map[n.id] = j_csel(g, iftrue, iffalse);
18,038✔
2364

2365
   const int slots = irgen_slots_for_type(g, mir_get_type(g->mu, n));
18,038✔
2366
   for (int i = 1; i < slots; i++) {
18,054✔
2367
      jit_value_t iftrue_i = jit_value_from_reg(jit_value_as_reg(iftrue) + i);
16✔
2368
      jit_value_t iffalse_i = jit_value_from_reg(jit_value_as_reg(iffalse) + i);
16✔
2369
      j_csel(g, iftrue_i, iffalse_i);
16✔
2370
   }
2371
}
18,038✔
2372

2373
static void irgen_op_jump(jit_irgen_t *g, mir_value_t n)
50,852✔
2374
{
2375
   mir_block_t target = mir_cast_block(mir_get_arg(g->mu, n, 0));
50,852✔
2376
   j_jump(g, JIT_CC_NONE, g->blocks[target.id]);
50,852✔
2377
}
50,852✔
2378

2379
static void irgen_op_fcall(jit_irgen_t *g, mir_value_t n)
45,815✔
2380
{
2381
   irgen_emit_debuginfo(g, n);   // For stack traces
45,815✔
2382

2383
   mir_type_t rtype = mir_get_type(g->mu, n);
45,815✔
2384
   if (mir_is_null(rtype)) {
45,815✔
2385
      // Must call using procedure calling convention
2386
      j_send(g, 0, jit_value_from_int64(0));
6,679✔
2387
      irgen_send_args(g, n, 1);
6,679✔
2388
   }
2389
   else
2390
      irgen_send_args(g, n, 0);
39,136✔
2391

2392
   j_call(g, irgen_get_handle(g, n, 0));
45,815✔
2393

2394
   if (!mir_is_null(rtype)) {
45,815✔
2395
      const int slots = irgen_slots_for_type(g, rtype);
39,136✔
2396
      g->map[n.id] = j_recv(g, 0);
39,136✔
2397
      for (int i = 1; i < slots; i++)
65,560✔
2398
         j_recv(g, i);   // Must be contiguous registers
26,424✔
2399

2400
      const mir_class_t rclass = mir_get_class(g->mu, rtype);
39,136✔
2401
      g->used_tlab |= rclass == MIR_TYPE_UARRAY
39,136✔
2402
         || rclass == MIR_TYPE_POINTER;
39,136✔
2403
   }
2404
   else {
2405
      irgen_label_t *cont = irgen_alloc_label(g);
6,679✔
2406
      jit_value_t state = j_recv(g, 0);
6,679✔
2407
      j_cmp(g, JIT_CC_EQ, state, jit_null_ptr());
6,679✔
2408
      j_jump(g, JIT_CC_T, cont);
6,679✔
2409
      macro_exit(g, JIT_EXIT_FUNC_WAIT);
6,679✔
2410
      irgen_bind_label(g, cont);
6,679✔
2411
   }
2412
}
45,815✔
2413

2414
static void irgen_op_syscall(jit_irgen_t *g, mir_value_t n)
756✔
2415
{
2416
   irgen_emit_debuginfo(g, n);   // For stack traces
756✔
2417

2418
   irgen_send_args(g, n, 0);
756✔
2419
   macro_exit(g, JIT_EXIT_SYSCALL);
756✔
2420

2421
   mir_type_t rtype = mir_get_type(g->mu, n);
756✔
2422
   if (!mir_is_null(rtype)) {
756✔
2423
      const int slots = irgen_slots_for_type(g, rtype);
52✔
2424
      g->map[n.id] = j_recv(g, 0);
52✔
2425
      for (int i = 1; i < slots; i++)
52✔
UNCOV
2426
         j_recv(g, i);   // Must be contiguous registers
×
2427
   }
2428
}
756✔
2429

2430
static void irgen_pcall_suspend(jit_irgen_t *g, jit_value_t state,
2,168✔
2431
                                irgen_label_t *cont)
2432
{
2433
   jit_value_t pcall_ptr = irgen_pcall_ptr(g);
2,168✔
2434
   j_store(g, JIT_SZ_PTR, state, pcall_ptr);
2,168✔
2435

2436
   j_cmp(g, JIT_CC_EQ, state, jit_null_ptr());
2,168✔
2437
   j_jump(g, JIT_CC_T, cont);
2,168✔
2438

2439
   j_send(g, 0, g->statereg);
2,168✔
2440

2441
   j_ret(g);
2,168✔
2442
}
2,168✔
2443

2444
static void irgen_op_pcall(jit_irgen_t *g, mir_value_t n)
1,084✔
2445
{
2446
   irgen_emit_debuginfo(g, n);   // For stack traces
1,084✔
2447

2448
   // First argument to procedure is suspended state
2449
   j_send(g, 0, jit_value_from_int64(0));
1,084✔
2450

2451
   irgen_send_args(g, n, 1);
1,084✔
2452

2453
   jit_handle_t handle = irgen_get_handle(g, n, 1);
1,084✔
2454
   j_call(g, handle);
1,084✔
2455

2456
   irgen_label_t *cont = irgen_alloc_label(g);
1,084✔
2457
   jit_value_t state = j_recv(g, 0);
1,084✔
2458

2459
   mir_block_t resume = mir_cast_block(mir_get_arg(g->mu, n, 0));
1,084✔
2460

2461
   jit_value_t state_ptr = irgen_state_ptr(g);
1,084✔
2462
   j_store(g, JIT_SZ_32, jit_value_from_int64(resume.id), state_ptr);
1,084✔
2463

2464
   irgen_pcall_suspend(g, state, cont);
1,084✔
2465

2466
   irgen_bind_label(g, cont);
1,084✔
2467
   j_jump(g, JIT_CC_NONE, g->blocks[resume.id]);
1,084✔
2468
}
1,084✔
2469

2470
static void irgen_op_resume(jit_irgen_t *g, mir_value_t n)
1,084✔
2471
{
2472
   jit_value_t old_state = j_load(g, JIT_SZ_PTR, irgen_pcall_ptr(g));
1,084✔
2473
   irgen_label_t *cont = irgen_alloc_label(g);
1,084✔
2474
   j_cmp(g, JIT_CC_EQ, old_state, jit_null_ptr());
1,084✔
2475
   j_jump(g, JIT_CC_T, cont);
1,084✔
2476

2477
   jit_handle_t handle = irgen_get_handle(g, n, 0);
1,084✔
2478

2479
   j_send(g, 0, old_state);
1,084✔
2480
   j_call(g, handle);
1,084✔
2481

2482
   jit_value_t new_state = j_recv(g, 0);
1,084✔
2483
   irgen_pcall_suspend(g, new_state, cont);
1,084✔
2484

2485
   irgen_bind_label(g, cont);
1,084✔
2486
}
1,084✔
2487

2488
static void irgen_op_wait(jit_irgen_t *g, mir_value_t n)
18,475✔
2489
{
2490
   if (mir_count_args(g->mu, n) > 1) {
18,475✔
2491
      jit_value_t after = irgen_get_arg(g, n, 1);
7,357✔
2492
      j_send(g, 0, after);
7,357✔
2493
      macro_exit(g, JIT_EXIT_SCHED_PROCESS);
7,357✔
2494
   }
2495

2496
   if (g->statereg.kind != JIT_VALUE_INVALID) {
18,475✔
2497
      mir_block_t target = mir_cast_block(mir_get_arg(g->mu, n, 0));
12,842✔
2498
      jit_value_t ptr = irgen_state_ptr(g);
12,842✔
2499
      j_store(g, JIT_SZ_32, jit_value_from_int64(target.id), ptr);
12,842✔
2500
   }
2501

2502
   if (mir_get_kind(g->mu) == MIR_UNIT_PROCEDURE)
18,475✔
2503
      j_send(g, 0, g->statereg);
364✔
2504
   else
2505
      j_send(g, 0, jit_value_from_int64(0));
18,111✔
2506

2507
   j_ret(g);
18,475✔
2508
}
18,475✔
2509

2510
static void irgen_op_protected_init(jit_irgen_t *g, mir_value_t n)
721✔
2511
{
2512
   jit_handle_t handle = irgen_get_handle(g, n, 0);
721✔
2513

2514
   irgen_send_args(g, n, 0);
721✔
2515
   j_call(g, handle);
721✔
2516

2517
   g->map[n.id] = j_recv(g, 0);
721✔
2518
}
721✔
2519

2520
static void irgen_op_reflect_value(jit_irgen_t *g, mir_value_t n)
64✔
2521
{
2522
   jit_value_t value = irgen_get_arg(g, n, 0);
64✔
2523
   jit_value_t context = irgen_get_arg(g, n, 1);
64✔
2524
   jit_value_t locus = irgen_get_arg(g, n, 2);
64✔
2525

2526
   j_send(g, 0, context);
64✔
2527
   j_send(g, 1, value);
64✔
2528
   j_send(g, 2, locus);
64✔
2529

2530
   if (mir_count_args(g->mu, n) > 3) {
64✔
2531
      mir_value_t bounds = mir_get_arg(g->mu, n, 3);
8✔
2532
      const int slots = irgen_slots_for_type(g, mir_get_type(g->mu, bounds));
8✔
2533
      if (slots > 1) {
8✔
2534
         jit_reg_t base = jit_value_as_reg(irgen_get_value(g, bounds));
8✔
2535
         for (int j = 0; j < slots; j++)
32✔
2536
            j_send(g, j + 3, jit_value_from_reg(base + j));
24✔
2537
      }
2538
      else
UNCOV
2539
         j_send(g, 3, irgen_get_value(g, bounds));
×
2540
   }
2541
   else
2542
      j_send(g, 3, value);
56✔
2543

2544
   macro_exit(g, JIT_EXIT_REFLECT_VALUE);
64✔
2545

2546
   g->map[n.id] = j_recv(g, 0);
64✔
2547
}
64✔
2548

2549
static void irgen_op_reflect_subtype(jit_irgen_t *g, mir_value_t n)
56✔
2550
{
2551
   jit_value_t context = irgen_get_arg(g, n, 0);
56✔
2552
   jit_value_t locus = irgen_get_arg(g, n, 1);
56✔
2553

2554
   j_send(g, 0, context);
56✔
2555
   j_send(g, 1, locus);
56✔
2556

2557
   if (mir_count_args(g->mu, n) > 2) {
56✔
UNCOV
2558
      mir_value_t bounds = mir_get_arg(g->mu, n, 2);
×
UNCOV
2559
      const int slots = irgen_slots_for_type(g, mir_get_type(g->mu, bounds));
×
UNCOV
2560
      if (slots > 1) {
×
2561
         jit_reg_t base = jit_value_as_reg(irgen_get_value(g, bounds));
×
2562
         for (int j = 0; j < slots; j++)
×
2563
            j_send(g, j + 2, jit_value_from_reg(base + j));
×
2564
      }
2565
      else
2566
         j_send(g, 2, irgen_get_value(g, bounds));
×
2567
   }
2568

2569
   macro_exit(g, JIT_EXIT_REFLECT_SUBTYPE);
56✔
2570

2571
   g->map[n.id] = j_recv(g, 0);
56✔
2572
}
56✔
2573

2574
static void irgen_op_process_init(jit_irgen_t *g, mir_value_t n)
154✔
2575
{
2576
   jit_handle_t handle = irgen_get_handle(g, n, 0);
154✔
2577
   jit_value_t locus = irgen_get_arg(g, n, 1);
154✔
2578

2579
   j_send(g, 0, jit_value_from_handle(handle));
154✔
2580
   j_send(g, 1, locus);
154✔
2581
   macro_exit(g, JIT_EXIT_PROCESS_INIT);
154✔
2582
}
154✔
2583

2584
static void irgen_op_index_check(jit_irgen_t *g, mir_value_t n)
20,976✔
2585
{
2586
   mir_value_t arg3 = mir_get_arg(g->mu, n, 3);
20,976✔
2587

2588
   jit_value_t value = irgen_get_arg(g, n, 0);
20,976✔
2589
   jit_value_t left  = irgen_get_arg(g, n, 1);
20,976✔
2590
   jit_value_t right = irgen_get_arg(g, n, 2);
20,976✔
2591
   jit_value_t dir   = irgen_get_value(g, arg3);
20,976✔
2592
   jit_value_t locus = irgen_get_arg(g, n, 4);
20,976✔
2593
   jit_value_t hint  = irgen_get_arg(g, n, 5);
20,976✔
2594

2595
   if (!mir_equals(arg3, g->flags))
20,976✔
2596
      j_cmp(g, JIT_CC_EQ, dir, jit_value_from_int64(RANGE_DOWNTO));
9,650✔
2597

2598
   jit_value_t low = j_csel(g, right, left);
20,976✔
2599
   jit_value_t high = j_csel(g, left, right);
20,976✔
2600

2601
   irgen_label_t *l_pass = irgen_alloc_label(g);
20,976✔
2602

2603
   j_cmp(g, JIT_CC_GE, value, low);
20,976✔
2604
   j_ccmp(g, JIT_CC_LE, value, high);
20,976✔
2605
   j_jump(g, JIT_CC_T, l_pass);
20,976✔
2606

2607
   j_send(g, 0, value);
20,976✔
2608
   j_send(g, 1, left);
20,976✔
2609
   j_send(g, 2, right);
20,976✔
2610
   j_send(g, 3, dir);
20,976✔
2611
   j_send(g, 4, locus);
20,976✔
2612
   j_send(g, 5, hint);
20,976✔
2613
   macro_exit(g, JIT_EXIT_INDEX_FAIL);
20,976✔
2614

2615
   irgen_bind_label(g, l_pass);
20,976✔
2616
}
20,976✔
2617

2618
static void irgen_op_range_check(jit_irgen_t *g, mir_value_t n)
5,681✔
2619
{
2620
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
5,681✔
2621
   mir_value_t arg3 = mir_get_arg(g->mu, n, 3);
5,681✔
2622

2623
   jit_value_t value = irgen_get_value(g, arg0);
5,681✔
2624
   jit_value_t left  = irgen_get_arg(g, n, 1);
5,681✔
2625
   jit_value_t right = irgen_get_arg(g, n, 2);
5,681✔
2626
   jit_value_t dir   = irgen_get_value(g, arg3);
5,681✔
2627
   jit_value_t locus = irgen_get_arg(g, n, 4);
5,681✔
2628
   jit_value_t hint  = irgen_get_arg(g, n, 5);
5,681✔
2629

2630
   if (!mir_equals(arg3, g->flags))
5,681✔
2631
      j_cmp(g, JIT_CC_EQ, dir, jit_value_from_int64(RANGE_DOWNTO));
5,497✔
2632

2633
   jit_value_t low = j_csel(g, right, left);
5,681✔
2634
   jit_value_t high = j_csel(g, left, right);
5,681✔
2635

2636
   irgen_label_t *l_fail = irgen_alloc_label(g);
5,681✔
2637
   irgen_label_t *l_pass = irgen_alloc_label(g);
5,681✔
2638

2639
   if (mir_is(g->mu, arg0, MIR_TYPE_REAL)) {
5,681✔
2640
      j_fcmp(g, JIT_CC_GE, value, low);
1,187✔
2641
      j_fccmp(g, JIT_CC_LE, value, high);
1,187✔
2642
      j_jump(g, JIT_CC_T, l_pass);
1,187✔
2643
   }
2644
   else {
2645
      j_cmp(g, JIT_CC_GE, value, low);
4,494✔
2646
      j_ccmp(g, JIT_CC_LE, value, high);
4,494✔
2647
      j_jump(g, JIT_CC_T, l_pass);
4,494✔
2648
   }
2649

2650
   irgen_bind_label(g, l_fail);
5,681✔
2651
   j_send(g, 0, value);
5,681✔
2652
   j_send(g, 1, left);
5,681✔
2653
   j_send(g, 2, right);
5,681✔
2654
   j_send(g, 3, dir);
5,681✔
2655
   j_send(g, 4, locus);
5,681✔
2656
   j_send(g, 5, hint);
5,681✔
2657
   macro_exit(g, JIT_EXIT_RANGE_FAIL);
5,681✔
2658

2659
   irgen_bind_label(g, l_pass);
5,681✔
2660
}
5,681✔
2661

2662
static void irgen_op_null_check(jit_irgen_t *g, mir_value_t n)
2,892✔
2663
{
2664
   jit_value_t ptr = irgen_get_arg(g, n, 0);
2,892✔
2665
   jit_value_t locus = irgen_get_arg(g, n, 1);
2,892✔
2666

2667
   irgen_label_t *l_pass = irgen_alloc_label(g);
2,892✔
2668

2669
   j_cmp(g, JIT_CC_NE, ptr, jit_value_from_int64(0));
2,892✔
2670
   j_jump(g, JIT_CC_T, l_pass);
2,892✔
2671

2672
   j_send(g, 0, locus);
2,892✔
2673
   macro_exit(g, JIT_EXIT_NULL_DEREF);
2,892✔
2674

2675
   irgen_bind_label(g, l_pass);
2,892✔
2676
}
2,892✔
2677

2678
static void irgen_op_zero_check(jit_irgen_t *g, mir_value_t n)
116✔
2679
{
2680
   jit_value_t value = irgen_get_arg(g, n, 0);
116✔
2681
   jit_value_t locus = irgen_get_arg(g, n, 1);
116✔
2682

2683
   irgen_label_t *l_pass = irgen_alloc_label(g);
116✔
2684

2685
   j_cmp(g, JIT_CC_NE, value, jit_value_from_int64(0));
116✔
2686
   j_jump(g, JIT_CC_T, l_pass);
116✔
2687

2688
   j_send(g, 0, locus);
116✔
2689
   macro_exit(g, JIT_EXIT_DIV_ZERO);
116✔
2690

2691
   irgen_bind_label(g, l_pass);
116✔
2692
}
116✔
2693

2694
static void irgen_op_exponent_check(jit_irgen_t *g, mir_value_t n)
659✔
2695
{
2696
   jit_value_t value = irgen_get_arg(g, n, 0);
659✔
2697
   jit_value_t locus = irgen_get_arg(g, n, 1);
659✔
2698

2699
   irgen_label_t *l_pass = irgen_alloc_label(g);
659✔
2700

2701
   j_cmp(g, JIT_CC_GE, value, jit_value_from_int64(0));
659✔
2702
   j_jump(g, JIT_CC_T, l_pass);
659✔
2703

2704
   j_send(g, 0, value);
659✔
2705
   j_send(g, 1, locus);
659✔
2706
   macro_exit(g, JIT_EXIT_EXPONENT_FAIL);
659✔
2707

2708
   irgen_bind_label(g, l_pass);
659✔
2709
}
659✔
2710

2711
static void irgen_op_length_check(jit_irgen_t *g, mir_value_t n)
9,518✔
2712
{
2713
   jit_value_t llen  = irgen_get_arg(g, n, 0);
9,518✔
2714
   jit_value_t rlen  = irgen_get_arg(g, n, 1);
9,518✔
2715
   jit_value_t locus = irgen_get_arg(g, n, 2);
9,518✔
2716

2717
   // TODO: why isn't this encoded with an enum?
2718
   jit_value_t dim;
9,518✔
2719
   if (mir_count_args(g->mu, n) > 3)
9,518✔
2720
      dim = irgen_get_arg(g, n, 3);
36✔
2721
   else
2722
      dim = jit_value_from_int64(0);
9,482✔
2723

2724
   irgen_label_t *l_pass = irgen_alloc_label(g);
9,518✔
2725

2726
   j_cmp(g, JIT_CC_EQ, llen, rlen);
9,518✔
2727
   j_jump(g, JIT_CC_T, l_pass);
9,518✔
2728

2729
   j_send(g, 0, llen);
9,518✔
2730
   j_send(g, 1, rlen);
9,518✔
2731
   j_send(g, 2, dim);
9,518✔
2732
   j_send(g, 3, locus);
9,518✔
2733
   macro_exit(g, JIT_EXIT_LENGTH_FAIL);
9,518✔
2734

2735
   irgen_bind_label(g, l_pass);
9,518✔
2736
}
9,518✔
2737

2738
static void irgen_op_package_init(jit_irgen_t *g, mir_value_t n)
33,723✔
2739
{
2740
   if (mir_count_args(g->mu, n) > 1)
33,723✔
2741
      j_send(g, 0, irgen_get_arg(g, n, 1));
242✔
2742
   else
2743
      j_send(g, 0, jit_value_from_int64(0));
33,481✔
2744

2745
   j_call(g, irgen_get_handle(g, n, 0));
33,723✔
2746

2747
   g->map[n.id] = j_recv(g, 0);
33,723✔
2748
}
33,723✔
2749

2750
static void irgen_op_link_package(jit_irgen_t *g, mir_value_t n)
14,273✔
2751
{
2752
   jit_handle_t handle = irgen_get_handle(g, n, 0);
14,273✔
2753

2754
   g->map[n.id] = macro_getpriv(g, handle);
14,273✔
2755
}
14,273✔
2756

2757
static void irgen_op_link_var(jit_irgen_t *g, mir_value_t n)
5,765✔
2758
{
2759
   jit_handle_t handle = irgen_get_handle(g, n, 0);
5,765✔
2760
   jit_value_t context = irgen_get_arg(g, n, 1);
5,765✔
2761
   ident_t var_name = mir_get_name(g->mu, mir_get_arg(g->mu, n, 2));
5,765✔
2762

2763
   jit_func_t *f = jit_get_func(g->func->jit, handle);
5,765✔
2764
   jit_fill_irbuf(f);
5,765✔
2765

2766
   link_tab_t *tab = f->linktab;
5,765✔
2767
   for (; tab < f->linktab + f->nvars; tab++) {
57,715✔
2768
      if (tab->name == var_name)
57,715✔
2769
         break;
2770
   }
2771

2772
   if (tab == f->linktab + f->nvars) {
5,765✔
UNCOV
2773
      mir_dump(g->mu);
×
2774
      fatal_trace("variable %s not found in unit %s", istr(var_name),
2775
                  istr(f->name));
2776
   }
2777

2778
   g->map[n.id] = jit_addr_from_value(context, tab->offset);
5,765✔
2779
}
5,765✔
2780

2781
static void irgen_op_new(jit_irgen_t *g, mir_value_t n)
841✔
2782
{
2783
   mir_type_t elem = mir_get_elem(g->mu, mir_get_type(g->mu, n));
841✔
2784

2785
   int headersz = 0;
841✔
2786
   if (mir_get_class(g->mu, elem) == MIR_TYPE_UARRAY) {
841✔
2787
      headersz = irgen_size_bytes(g, elem);
603✔
2788
      elem = mir_get_elem(g->mu, elem);
603✔
2789
   }
2790

2791
   jit_value_t bytes = jit_value_from_int64(irgen_size_bytes(g, elem));
841✔
2792

2793
   irgen_emit_debuginfo(g, n);   // For out-of-memory stack traces
841✔
2794

2795
   if (mir_count_args(g->mu, n) > 0)
841✔
2796
      bytes = j_mul(g, bytes, irgen_get_arg(g, n, 0));
727✔
2797

2798
   if (headersz > 0)
841✔
2799
      bytes = j_add(g, bytes, jit_value_from_int64(headersz));
603✔
2800

2801
   jit_value_t mem = macro_galloc(g, bytes);
841✔
2802
   g->map[n.id] = mem;
841✔
2803

2804
   if (headersz > 0) {
841✔
2805
      // Initialise the header to point at the body
2806
      jit_value_t ptr = jit_addr_from_value(mem, 0);
603✔
2807
      jit_value_t body = j_add(g, mem, jit_value_from_int64(headersz));
603✔
2808
      j_store(g, JIT_SZ_PTR, body, ptr);
603✔
2809
   }
2810
}
841✔
2811

2812
static void irgen_op_alloc(jit_irgen_t *g, mir_value_t n)
9,431✔
2813
{
2814
   mir_type_t type = mir_get_pointer(g->mu, mir_get_type(g->mu, n));
9,431✔
2815

2816
   const int bytes = irgen_size_bytes(g, type);
9,431✔
2817

2818
   jit_value_t count = irgen_get_arg(g, n, 0);
9,431✔
2819
   jit_value_t total = j_mul(g, count, jit_value_from_int64(bytes));
9,431✔
2820

2821
   g->map[n.id] = macro_lalloc(g, total);
9,431✔
2822
   g->used_tlab = true;
9,431✔
2823
}
9,431✔
2824

2825
static void irgen_op_all(jit_irgen_t *g, mir_value_t n)
3,733✔
2826
{
2827
   jit_value_t arg = irgen_get_arg(g, n, 0);
3,733✔
2828
   g->map[n.id] = jit_addr_from_value(arg, 0);
3,733✔
2829
}
3,733✔
2830

2831
static void irgen_op_closure(jit_irgen_t *g, mir_value_t n)
6,517✔
2832
{
2833
   jit_handle_t handle = irgen_get_handle(g, n, 0);
6,517✔
2834

2835
   jit_reg_t base = irgen_alloc_reg(g);
6,517✔
2836
   j_mov(g, base, jit_value_from_handle(handle));
6,517✔
2837

2838
   jit_reg_t context = irgen_alloc_reg(g);
6,517✔
2839
   j_mov(g, context, irgen_get_arg(g, n, 1));
6,517✔
2840

2841
   g->map[n.id] = jit_value_from_reg(base);
6,517✔
2842
}
6,517✔
2843

2844
static void irgen_op_resolution_wrapper(jit_irgen_t *g, mir_value_t n)
6,010✔
2845
{
2846
   jit_value_t closure = irgen_get_arg(g, n, 0);
6,010✔
2847

2848
   jit_reg_t base = irgen_alloc_reg(g);
6,010✔
2849
   j_mov(g, base, closure);
6,010✔
2850

2851
   jit_reg_t context = irgen_alloc_reg(g);
6,010✔
2852
   j_mov(g, context, jit_value_from_reg(jit_value_as_reg(closure) + 1));
6,010✔
2853

2854
   jit_reg_t nlits = irgen_alloc_reg(g);
6,010✔
2855
   j_mov(g, nlits, irgen_get_arg(g, n, 1));
6,010✔
2856

2857
   mir_type_t type = mir_get_base(g->mu, mir_get_type(g->mu, n));
6,010✔
2858

2859
   uint32_t flagbits = 0;
6,010✔
2860
   if (mir_get_class(g->mu, type) == MIR_TYPE_POINTER)
6,010✔
2861
      flagbits |= R_COMPOSITE;
200✔
2862

2863
   jit_reg_t flags = irgen_alloc_reg(g);
6,010✔
2864
   j_mov(g, flags, jit_value_from_int64(flagbits));
6,010✔
2865

2866
   g->map[n.id] = jit_value_from_reg(base);
6,010✔
2867
}
6,010✔
2868

2869
static void irgen_op_init_signal(jit_irgen_t *g, mir_value_t n)
21,791✔
2870
{
2871
   jit_value_t count = irgen_get_arg(g, n, 0);
21,791✔
2872
   jit_value_t size  = irgen_get_arg(g, n, 1);
21,791✔
2873
   jit_value_t value = irgen_get_arg(g, n, 2);
21,791✔
2874
   jit_value_t flags = irgen_get_arg(g, n, 3);
21,791✔
2875
   jit_value_t locus = irgen_get_arg(g, n, 4);
21,791✔
2876

2877
   jit_value_t offset;
21,791✔
2878
   if (mir_count_args(g->mu, n) > 5)
21,791✔
2879
      offset = irgen_get_arg(g, n, 5);
7,519✔
2880
   else
2881
      offset = jit_value_from_int64(0);
14,272✔
2882

2883
   jit_value_t scalar = irgen_is_scalar(g, n, 2);
21,791✔
2884

2885
   j_send(g, 0, count);
21,791✔
2886
   j_send(g, 1, size);
21,791✔
2887
   j_send(g, 2, value);
21,791✔
2888
   j_send(g, 3, flags);
21,791✔
2889
   j_send(g, 4, locus);
21,791✔
2890
   j_send(g, 5, offset);
21,791✔
2891
   j_send(g, 6, scalar);
21,791✔
2892

2893
   macro_exit(g, JIT_EXIT_INIT_SIGNAL);
21,791✔
2894

2895
   g->map[n.id] = j_recv(g, 0);
21,791✔
2896

2897
   // Offset into signal must be next sequential register
2898
   jit_reg_t next = irgen_alloc_reg(g);
21,791✔
2899
   j_mov(g, next, jit_value_from_int64(0));
21,791✔
2900
}
21,791✔
2901

2902
static void irgen_op_implicit_signal(jit_irgen_t *g, mir_value_t n)
108✔
2903
{
2904
   jit_value_t count   = irgen_get_arg(g, n, 0);
108✔
2905
   jit_value_t size    = irgen_get_arg(g, n, 1);
108✔
2906
   jit_value_t locus   = irgen_get_arg(g, n, 2);
108✔
2907
   jit_value_t kind    = irgen_get_arg(g, n, 3);
108✔
2908
   jit_value_t closure = irgen_get_arg(g, n, 4);
108✔
2909
   jit_value_t context = jit_value_from_reg(jit_value_as_reg(closure) + 1);
108✔
2910
   jit_value_t delay   = irgen_get_arg(g, n, 5);
108✔
2911

2912
   j_send(g, 0, count);
108✔
2913
   j_send(g, 1, size);
108✔
2914
   j_send(g, 2, locus);
108✔
2915
   j_send(g, 3, kind);
108✔
2916
   j_send(g, 4, closure);
108✔
2917
   j_send(g, 5, context);
108✔
2918
   j_send(g, 6, delay);
108✔
2919

2920
   macro_exit(g, JIT_EXIT_IMPLICIT_SIGNAL);
108✔
2921

2922
   g->map[n.id] = j_recv(g, 0);
108✔
2923

2924
   // Offset into signal must be next sequential register
2925
   jit_reg_t next = irgen_alloc_reg(g);
108✔
2926
   j_mov(g, next, jit_value_from_int64(0));
108✔
2927
}
108✔
2928

2929
static void irgen_op_alias_signal(jit_irgen_t *g, mir_value_t n)
5,604✔
2930
{
2931
   jit_value_t shared = irgen_get_arg(g, n, 0);
5,604✔
2932
   jit_value_t locus  = irgen_get_arg(g, n, 1);
5,604✔
2933

2934
   j_send(g, 0, shared);
5,604✔
2935
   j_send(g, 1, locus);
5,604✔
2936

2937
   macro_exit(g, JIT_EXIT_ALIAS_SIGNAL);
5,604✔
2938
}
5,604✔
2939

2940
static void irgen_op_map_signal(jit_irgen_t *g, mir_value_t n)
7,125✔
2941
{
2942
   jit_value_t src_ss  = irgen_get_arg(g, n, 0);
7,125✔
2943
   jit_value_t src_off = jit_value_from_reg(jit_value_as_reg(src_ss) + 1);
7,125✔
2944
   jit_value_t dst_ss  = irgen_get_arg(g, n, 1);
7,125✔
2945
   jit_value_t dst_off = jit_value_from_reg(jit_value_as_reg(dst_ss) + 1);
7,125✔
2946
   jit_value_t count   = irgen_get_arg(g, n, 2);
7,125✔
2947

2948
   j_send(g, 0, src_ss);
7,125✔
2949
   j_send(g, 1, src_off);
7,125✔
2950
   j_send(g, 2, dst_ss);
7,125✔
2951
   j_send(g, 3, dst_off);
7,125✔
2952
   j_send(g, 4, count);
7,125✔
2953

2954
   macro_exit(g, JIT_EXIT_MAP_SIGNAL);
7,125✔
2955
}
7,125✔
2956

2957
static void irgen_op_map_const(jit_irgen_t *g, mir_value_t n)
252✔
2958
{
2959
   jit_value_t initval   = irgen_get_arg(g, n, 0);
252✔
2960
   jit_value_t dst_ss    = irgen_get_arg(g, n, 1);
252✔
2961
   jit_value_t dst_off   = jit_value_from_reg(jit_value_as_reg(dst_ss) + 1);
252✔
2962
   jit_value_t dst_count = irgen_get_arg(g, n, 2);
252✔
2963

2964
   jit_value_t scalar = irgen_is_scalar(g, n, 0);
252✔
2965

2966
   j_send(g, 0, dst_ss);
252✔
2967
   j_send(g, 1, dst_off);
252✔
2968
   j_send(g, 2, initval);
252✔
2969
   j_send(g, 3, dst_count);
252✔
2970
   j_send(g, 4, scalar);
252✔
2971

2972
   macro_exit(g, JIT_EXIT_MAP_CONST);
252✔
2973
}
252✔
2974

2975
static void irgen_op_map_implicit(jit_irgen_t *g, mir_value_t n)
84✔
2976
{
2977
   jit_value_t src_ss  = irgen_get_arg(g, n, 0);
84✔
2978
   jit_value_t src_off = jit_value_from_reg(jit_value_as_reg(src_ss) + 1);
84✔
2979
   jit_value_t dst_ss  = irgen_get_arg(g, n, 1);
84✔
2980
   jit_value_t dst_off = jit_value_from_reg(jit_value_as_reg(dst_ss) + 1);
84✔
2981
   jit_value_t count   = irgen_get_arg(g, n, 2);
84✔
2982

2983
   j_send(g, 0, src_ss);
84✔
2984
   j_send(g, 1, src_off);
84✔
2985
   j_send(g, 2, dst_ss);
84✔
2986
   j_send(g, 3, dst_off);
84✔
2987
   j_send(g, 4, count);
84✔
2988

2989
   macro_exit(g, JIT_EXIT_MAP_IMPLICIT);
84✔
2990
}
84✔
2991

2992
static void irgen_op_resolve_signal(jit_irgen_t *g, mir_value_t n)
4,695✔
2993
{
2994
   jit_value_t shared  = irgen_get_arg(g, n, 0);
4,695✔
2995
   jit_value_t resfn   = irgen_get_arg(g, n, 1);
4,695✔
2996

2997
   j_send(g, 0, shared);
4,695✔
2998
   j_send(g, 1, resfn);
4,695✔
2999

3000
   macro_exit(g, JIT_EXIT_RESOLVE_SIGNAL);
4,695✔
3001
}
4,695✔
3002

3003
static void irgen_op_unreachable(jit_irgen_t *g, mir_value_t n)
1,719✔
3004
{
3005
   jit_value_t locus;
1,719✔
3006
   if (mir_count_args(g->mu, n) > 0)
1,719✔
3007
      locus = irgen_get_arg(g, n, 0);
125✔
3008
   else
3009
      locus = jit_value_from_int64(0);
1,594✔
3010

3011
   j_send(g, 0, locus);
1,719✔
3012
   macro_exit(g, JIT_EXIT_UNREACHABLE);
1,719✔
3013
}
1,719✔
3014

3015
static void irgen_op_report(jit_irgen_t *g, mir_value_t n)
2,740✔
3016
{
3017
   jit_value_t severity = irgen_get_arg(g, n, 0);
2,740✔
3018
   jit_value_t msg      = irgen_get_arg(g, n, 1);
2,740✔
3019
   jit_value_t length   = irgen_get_arg(g, n, 2);
2,740✔
3020
   jit_value_t locus    = irgen_get_arg(g, n, 3);
2,740✔
3021

3022
   j_send(g, 0, msg);
2,740✔
3023
   j_send(g, 1, length);
2,740✔
3024
   j_send(g, 2, severity);
2,740✔
3025
   j_send(g, 3, locus);
2,740✔
3026
   macro_exit(g, JIT_EXIT_REPORT);
2,740✔
3027
}
2,740✔
3028

3029
static void irgen_op_assert(jit_irgen_t *g, mir_value_t n)
18,623✔
3030
{
3031
   jit_value_t severity = irgen_get_arg(g, n, 1);
18,623✔
3032
   jit_value_t locus    = irgen_get_arg(g, n, 4);
18,623✔
3033

3034
   // TODO: having null arguments sucks - why not have optional args?
3035
   jit_value_t msg    = jit_value_from_int64(0);
18,623✔
3036
   jit_value_t length = jit_value_from_int64(0);
18,623✔
3037
   if (!mir_is_null(mir_get_arg(g->mu, n, 2))) {
18,623✔
3038
      msg    = irgen_get_arg(g, n, 2);
4,560✔
3039
      length = irgen_get_arg(g, n, 3);
4,560✔
3040
   }
3041

3042
   jit_value_t hint_left, hint_right, hint_valid;
18,623✔
3043
   if (mir_count_args(g->mu, n) > 5) {
18,623✔
3044
      hint_left  = irgen_get_arg(g, n, 5);
7,857✔
3045
      hint_right = irgen_get_arg(g, n, 6);
7,857✔
3046
      hint_valid = jit_value_from_int64(true);
7,857✔
3047
   }
3048
   else {
3049
      hint_left = hint_right = jit_value_from_int64(0);
10,766✔
3050
      hint_valid = jit_value_from_int64(false);
10,766✔
3051
   }
3052

3053
   irgen_label_t *l_pass = irgen_alloc_label(g);
18,623✔
3054

3055
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
18,623✔
3056
   if (!mir_equals(arg0, g->flags)) {
18,623✔
3057
      jit_value_t test = irgen_get_value(g, arg0);
9,994✔
3058
      j_cmp(g, JIT_CC_NE, test, jit_value_from_int64(0));
9,994✔
3059
   }
3060

3061
   j_jump(g, JIT_CC_T, l_pass);
18,623✔
3062

3063
   j_send(g, 0, msg);
18,623✔
3064
   j_send(g, 1, length);
18,623✔
3065
   j_send(g, 2, severity);
18,623✔
3066
   j_send(g, 3, hint_left);
18,623✔
3067
   j_send(g, 4, hint_right);
18,623✔
3068
   j_send(g, 5, hint_valid);
18,623✔
3069
   j_send(g, 6, locus);
18,623✔
3070
   macro_exit(g, JIT_EXIT_ASSERT_FAIL);
18,623✔
3071

3072
   irgen_bind_label(g, l_pass);
18,623✔
3073
}
18,623✔
3074

3075
static void irgen_op_file_open(jit_irgen_t *g, mir_value_t n)
1,555✔
3076
{
3077
   jit_value_t file   = irgen_get_arg(g, n, 0);
1,555✔
3078
   jit_value_t name   = irgen_get_arg(g, n, 1);
1,555✔
3079
   jit_value_t length = irgen_get_arg(g, n, 2);
1,555✔
3080
   jit_value_t kind   = irgen_get_arg(g, n, 3);
1,555✔
3081

3082
   irgen_emit_debuginfo(g, n);   // For stack traces
1,555✔
3083

3084
   jit_value_t status = jit_null_ptr();
1,555✔
3085
   if (mir_count_args(g->mu, n) == 5)
1,555✔
3086
      status = irgen_get_arg(g, n, 4);
33✔
3087

3088
   j_send(g, 0, status);
1,555✔
3089
   j_send(g, 1, file);
1,555✔
3090
   j_send(g, 2, name);
1,555✔
3091
   j_send(g, 3, length);
1,555✔
3092
   j_send(g, 4, kind);
1,555✔
3093

3094
   macro_exit(g, JIT_EXIT_FILE_OPEN);
1,555✔
3095
}
1,555✔
3096

3097
static void irgen_op_file_read(jit_irgen_t *g, mir_value_t n)
120✔
3098
{
3099
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
120✔
3100
   mir_value_t arg1 = mir_get_arg(g->mu, n, 1);
120✔
3101

3102
   jit_value_t file = irgen_get_value(g, arg0);
120✔
3103
   jit_value_t ptr  = irgen_get_value(g, arg1);
120✔
3104

3105
   jit_value_t count = jit_value_from_int64(1);
120✔
3106
   if (mir_count_args(g->mu, n) >= 3)
120✔
3107
      count = irgen_get_arg(g, n, 2);
56✔
3108

3109
   mir_type_t file_type = mir_get_elem(g->mu, mir_get_type(g->mu, arg0));
120✔
3110
   assert(mir_get_class(g->mu, file_type) == MIR_TYPE_FILE);
120✔
3111

3112
   mir_type_t elem_type = mir_get_base(g->mu, file_type);
120✔
3113
   switch (mir_get_class(g->mu, elem_type)) {
120✔
3114
   case MIR_TYPE_UARRAY:
56✔
3115
   case MIR_TYPE_CARRAY:
3116
      elem_type = mir_get_elem(g->mu, elem_type);
56✔
3117
      break;
56✔
3118
   default:
3119
      break;
3120
   }
3121

3122
   jit_value_t size = jit_value_from_int64(irgen_size_bytes(g, elem_type));
120✔
3123

3124
   j_send(g, 0, file);
120✔
3125
   j_send(g, 1, ptr);
120✔
3126
   j_send(g, 2, size);
120✔
3127
   j_send(g, 3, count);
120✔
3128

3129
   macro_exit(g, JIT_EXIT_FILE_READ);
120✔
3130

3131
   if (mir_count_args(g->mu, n) >= 4) {
120✔
3132
      mir_value_t arg3 = mir_get_arg(g->mu, n, 3);
44✔
3133
      mir_type_t out_type = mir_get_elem(g->mu, mir_get_type(g->mu, arg3));
44✔
3134
      jit_size_t out_size = irgen_jit_size(g, out_type);
44✔
3135

3136
      jit_value_t outarg = irgen_get_value(g, arg3);
44✔
3137
      jit_value_t outptr = jit_addr_from_value(outarg, 0);
44✔
3138
      jit_value_t len = j_recv(g, 0);
44✔
3139
      j_store(g, out_size, len, outptr);
44✔
3140
   }
3141
}
120✔
3142

3143
static void irgen_op_file_write(jit_irgen_t *g, mir_value_t n)
338✔
3144
{
3145
   mir_value_t arg0 = mir_get_arg(g->mu, n, 0);
338✔
3146
   mir_value_t arg1 = mir_get_arg(g->mu, n, 1);
338✔
3147

3148
   jit_value_t file = irgen_get_value(g, arg0);
338✔
3149
   jit_value_t data = irgen_get_value(g, arg1);
338✔
3150

3151
   jit_value_t count;
338✔
3152
   if (mir_count_args(g->mu, n) > 2)
338✔
3153
      count = irgen_get_arg(g, n, 2);
262✔
3154
   else
3155
      count = jit_value_from_int64(1);
76✔
3156

3157
   mir_type_t file_type = mir_get_elem(g->mu, mir_get_type(g->mu, arg0));
338✔
3158
   assert(mir_get_class(g->mu, file_type) == MIR_TYPE_FILE);
338✔
3159

3160
   mir_type_t elem_type = mir_get_base(g->mu, file_type);
338✔
3161
   switch (mir_get_class(g->mu, elem_type)) {
338✔
3162
   case MIR_TYPE_UARRAY:
262✔
3163
   case MIR_TYPE_CARRAY:
3164
      elem_type = mir_get_elem(g->mu, elem_type);
262✔
3165
      break;
262✔
3166
   default:
3167
      break;
3168
   }
3169

3170
   jit_value_t bytes = jit_value_from_int64(irgen_size_bytes(g, elem_type));
338✔
3171
   jit_value_t scalar = jit_value_from_int64(mir_is_numeric(g->mu, arg1));
338✔
3172

3173
   j_send(g, 0, file);
338✔
3174
   j_send(g, 1, data);
338✔
3175
   j_send(g, 2, bytes);
338✔
3176
   j_send(g, 3, count);
338✔
3177
   j_send(g, 4, scalar);
338✔
3178

3179
   macro_exit(g, JIT_EXIT_FILE_WRITE);
338✔
3180
}
338✔
3181

3182
static void irgen_op_package_scope(jit_irgen_t *g, mir_value_t n)
59✔
3183
{
3184
   jit_value_t locus = irgen_get_arg(g, n, 0);
59✔
3185
   j_send(g, 0, locus);
59✔
3186
   j_send(g, 2, jit_value_from_int64(0));
59✔
3187
   j_send(g, 2, jit_value_from_int64(SCOPE_PACKAGE));
59✔
3188

3189
   macro_exit(g, JIT_EXIT_PUSH_SCOPE);
59✔
3190
}
59✔
3191

3192
static void irgen_op_array_scope(jit_irgen_t *g, mir_value_t n)
839✔
3193
{
3194
   jit_value_t locus = irgen_get_arg(g, n, 0);
839✔
3195
   j_send(g, 0, locus);
839✔
3196

3197
   const int size = irgen_size_bytes(g, mir_get_type(g->mu, n));
839✔
3198
   j_send(g, 1, jit_value_from_int64(size));
839✔
3199
   j_send(g, 2, jit_value_from_int64(SCOPE_ARRAY));
839✔
3200

3201
   macro_exit(g, JIT_EXIT_PUSH_SCOPE);
839✔
3202
}
839✔
3203

3204
static void irgen_op_record_scope(jit_irgen_t *g, mir_value_t n)
2,168✔
3205
{
3206
   jit_value_t locus = irgen_get_arg(g, n, 0);
2,168✔
3207
   j_send(g, 0, locus);
2,168✔
3208

3209
   const int size = irgen_size_bytes(g, mir_get_type(g->mu, n));
2,168✔
3210
   j_send(g, 1, jit_value_from_int64(size));
2,168✔
3211
   j_send(g, 2, jit_value_from_int64(SCOPE_RECORD));
2,168✔
3212

3213
   macro_exit(g, JIT_EXIT_PUSH_SCOPE);
2,168✔
3214
}
2,168✔
3215

3216
static void irgen_op_pop_scope(jit_irgen_t *g, mir_value_t n)
3,066✔
3217
{
3218
   macro_exit(g, JIT_EXIT_POP_SCOPE);
3,066✔
3219
}
3,066✔
3220

3221
static void irgen_op_drive_signal(jit_irgen_t *g, mir_value_t n)
12,428✔
3222
{
3223
   jit_value_t shared = irgen_get_arg(g, n, 0);
12,428✔
3224
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
12,428✔
3225
   jit_value_t count  = irgen_get_arg(g, n, 1);
12,428✔
3226

3227
   j_send(g, 0, shared);
12,428✔
3228
   j_send(g, 1, offset);
12,428✔
3229
   j_send(g, 2, count);
12,428✔
3230
   macro_exit(g, JIT_EXIT_DRIVE_SIGNAL);
12,428✔
3231
}
12,428✔
3232

3233
static void irgen_op_transfer_signal(jit_irgen_t *g, mir_value_t n)
1,554✔
3234
{
3235
   jit_value_t target  = irgen_get_arg(g, n, 0);
1,554✔
3236
   jit_value_t toffset = jit_value_from_reg(jit_value_as_reg(target) + 1);
1,554✔
3237
   jit_value_t source  = irgen_get_arg(g, n, 1);
1,554✔
3238
   jit_value_t soffset = jit_value_from_reg(jit_value_as_reg(source) + 1);
1,554✔
3239
   jit_value_t count   = irgen_get_arg(g, n, 2);
1,554✔
3240
   jit_value_t reject  = irgen_get_arg(g, n, 3);
1,554✔
3241
   jit_value_t after   = irgen_get_arg(g, n, 4);
1,554✔
3242

3243
   j_send(g, 0, target);
1,554✔
3244
   j_send(g, 1, toffset);
1,554✔
3245
   j_send(g, 2, source);
1,554✔
3246
   j_send(g, 3, soffset);
1,554✔
3247
   j_send(g, 4, count);
1,554✔
3248
   j_send(g, 5, after);
1,554✔
3249
   j_send(g, 6, reject);
1,554✔
3250

3251
   macro_exit(g, JIT_EXIT_TRANSFER_SIGNAL);
1,554✔
3252
}
1,554✔
3253

3254
static void irgen_op_resolved(jit_irgen_t *g, mir_value_t n)
19,353✔
3255
{
3256
   jit_value_t shared = irgen_get_arg(g, n, 0);
19,353✔
3257
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
19,353✔
3258

3259
   jit_value_t data_ptr = irgen_lea(g, jit_addr_from_value(shared, 8));
19,353✔
3260

3261
   mir_type_t type = mir_get_pointer(g->mu, mir_get_type(g->mu, n));
19,353✔
3262

3263
   const int scale = irgen_size_bytes(g, type);
19,353✔
3264
   jit_value_t scaled = j_mul(g, offset, jit_value_from_int64(scale));
19,353✔
3265

3266
   g->map[n.id] = j_add(g, data_ptr, scaled);
19,353✔
3267
}
19,353✔
3268

3269
static void irgen_op_last_value(jit_irgen_t *g, mir_value_t n)
275✔
3270
{
3271
   jit_value_t shared = irgen_get_arg(g, n, 0);
275✔
3272
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
275✔
3273

3274
   jit_value_t data_ptr = irgen_lea(g, jit_addr_from_value(shared, 8));
275✔
3275
   jit_value_t size = j_load(g, JIT_SZ_32, jit_addr_from_value(shared, 0));
275✔
3276

3277
   jit_value_t last_value = j_add(g, data_ptr, size);
275✔
3278

3279
   mir_type_t type = mir_get_elem(g->mu, mir_get_type(g->mu, n));
275✔
3280

3281
   const int scale = irgen_size_bytes(g, type);
275✔
3282
   jit_value_t scaled = j_mul(g, offset, jit_value_from_int64(scale));
275✔
3283

3284
   g->map[n.id] = j_add(g, last_value, scaled);
275✔
3285
}
275✔
3286

3287
static void irgen_op_sched_waveform(jit_irgen_t *g, mir_value_t n)
14,305✔
3288
{
3289
   jit_value_t shared = irgen_get_arg(g, n, 0);
14,305✔
3290
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
14,305✔
3291
   jit_value_t count  = irgen_get_arg(g, n, 1);
14,305✔
3292
   jit_value_t value  = irgen_get_arg(g, n, 2);
14,305✔
3293
   jit_value_t reject = irgen_get_arg(g, n, 3);
14,305✔
3294
   jit_value_t after  = irgen_get_arg(g, n, 4);
14,305✔
3295

3296
   jit_value_t scalar = irgen_is_scalar(g, n, 2);
14,305✔
3297

3298
   j_send(g, 0, shared);
14,305✔
3299
   j_send(g, 1, offset);
14,305✔
3300
   j_send(g, 2, count);
14,305✔
3301
   j_send(g, 3, value);
14,305✔
3302
   j_send(g, 4, after);
14,305✔
3303
   j_send(g, 5, reject);
14,305✔
3304
   j_send(g, 6, scalar);
14,305✔
3305

3306
   macro_exit(g, JIT_EXIT_SCHED_WAVEFORM);
14,305✔
3307
}
14,305✔
3308

3309
static void irgen_op_disconnect(jit_irgen_t *g, mir_value_t n)
32✔
3310
{
3311
   jit_value_t shared = irgen_get_arg(g, n, 0);
32✔
3312
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
32✔
3313
   jit_value_t count  = irgen_get_arg(g, n, 1);
32✔
3314
   jit_value_t reject = irgen_get_arg(g, n, 2);
32✔
3315
   jit_value_t after  = irgen_get_arg(g, n, 3);
32✔
3316

3317
   j_send(g, 0, shared);
32✔
3318
   j_send(g, 1, offset);
32✔
3319
   j_send(g, 2, count);
32✔
3320
   j_send(g, 3, reject);
32✔
3321
   j_send(g, 4, after);
32✔
3322

3323
   macro_exit(g, JIT_EXIT_DISCONNECT);
32✔
3324
}
32✔
3325

3326
static void irgen_op_force(jit_irgen_t *g, mir_value_t n)
84✔
3327
{
3328
   jit_value_t shared = irgen_get_arg(g, n, 0);
84✔
3329
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
84✔
3330
   jit_value_t count  = irgen_get_arg(g, n, 1);
84✔
3331
   jit_value_t value  = irgen_get_arg(g, n, 2);
84✔
3332

3333
   jit_value_t scalar = irgen_is_scalar(g, n, 2);
84✔
3334

3335
   j_send(g, 0, shared);
84✔
3336
   j_send(g, 1, offset);
84✔
3337
   j_send(g, 2, count);
84✔
3338
   j_send(g, 3, value);
84✔
3339
   j_send(g, 4, scalar);
84✔
3340

3341
   macro_exit(g, JIT_EXIT_FORCE);
84✔
3342
}
84✔
3343

3344
static void irgen_op_release(jit_irgen_t *g, mir_value_t n)
40✔
3345
{
3346
   jit_value_t shared = irgen_get_arg(g, n, 0);
40✔
3347
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
40✔
3348
   jit_value_t count  = irgen_get_arg(g, n, 1);
40✔
3349

3350
   j_send(g, 0, shared);
40✔
3351
   j_send(g, 1, offset);
40✔
3352
   j_send(g, 2, count);
40✔
3353

3354
   macro_exit(g, JIT_EXIT_RELEASE);
40✔
3355
}
40✔
3356

3357
static void irgen_op_deposit_signal(jit_irgen_t *g, mir_value_t n)
368✔
3358
{
3359
   jit_value_t shared = irgen_get_arg(g, n, 0);
368✔
3360
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
368✔
3361
   jit_value_t count  = irgen_get_arg(g, n, 1);
368✔
3362
   jit_value_t value  = irgen_get_arg(g, n, 2);
368✔
3363

3364
   jit_value_t scalar = irgen_is_scalar(g, n, 2);
368✔
3365

3366
   j_send(g, 0, shared);
368✔
3367
   j_send(g, 1, offset);
368✔
3368
   j_send(g, 2, count);
368✔
3369
   j_send(g, 3, value);
368✔
3370
   j_send(g, 4, scalar);
368✔
3371

3372
   macro_exit(g, JIT_EXIT_DEPOSIT_SIGNAL);
368✔
3373
}
368✔
3374

3375
static void irgen_op_put_conversion(jit_irgen_t *g, mir_value_t n)
556✔
3376
{
3377
   jit_value_t cf     = irgen_get_arg(g, n, 0);
556✔
3378
   jit_value_t shared = irgen_get_arg(g, n, 1);
556✔
3379
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
556✔
3380
   jit_value_t count  = irgen_get_arg(g, n, 2);
556✔
3381
   jit_value_t value  = irgen_get_arg(g, n, 3);
556✔
3382

3383
   jit_value_t scalar = irgen_is_scalar(g, n, 3);
556✔
3384

3385
   j_send(g, 0, cf);
556✔
3386
   j_send(g, 1, shared);
556✔
3387
   j_send(g, 2, offset);
556✔
3388
   j_send(g, 3, count);
556✔
3389
   j_send(g, 4, value);
556✔
3390
   j_send(g, 5, scalar);
556✔
3391

3392
   macro_exit(g, JIT_EXIT_PUT_CONVERSION);
556✔
3393
}
556✔
3394

3395
static void irgen_op_sched_event(jit_irgen_t *g, mir_value_t n)
7,989✔
3396
{
3397
   jit_value_t shared = irgen_get_arg(g, n, 0);
7,989✔
3398
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
7,989✔
3399
   jit_value_t count  = irgen_get_arg(g, n, 1);
7,989✔
3400

3401
   j_send(g, 0, shared);
7,989✔
3402
   j_send(g, 1, offset);
7,989✔
3403
   j_send(g, 2, count);
7,989✔
3404
   macro_exit(g, JIT_EXIT_SCHED_EVENT);
7,989✔
3405
}
7,989✔
3406

3407
static void irgen_op_clear_event(jit_irgen_t *g, mir_value_t n)
694✔
3408
{
3409
   jit_value_t shared = irgen_get_arg(g, n, 0);
694✔
3410
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
694✔
3411
   jit_value_t count  = irgen_get_arg(g, n, 1);
694✔
3412

3413
   j_send(g, 0, shared);
694✔
3414
   j_send(g, 1, offset);
694✔
3415
   j_send(g, 2, count);
694✔
3416
   macro_exit(g, JIT_EXIT_CLEAR_EVENT);
694✔
3417
}
694✔
3418

3419
static void irgen_op_event(jit_irgen_t *g, mir_value_t n)
745✔
3420
{
3421
   jit_value_t shared = irgen_get_arg(g, n, 0);
745✔
3422
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
745✔
3423
   jit_value_t count  = irgen_get_arg(g, n, 1);
745✔
3424

3425
   jit_value_t flags = j_load(g, JIT_SZ_32, jit_addr_from_value(shared, 4));
745✔
3426

3427
   jit_value_t cachebit = jit_value_from_int64(SIG_F_CACHE_EVENT);
745✔
3428
   jit_value_t cacheflag = j_and(g, flags, cachebit);
745✔
3429

3430
   irgen_label_t *l_slow = irgen_alloc_label(g);
745✔
3431
   irgen_label_t *l_cont = irgen_alloc_label(g);
745✔
3432

3433
   j_cmp(g, JIT_CC_EQ, cacheflag, jit_value_from_int64(0));
745✔
3434
   j_jump(g, JIT_CC_T, l_slow);
745✔
3435

3436
   jit_value_t eventbit = jit_value_from_int64(SIG_F_EVENT_FLAG);
745✔
3437
   jit_value_t eventflag = j_and(g, flags, eventbit);
745✔
3438

3439
   jit_value_t shift = jit_value_from_int64(ilog2(SIG_F_EVENT_FLAG));
745✔
3440
   jit_value_t result = j_asr(g, eventflag, shift);
745✔
3441
   g->map[n.id] = result;
745✔
3442

3443
   j_jump(g, JIT_CC_NONE, l_cont);
745✔
3444

3445
   irgen_bind_label(g, l_slow);
745✔
3446

3447
   j_send(g, 0, shared);
745✔
3448
   j_send(g, 1, offset);
745✔
3449
   j_send(g, 2, count);
745✔
3450
   macro_exit(g, JIT_EXIT_TEST_EVENT);
745✔
3451

3452
   jit_value_t retval = j_recv(g, 0);
745✔
3453
   j_mov(g, jit_value_as_reg(result), retval);
745✔
3454

3455
   irgen_bind_label(g, l_cont);
745✔
3456
}
745✔
3457

3458
static void irgen_op_active(jit_irgen_t *g, mir_value_t n)
292✔
3459
{
3460
   jit_value_t shared = irgen_get_arg(g, n, 0);
292✔
3461
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
292✔
3462
   jit_value_t count  = irgen_get_arg(g, n, 1);
292✔
3463

3464
   j_send(g, 0, shared);
292✔
3465
   j_send(g, 1, offset);
292✔
3466
   j_send(g, 2, count);
292✔
3467
   macro_exit(g, JIT_EXIT_TEST_ACTIVE);
292✔
3468

3469
   g->map[n.id] = j_recv(g, 0);
292✔
3470
}
292✔
3471

UNCOV
3472
static void irgen_op_debug_out(jit_irgen_t *g, mir_value_t n)
×
3473
{
UNCOV
3474
   jit_value_t value = irgen_get_arg(g, n, 0);
×
3475

UNCOV
3476
   j_send(g, 0, value);
×
3477
   macro_exit(g, JIT_EXIT_DEBUG_OUT);
×
UNCOV
3478
}
×
3479

3480
static void irgen_op_last_event(jit_irgen_t *g, mir_value_t n)
44✔
3481
{
3482
   jit_value_t shared = irgen_get_arg(g, n, 0);
44✔
3483
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
44✔
3484

3485
   jit_value_t count;
44✔
3486
   if (mir_count_args(g->mu, n) > 1)
44✔
3487
      count = irgen_get_arg(g, n, 1);
12✔
3488
   else
3489
      count = jit_value_from_int64(1);
32✔
3490

3491
   j_send(g, 0, shared);
44✔
3492
   j_send(g, 1, offset);
44✔
3493
   j_send(g, 2, count);
44✔
3494
   macro_exit(g, JIT_EXIT_LAST_EVENT);
44✔
3495

3496
   g->map[n.id] = j_recv(g, 0);
44✔
3497
}
44✔
3498

3499
static void irgen_op_last_active(jit_irgen_t *g, mir_value_t n)
48✔
3500
{
3501
   jit_value_t shared = irgen_get_arg(g, n, 0);
48✔
3502
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
48✔
3503

3504
   jit_value_t count;
48✔
3505
   if (mir_count_args(g->mu, n) > 1)
48✔
3506
      count = irgen_get_arg(g, n, 1);
8✔
3507
   else
3508
      count = jit_value_from_int64(1);
40✔
3509

3510
   j_send(g, 0, shared);
48✔
3511
   j_send(g, 1, offset);
48✔
3512
   j_send(g, 2, count);
48✔
3513
   macro_exit(g, JIT_EXIT_LAST_ACTIVE);
48✔
3514

3515
   g->map[n.id] = j_recv(g, 0);
48✔
3516
}
48✔
3517

3518
static void irgen_op_driving(jit_irgen_t *g, mir_value_t n)
48✔
3519
{
3520
   jit_value_t shared = irgen_get_arg(g, n, 0);
48✔
3521
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
48✔
3522
   jit_value_t count  = irgen_get_arg(g, n, 1);
48✔
3523

3524
   j_send(g, 0, shared);
48✔
3525
   j_send(g, 1, offset);
48✔
3526
   j_send(g, 2, count);
48✔
3527

3528
   macro_exit(g, JIT_EXIT_DRIVING);
48✔
3529

3530
   g->map[n.id] = j_recv(g, 0);
48✔
3531
}
48✔
3532

3533
static void irgen_op_driving_value(jit_irgen_t *g, mir_value_t n)
152✔
3534
{
3535
   jit_value_t shared = irgen_get_arg(g, n, 0);
152✔
3536
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
152✔
3537

3538
   jit_value_t count;
152✔
3539
   if (mir_count_args(g->mu, n) > 1)
152✔
3540
      count = irgen_get_arg(g, n, 1);
40✔
3541
   else
3542
      count = jit_value_from_int64(1);
112✔
3543

3544
   j_send(g, 0, shared);
152✔
3545
   j_send(g, 1, offset);
152✔
3546
   j_send(g, 2, count);
152✔
3547

3548
   macro_exit(g, JIT_EXIT_DRIVING_VALUE);
152✔
3549

3550
   g->map[n.id] = j_recv(g, 0);
152✔
3551
}
152✔
3552

3553
static void irgen_op_cover_increment(jit_irgen_t *g, mir_value_t n)
3,109✔
3554
{
3555
   uint32_t tag = irgen_get_const(g, n, 0);
3,109✔
3556
   jit_value_t mem = jit_addr_from_cover_tag(tag);
3,109✔
3557

3558
   macro_sadd(g, JIT_SZ_32, mem, jit_value_from_int64(1));
3,109✔
3559
}
3,109✔
3560

3561
static void irgen_op_cover_toggle(jit_irgen_t *g, mir_value_t n)
518✔
3562
{
3563
   jit_value_t shared = irgen_get_arg(g, n, 0);
518✔
3564
   uint32_t tag = irgen_get_const(g, n, 1);
518✔
3565

3566
   j_send(g, 0, shared);
518✔
3567
   j_send(g, 1, jit_value_from_int64(tag));
518✔
3568
   macro_exit(g, JIT_EXIT_COVER_TOGGLE);
518✔
3569
}
518✔
3570

3571
static void irgen_op_cover_state(jit_irgen_t *g, mir_value_t n)
16✔
3572
{
3573
   jit_value_t shared = irgen_get_arg(g, n, 0);
16✔
3574
   jit_value_t low = irgen_get_arg(g, n, 1);
16✔
3575
   uint32_t tag = irgen_get_const(g, n, 2);
16✔
3576

3577
   j_send(g, 0, shared);
16✔
3578
   j_send(g, 1, low);
16✔
3579
   j_send(g, 2, jit_value_from_int64(tag));
16✔
3580
   macro_exit(g, JIT_EXIT_COVER_STATE);
16✔
3581
}
16✔
3582

3583
static void irgen_op_enter_state(jit_irgen_t *g, mir_value_t n)
1,040✔
3584
{
3585
   jit_value_t state = irgen_get_arg(g, n, 0);
1,040✔
3586

3587
   jit_value_t strong;
1,040✔
3588
   if (mir_count_args(g->mu, n) > 1)
1,040✔
3589
      strong = irgen_get_arg(g, n, 1);
24✔
3590
   else
3591
      strong = jit_value_from_int64(0);
1,016✔
3592

3593
   j_send(g, 0, state);
1,040✔
3594
   j_send(g, 1, strong);
1,040✔
3595
   macro_exit(g, JIT_EXIT_ENTER_STATE);
1,040✔
3596
}
1,040✔
3597

3598
static void irgen_op_function_trigger(jit_irgen_t *g, mir_value_t n)
286✔
3599
{
3600
   jit_handle_t handle = irgen_get_handle(g, n, 0);
286✔
3601

3602
   const int nargs = mir_count_args(g->mu, n);
286✔
3603

3604
   int nslots = 0;
286✔
3605
   for (int i = 1; i < nargs; i++) {
754✔
3606
      mir_type_t type = mir_get_type(g->mu, mir_get_arg(g->mu, n, i));
468✔
3607
      nslots += irgen_slots_for_type(g, type);
468✔
3608
   }
3609

3610
   j_send(g, 0, jit_value_from_handle(handle));
286✔
3611
   j_send(g, 1, jit_value_from_int64(nslots));
286✔
3612
   irgen_send_args(g, n, 2);
286✔
3613

3614
   macro_exit(g, JIT_EXIT_FUNCTION_TRIGGER);
286✔
3615

3616
   g->map[n.id] = j_recv(g, 0);
286✔
3617
}
286✔
3618

3619
static void irgen_op_or_trigger(jit_irgen_t *g, mir_value_t n)
44✔
3620
{
3621
   jit_value_t left = irgen_get_arg(g, n, 0);
44✔
3622
   jit_value_t right = irgen_get_arg(g, n, 1);
44✔
3623

3624
   j_send(g, 0, left);
44✔
3625
   j_send(g, 1, right);
44✔
3626

3627
   macro_exit(g, JIT_EXIT_OR_TRIGGER);
44✔
3628

3629
   g->map[n.id] = j_recv(g, 0);
44✔
3630
}
44✔
3631

3632
static void irgen_op_cmp_trigger(jit_irgen_t *g, mir_value_t n)
60✔
3633
{
3634
   jit_value_t shared = irgen_get_arg(g, n, 0);
60✔
3635
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
60✔
3636
   jit_value_t right = irgen_get_arg(g, n, 1);
60✔
3637

3638
   j_send(g, 0, shared);
60✔
3639
   j_send(g, 1, offset);
60✔
3640
   j_send(g, 2, right);
60✔
3641

3642
   macro_exit(g, JIT_EXIT_CMP_TRIGGER);
60✔
3643

3644
   g->map[n.id] = j_recv(g, 0);
60✔
3645
}
60✔
3646

3647
static void irgen_op_add_trigger(jit_irgen_t *g, mir_value_t n)
498✔
3648
{
3649
   jit_value_t trigger = irgen_get_arg(g, n, 0);
498✔
3650

3651
   j_send(g, 0, trigger);
498✔
3652
   macro_exit(g, JIT_EXIT_ADD_TRIGGER);
498✔
3653
}
498✔
3654

3655
static void irgen_op_port_conversion(jit_irgen_t *g, mir_value_t n)
375✔
3656
{
3657
   jit_value_t closure1 = irgen_get_arg(g, n, 0);
375✔
3658
   jit_value_t context1 = jit_value_from_reg(jit_value_as_reg(closure1) + 1);
375✔
3659

3660
   jit_value_t closure2, context2;
375✔
3661
   if (mir_count_args(g->mu, n) > 1) {
375✔
3662
      closure2 = irgen_get_arg(g, n, 1);
24✔
3663
      context2 = jit_value_from_reg(jit_value_as_reg(closure2) + 1);
24✔
3664
   }
3665
   else {
3666
      closure2 = jit_value_from_handle(JIT_HANDLE_INVALID);
351✔
3667
      context2 = jit_value_from_int64(0);
351✔
3668
   }
3669

3670
   j_send(g, 0, closure1);
375✔
3671
   j_send(g, 1, context1);
375✔
3672
   j_send(g, 2, closure2);
375✔
3673
   j_send(g, 3, context2);
375✔
3674
   macro_exit(g, JIT_EXIT_PORT_CONVERSION);
375✔
3675

3676
   g->map[n.id] = j_recv(g, 0);
375✔
3677
}
375✔
3678

3679
static void irgen_op_convert_in(jit_irgen_t *g, mir_value_t n)
479✔
3680
{
3681
   jit_value_t conv   = irgen_get_arg(g, n, 0);
479✔
3682
   jit_value_t shared = irgen_get_arg(g, n, 1);
479✔
3683
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
479✔
3684
   jit_value_t count  = irgen_get_arg(g, n, 2);
479✔
3685

3686
   j_send(g, 0, conv);
479✔
3687
   j_send(g, 1, shared);
479✔
3688
   j_send(g, 2, offset);
479✔
3689
   j_send(g, 3, count);
479✔
3690
   macro_exit(g, JIT_EXIT_CONVERT_IN);
479✔
3691
}
479✔
3692

3693
static void irgen_op_convert_out(jit_irgen_t *g, mir_value_t n)
535✔
3694
{
3695
   jit_value_t conv   = irgen_get_arg(g, n, 0);
535✔
3696
   jit_value_t shared = irgen_get_arg(g, n, 1);
535✔
3697
   jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1);
535✔
3698
   jit_value_t count  = irgen_get_arg(g, n, 2);
535✔
3699

3700
   j_send(g, 0, conv);
535✔
3701
   j_send(g, 1, shared);
535✔
3702
   j_send(g, 2, offset);
535✔
3703
   j_send(g, 3, count);
535✔
3704
   macro_exit(g, JIT_EXIT_CONVERT_OUT);
535✔
3705
}
535✔
3706

3707
static void irgen_op_bind_foreign(jit_irgen_t *g, mir_value_t n)
1,306✔
3708
{
3709
   jit_value_t spec   = irgen_get_arg(g, n, 0);
1,306✔
3710
   jit_value_t length = irgen_get_arg(g, n, 1);
1,306✔
3711

3712
   jit_value_t locus;
1,306✔
3713
   if (mir_count_args(g->mu, n) > 2)
1,306✔
3714
      locus = irgen_get_arg(g, n, 2);
1,074✔
3715
   else
3716
      locus = jit_value_from_int64(0);
232✔
3717

3718
   j_send(g, 0, spec);
1,306✔
3719
   j_send(g, 1, length);
1,306✔
3720
   j_send(g, 2, locus);
1,306✔
3721
   macro_exit(g, JIT_EXIT_BIND_FOREIGN);
1,306✔
3722

3723
   int pslot = 0;
1,306✔
3724
   if (mir_is_null(mir_get_result(g->mu)))
1,306✔
3725
      j_send(g, pslot++, jit_value_from_int64(0));    // Procedure state
400✔
3726

3727
   const int nparams = mir_count_params(g->mu);
1,306✔
3728
   for (int i = 0; i < nparams; i++) {
3,818✔
3729
      mir_value_t p = mir_get_param(g->mu, i);
2,512✔
3730
      const int slots = irgen_slots_for_type(g, mir_get_type(g->mu, p));
2,512✔
3731
      if (unlikely(pslot + slots >= JIT_MAX_ARGS))
2,512✔
UNCOV
3732
         fatal("foreign subprogram %s requires more than the maximum supported "
×
UNCOV
3733
               "%d arguments", istr(mir_get_name(g->mu, MIR_NULL_VALUE)),
×
3734
               JIT_MAX_ARGS);
3735

3736
      jit_value_t r = irgen_get_value(g, p);
2,512✔
3737
      j_send(g, pslot++, r);
2,512✔
3738
      for (int j = 1; j < slots; j++)
2,778✔
3739
         j_send(g, pslot++, jit_value_from_reg(jit_value_as_reg(r) + j));
266✔
3740
   }
3741

3742
   macro_reexec(g);
1,306✔
3743
}
1,306✔
3744

3745
static void irgen_op_instance_name(jit_irgen_t *g, mir_value_t n)
1,018✔
3746
{
3747
   irgen_send_args(g, n, 0);
1,018✔
3748

3749
   macro_exit(g, JIT_EXIT_INSTANCE_NAME);
1,018✔
3750

3751
   const int slots = irgen_slots_for_type(g, mir_get_type(g->mu, n));
1,018✔
3752
   g->map[n.id] = j_recv(g, 0);
1,018✔
3753
   for (int i = 1; i < slots; i++)
3,054✔
3754
      j_recv(g, i);
2,036✔
3755
}
1,018✔
3756

3757
static void irgen_op_bind_external(jit_irgen_t *g, mir_value_t n)
257✔
3758
{
3759
   jit_value_t locus = irgen_get_arg(g, n, 0);
257✔
3760
   jit_handle_t handle = irgen_get_handle(g, n, 1);
257✔
3761

3762
   j_send(g, 0, locus);
257✔
3763
   j_send(g, 1, jit_value_from_handle(handle));
257✔
3764
   macro_exit(g, JIT_EXIT_BIND_EXTERNAL);
257✔
3765

3766
   g->map[n.id] = j_recv(g, 0);
257✔
3767
}
257✔
3768

3769
static void irgen_op_pack(jit_irgen_t *g, mir_value_t n)
712✔
3770
{
3771
   assert(mir_is(g->mu, n, MIR_TYPE_VEC4));  // TODO
712✔
3772

3773
   mir_value_t arg = mir_get_arg(g->mu, n, 0);
712✔
3774
   jit_value_t unpacked = irgen_get_value(g, arg);
712✔
3775

3776
   if (mir_is(g->mu, arg, MIR_TYPE_POINTER)) {
712✔
3777
      const int size = mir_get_size(g->mu, mir_get_type(g->mu, n));
244✔
3778
      macro_pack(g, unpacked, jit_value_from_int64(size));
244✔
3779

3780
      g->map[n.id] = j_recv(g, 0);
244✔
3781
      j_recv(g, 1);  // B-bits
244✔
3782
   }
3783
   else {
3784
      jit_value_t one = jit_value_from_int64(1);
468✔
3785
      jit_value_t shifted = j_asr(g, unpacked, one);
468✔
3786
      jit_value_t abits = j_and(g, unpacked, one);
468✔
3787
      jit_value_t bbits = j_and(g, shifted, one);
468✔
3788
      assert(jit_value_as_reg(bbits) == jit_value_as_reg(abits) + 1);
468✔
3789

3790
      g->map[n.id] = abits;
468✔
3791
      (void)bbits;
712✔
3792
   }
3793
}
712✔
3794

3795
static void irgen_op_unpack(jit_irgen_t *g, mir_value_t n)
628✔
3796
{
3797
   mir_value_t arg = mir_get_arg(g->mu, n, 0);
628✔
3798
   assert(mir_is(g->mu, arg, MIR_TYPE_VEC4));
628✔
3799

3800
   jit_value_t strength = jit_value_from_int64(irgen_get_enum(g, n, 1));
628✔
3801

3802
   jit_value_t abits = irgen_get_value(g, arg);
628✔
3803
   jit_value_t bbits = jit_value_from_reg(jit_value_as_reg(abits) + 1);
628✔
3804

3805
   if (mir_is_scalar(g->mu, n)) {
628✔
3806
      jit_value_t bshift = j_shl(g, bbits, jit_value_from_int64(1));
404✔
3807
      jit_value_t bits = j_or(g, abits, bshift);
404✔
3808

3809
      g->map[n.id] = j_or(g, bits, strength);
404✔
3810
   }
3811
   else {
3812
      const int size = mir_get_size(g->mu, mir_get_type(g->mu, arg));
224✔
3813
      jit_value_t dest = irgen_get_arg(g, n, 2);
224✔
3814
      j_send(g, 0, dest);
224✔
3815
      j_send(g, 1, jit_value_from_int64(size));
224✔
3816
      j_send(g, 2, strength);
224✔
3817
      macro_unpack(g, abits, bbits);
224✔
3818
   }
3819
}
628✔
3820

3821
static jit_cc_t irgen_vector_cmp(mir_vec_op_t op)
52✔
3822
{
3823
   switch (op) {
52✔
3824
   case MIR_VEC_LT:      return JIT_CC_LT;
3825
   case MIR_VEC_LEQ:     return JIT_CC_LE;
3826
   case MIR_VEC_GT:      return JIT_CC_GT;
3827
   case MIR_VEC_GEQ:     return JIT_CC_GE;
3828
   case MIR_VEC_LOG_EQ:  return JIT_CC_EQ;
3829
   case MIR_VEC_LOG_NEQ: return JIT_CC_NE;
3830
   default: should_not_reach_here();
3831
   }
3832
}
3833

3834
static void irgen_op_binary(jit_irgen_t *g, mir_value_t n)
528✔
3835
{
3836
   mir_value_t left = mir_get_arg(g->mu, n, 1);
528✔
3837
   mir_value_t right = mir_get_arg(g->mu, n, 2);
528✔
3838

3839
   jit_value_t aleft = irgen_get_value(g, left);
528✔
3840
   jit_value_t aright = irgen_get_value(g, right);
528✔
3841

3842
   jit_value_t bleft, bright;
528✔
3843
   if (mir_is(g->mu, left, MIR_TYPE_VEC4)) {
528✔
3844
      bleft = jit_value_from_reg(jit_value_as_reg(aleft) + 1);
528✔
3845
      bright = jit_value_from_reg(jit_value_as_reg(aright) + 1);
528✔
3846
   }
3847
   else
UNCOV
3848
      assert(false);  // TODO
×
3849

3850
   mir_type_t type = mir_get_type(g->mu, n);
528✔
3851
   const int size = mir_get_size(g->mu, type);
528✔
3852
   assert(size <= 64);  // TODO
528✔
3853
   (void)size;
528✔
3854

3855
   bool logical = false;
528✔
3856
   jit_value_t abits;
528✔
3857
   const mir_vec_op_t op = irgen_get_enum(g, n, 0);
528✔
3858
   switch (op) {
528✔
3859
   case MIR_VEC_LOG_AND:
16✔
3860
      logical = true;
16✔
3861
   case MIR_VEC_BIT_AND:
48✔
3862
      abits = j_and(g, aleft, aright);
48✔
3863
      break;
48✔
3864
   case MIR_VEC_LOG_OR:
28✔
3865
      logical = true;
28✔
3866
   case MIR_VEC_BIT_OR:
92✔
3867
      abits = j_or(g, aleft, aright);
92✔
3868
      break;
92✔
3869
   case MIR_VEC_BIT_XOR:
4✔
3870
      abits = j_xor(g, aleft, aright);
4✔
3871
      break;
4✔
3872
   case MIR_VEC_ADD:
28✔
3873
      abits = j_add(g, aleft, aright);
28✔
3874
      break;
28✔
3875
   case MIR_VEC_SUB:
4✔
3876
      abits = j_sub(g, aleft, aright);
4✔
3877
      break;
4✔
3878
   case MIR_VEC_CASE_EQ:
68✔
3879
      j_cmp(g, JIT_CC_EQ, aleft, aright);
68✔
3880
      j_ccmp(g, JIT_CC_EQ, bleft, bright);
68✔
3881
      abits = j_cset(g);
68✔
3882
      break;
68✔
3883
   case MIR_VEC_CASE_NEQ:
180✔
3884
      j_cmp(g, JIT_CC_EQ, aleft, aright);
180✔
3885
      j_ccmp(g, JIT_CC_EQ, bleft, bright);
180✔
3886
      abits = j_not(g, j_cset(g));
180✔
3887
      break;
180✔
3888
   case MIR_VEC_LT:
52✔
3889
   case MIR_VEC_LEQ:
3890
   case MIR_VEC_GT:
3891
   case MIR_VEC_GEQ:
3892
   case MIR_VEC_LOG_EQ:
3893
   case MIR_VEC_LOG_NEQ:
3894
      j_cmp(g, irgen_vector_cmp(op), aleft, aright);
52✔
3895
      abits = j_cset(g);
52✔
3896
      break;
52✔
3897
   case MIR_VEC_SLL:
52✔
3898
      abits = j_shl(g, aleft, aright);
52✔
3899
      break;
52✔
UNCOV
3900
   default:
×
3901
      should_not_reach_here();
3902
   }
3903

3904
   if (logical) {
528✔
3905
      j_cmp(g, JIT_CC_NE, abits, jit_value_from_int64(0));
44✔
3906
      abits = j_cset(g);
44✔
3907
   }
3908

3909
   jit_reg_t bbits = irgen_alloc_reg(g);
528✔
3910
   assert(abits.kind == JIT_VALUE_REG);
528✔
3911
   assert(bbits == abits.reg + 1);
528✔
3912

3913
   j_mov(g, bbits, jit_value_from_int64(0));
528✔
3914
   g->map[n.id] = abits;
528✔
3915
}
528✔
3916

3917
static void irgen_op_unary(jit_irgen_t *g, mir_value_t n)
56✔
3918
{
3919
   jit_value_t arg = irgen_get_arg(g, n, 1);
56✔
3920

3921
   mir_type_t type = mir_get_type(g->mu, n);
56✔
3922
   const int size = mir_get_size(g->mu, type);
56✔
3923
   assert(size <= 64);  // TODO
56✔
3924

3925
   jit_value_t abits;
56✔
3926
   switch (irgen_get_enum(g, n, 0)) {
56✔
3927
   case MIR_VEC_BIT_NOT:
32✔
3928
      {
3929
         uint64_t mask = ~UINT64_C(0);
32✔
3930
         if (size < 64) mask >>= 64 - size;
32✔
3931
         abits = j_xor(g, arg, jit_value_from_int64(mask));
32✔
3932
      }
3933
      break;
32✔
3934
   case MIR_VEC_LOG_NOT:
20✔
3935
      abits = j_not(g, arg);
20✔
3936
      break;
20✔
3937
   case MIR_VEC_SUB:
4✔
3938
      abits = j_neg(g, arg);
4✔
3939
      break;
4✔
UNCOV
3940
   default:
×
3941
      should_not_reach_here();
3942
   }
3943

3944
   jit_reg_t bbits = irgen_alloc_reg(g);
56✔
3945
   assert(abits.kind == JIT_VALUE_REG);
56✔
3946
   assert(bbits == abits.reg + 1);
56✔
3947

3948
   j_mov(g, bbits, jit_value_from_int64(0));
56✔
3949
   g->map[n.id] = abits;
56✔
3950
}
56✔
3951

3952
static void irgen_block(jit_irgen_t *g, mir_block_t block)
204,671✔
3953
{
3954
   irgen_bind_label(g, g->blocks[block.id]);
204,671✔
3955

3956
   g->flags = MIR_NULL_VALUE;
204,671✔
3957
   g->curblock = block;
204,671✔
3958

3959
   const int nops = mir_count_nodes(g->mu, block);
204,671✔
3960
   for (int i = 0; i < nops; i++) {
1,886,408✔
3961
      mir_value_t n = mir_get_node(g->mu, block, i);
1,681,737✔
3962

3963
      const mir_op_t op = mir_get_op(g->mu, n);
1,681,737✔
3964
      if (op == MIR_OP_COMMENT)
1,681,737✔
3965
         continue;
314✔
3966

3967
#ifdef DEBUG
3968
      mir_set_cursor(g->mu, block, i);
1,681,423✔
3969
      irgen_emit_debuginfo(g, n);
1,681,423✔
3970
#endif
3971

3972
      switch (op) {
1,681,423✔
3973
      case MIR_OP_CONST:
10,051✔
3974
         irgen_op_const(g, n);
10,051✔
3975
         break;
10,051✔
3976
      case MIR_OP_CONST_REAL:
29,794✔
3977
         irgen_op_const_real(g, n);
29,794✔
3978
         break;
29,794✔
3979
      case MIR_OP_CONST_VEC:
2,240✔
3980
         irgen_op_const_vec(g, n);
2,240✔
3981
         break;
2,240✔
3982
      case MIR_OP_CONST_ARRAY:
41,596✔
3983
         irgen_op_const_array(g, n);
41,596✔
3984
         break;
41,596✔
3985
      case MIR_OP_CONST_REP:
347✔
3986
         irgen_op_const_rep(g, n);
347✔
3987
         break;
347✔
3988
      case MIR_OP_CONST_RECORD:
2,592✔
3989
         irgen_op_const_record(g, n);
2,592✔
3990
         break;
2,592✔
3991
      case MIR_OP_ADDRESS_OF:
43,197✔
3992
         irgen_op_address_of(g, n);
43,197✔
3993
         break;
43,197✔
3994
      case MIR_OP_LOCUS:
102,021✔
3995
         irgen_op_locus(g, n);
102,021✔
3996
         break;
102,021✔
3997
      case MIR_OP_TRAP_ADD:
5,294✔
3998
         irgen_op_trap_add(g, n);
5,294✔
3999
         break;
5,294✔
4000
      case MIR_OP_NOT:
3,545✔
4001
         irgen_op_not(g, n);
3,545✔
4002
         break;
3,545✔
4003
      case MIR_OP_AND:
6,005✔
4004
         irgen_op_and(g, n);
6,005✔
4005
         break;
6,005✔
4006
      case MIR_OP_OR:
2,766✔
4007
         irgen_op_or(g, n);
2,766✔
4008
         break;
2,766✔
4009
      case MIR_OP_XOR:
149✔
4010
         irgen_op_xor(g, n);
149✔
4011
         break;
149✔
4012
      case MIR_OP_ADD:
19,312✔
4013
         irgen_op_add(g, n);
19,312✔
4014
         break;
19,312✔
4015
      case MIR_OP_TRAP_MUL:
488✔
4016
         irgen_op_trap_mul(g, n);
488✔
4017
         break;
488✔
4018
      case MIR_OP_MUL:
3,932✔
4019
         irgen_op_mul(g, n);
3,932✔
4020
         break;
3,932✔
4021
      case MIR_OP_DIV:
2,022✔
4022
         irgen_op_div(g, n);
2,022✔
4023
         break;
2,022✔
4024
      case MIR_OP_EXP:
175✔
4025
         irgen_op_exp(g, n);
175✔
4026
         break;
175✔
4027
      case MIR_OP_TRAP_EXP:
683✔
4028
         irgen_op_trap_exp(g, n);
683✔
4029
         break;
683✔
4030
      case MIR_OP_SUB:
37,824✔
4031
         irgen_op_sub(g, n);
37,824✔
4032
         break;
37,824✔
4033
      case MIR_OP_TRAP_SUB:
1,717✔
4034
         irgen_op_trap_sub(g, n);
1,717✔
4035
         break;
1,717✔
4036
      case MIR_OP_NEG:
9,187✔
4037
         irgen_op_neg(g, n);
9,187✔
4038
         break;
9,187✔
4039
      case MIR_OP_TRAP_NEG:
343✔
4040
         irgen_op_trap_neg(g, n);
343✔
4041
         break;
343✔
4042
      case MIR_OP_ABS:
986✔
4043
         irgen_op_abs(g, n);
986✔
4044
         break;
986✔
4045
      case MIR_OP_MOD:
188✔
4046
         irgen_op_mod(g, n);
188✔
4047
         break;
188✔
4048
      case MIR_OP_REM:
881✔
4049
         irgen_op_rem(g, n);
881✔
4050
         break;
881✔
4051
      case MIR_OP_CMP:
50,892✔
4052
         irgen_op_cmp(g, n);
50,892✔
4053
         break;
50,892✔
4054
      case MIR_OP_RETURN:
85,155✔
4055
         irgen_op_return(g, n);
85,155✔
4056
         break;
85,155✔
4057
      case MIR_OP_STORE:
121,145✔
4058
         irgen_op_store(g, n);
121,145✔
4059
         break;
121,145✔
4060
      case MIR_OP_LOAD:
174,892✔
4061
         irgen_op_load(g, n);
174,892✔
4062
         break;
174,892✔
4063
      case MIR_OP_WRAP:
42,882✔
4064
         irgen_op_wrap(g, n);
42,882✔
4065
         break;
42,882✔
4066
      case MIR_OP_UARRAY_LEFT:
22,146✔
4067
         irgen_op_uarray_left(g, n);
22,146✔
4068
         break;
22,146✔
4069
      case MIR_OP_UARRAY_RIGHT:
18,279✔
4070
         irgen_op_uarray_right(g, n);
18,279✔
4071
         break;
18,279✔
4072
      case MIR_OP_UARRAY_DIR:
22,059✔
4073
         irgen_op_uarray_dir(g, n);
22,059✔
4074
         break;
22,059✔
4075
      case MIR_OP_UARRAY_LEN:
28,600✔
4076
         irgen_op_uarray_len(g, n);
28,600✔
4077
         break;
28,600✔
4078
      case MIR_OP_UNWRAP:
34,641✔
4079
         irgen_op_unwrap(g, n);
34,641✔
4080
         break;
34,641✔
4081
      case MIR_OP_CAST:
73,899✔
4082
         irgen_op_cast(g, n);
73,899✔
4083
         break;
73,899✔
4084
      case MIR_OP_RANGE_NULL:
4,326✔
4085
         irgen_op_range_null(g, n);
4,326✔
4086
         break;
4,326✔
4087
      case MIR_OP_RANGE_LENGTH:
9,001✔
4088
         irgen_op_range_length(g, n);
9,001✔
4089
         break;
9,001✔
4090
      case MIR_OP_COND:
46,425✔
4091
         irgen_op_cond(g, n);
46,425✔
4092
         break;
46,425✔
4093
      case MIR_OP_SELECT:
18,038✔
4094
         irgen_op_select(g, n);
18,038✔
4095
         break;
18,038✔
4096
      case MIR_OP_JUMP:
50,852✔
4097
         irgen_op_jump(g, n);
50,852✔
4098
         break;
50,852✔
4099
      case MIR_OP_ARRAY_REF:
49,069✔
4100
         irgen_op_array_ref(g, n);
49,069✔
4101
         break;
49,069✔
4102
      case MIR_OP_CONTEXT_UPREF:
15,822✔
4103
         irgen_op_context_upref(g, n);
15,822✔
4104
         break;
15,822✔
4105
      case MIR_OP_FCALL:
45,815✔
4106
         irgen_op_fcall(g, n);
45,815✔
4107
         break;
45,815✔
4108
      case MIR_OP_PCALL:
1,084✔
4109
         irgen_op_pcall(g, n);
1,084✔
4110
         break;
1,084✔
4111
      case MIR_OP_RESUME:
1,084✔
4112
         irgen_op_resume(g, n);
1,084✔
4113
         break;
1,084✔
4114
      case MIR_OP_SYSCALL:
756✔
4115
         irgen_op_syscall(g, n);
756✔
4116
         break;
756✔
4117
      case MIR_OP_WAIT:
18,475✔
4118
         irgen_op_wait(g, n);
18,475✔
4119
         break;
18,475✔
4120
      case MIR_OP_COPY:
30,603✔
4121
         irgen_op_copy(g, n);
30,603✔
4122
         break;
30,603✔
4123
      case MIR_OP_SET:
7,541✔
4124
         irgen_op_set(g, n);
7,541✔
4125
         break;
7,541✔
4126
      case MIR_OP_VAR_UPREF:
63,061✔
4127
         irgen_op_var_upref(g, n);
63,061✔
4128
         break;
63,061✔
4129
      case MIR_OP_INDEX_CHECK:
20,976✔
4130
         irgen_op_index_check(g, n);
20,976✔
4131
         break;
20,976✔
4132
      case MIR_OP_RANGE_CHECK:
5,681✔
4133
         irgen_op_range_check(g, n);
5,681✔
4134
         break;
5,681✔
4135
      case MIR_OP_PACKAGE_INIT:
33,723✔
4136
         irgen_op_package_init(g, n);
33,723✔
4137
         break;
33,723✔
4138
      case MIR_OP_LINK_PACKAGE:
14,273✔
4139
         irgen_op_link_package(g, n);
14,273✔
4140
         break;
14,273✔
4141
      case MIR_OP_LINK_VAR:
5,765✔
4142
         irgen_op_link_var(g, n);
5,765✔
4143
         break;
5,765✔
4144
      case MIR_OP_RECORD_REF:
48,397✔
4145
         irgen_op_record_ref(g, n);
48,397✔
4146
         break;
48,397✔
4147
      case MIR_OP_NULL:
5,700✔
4148
         irgen_op_null(g, n);
5,700✔
4149
         break;
5,700✔
4150
      case MIR_OP_NEW:
841✔
4151
         irgen_op_new(g, n);
841✔
4152
         break;
841✔
4153
      case MIR_OP_ALLOC:
9,431✔
4154
         irgen_op_alloc(g, n);
9,431✔
4155
         break;
9,431✔
4156
      case MIR_OP_ALL:
3,733✔
4157
         irgen_op_all(g, n);
3,733✔
4158
         break;
3,733✔
4159
      case MIR_OP_EXPONENT_CHECK:
659✔
4160
         irgen_op_exponent_check(g, n);
659✔
4161
         break;
659✔
4162
      case MIR_OP_NULL_CHECK:
2,892✔
4163
         irgen_op_null_check(g, n);
2,892✔
4164
         break;
2,892✔
4165
      case MIR_OP_ZERO_CHECK:
116✔
4166
         irgen_op_zero_check(g, n);
116✔
4167
         break;
116✔
4168
      case MIR_OP_LENGTH_CHECK:
9,518✔
4169
         irgen_op_length_check(g, n);
9,518✔
4170
         break;
9,518✔
4171
      case MIR_OP_CLOSURE:
6,517✔
4172
         irgen_op_closure(g, n);
6,517✔
4173
         break;
6,517✔
4174
      case MIR_OP_RESOLUTION_WRAPPER:
6,010✔
4175
         irgen_op_resolution_wrapper(g, n);
6,010✔
4176
         break;
6,010✔
4177
      case MIR_OP_INIT_SIGNAL:
21,791✔
4178
         irgen_op_init_signal(g, n);
21,791✔
4179
         break;
21,791✔
4180
      case MIR_OP_IMPLICIT_SIGNAL:
108✔
4181
         irgen_op_implicit_signal(g, n);
108✔
4182
         break;
108✔
4183
      case MIR_OP_ALIAS_SIGNAL:
5,604✔
4184
         irgen_op_alias_signal(g, n);
5,604✔
4185
         break;
5,604✔
4186
      case MIR_OP_MAP_SIGNAL:
7,125✔
4187
         irgen_op_map_signal(g, n);
7,125✔
4188
         break;
7,125✔
4189
      case MIR_OP_MAP_CONST:
252✔
4190
         irgen_op_map_const(g, n);
252✔
4191
         break;
252✔
4192
      case MIR_OP_MAP_IMPLICIT:
84✔
4193
         irgen_op_map_implicit(g, n);
84✔
4194
         break;
84✔
4195
      case MIR_OP_RESOLVE_SIGNAL:
4,695✔
4196
         irgen_op_resolve_signal(g, n);
4,695✔
4197
         break;
4,695✔
4198
      case MIR_OP_UNREACHABLE:
1,719✔
4199
         irgen_op_unreachable(g, n);
1,719✔
4200
         break;
1,719✔
4201
      case MIR_OP_REPORT:
2,740✔
4202
         irgen_op_report(g, n);
2,740✔
4203
         break;
2,740✔
4204
      case MIR_OP_ASSERT:
18,623✔
4205
         irgen_op_assert(g, n);
18,623✔
4206
         break;
18,623✔
4207
      case MIR_OP_CASE:
961✔
4208
         irgen_op_case(g, n);
961✔
4209
         break;
961✔
4210
      case MIR_OP_PROTECTED_INIT:
721✔
4211
         irgen_op_protected_init(g, n);
721✔
4212
         break;
721✔
4213
      case MIR_OP_REFLECT_VALUE:
64✔
4214
         irgen_op_reflect_value(g, n);
64✔
4215
         break;
64✔
4216
      case MIR_OP_REFLECT_SUBTYPE:
56✔
4217
         irgen_op_reflect_subtype(g, n);
56✔
4218
         break;
56✔
4219
      case MIR_OP_PROCESS_INIT:
154✔
4220
         irgen_op_process_init(g, n);
154✔
4221
         break;
154✔
4222
      case MIR_OP_FILE_OPEN:
1,555✔
4223
         irgen_op_file_open(g, n);
1,555✔
4224
         break;
1,555✔
4225
      case MIR_OP_FILE_READ:
120✔
4226
         irgen_op_file_read(g, n);
120✔
4227
         break;
120✔
4228
      case MIR_OP_FILE_WRITE:
338✔
4229
         irgen_op_file_write(g, n);
338✔
4230
         break;
338✔
4231
      case MIR_OP_PACKAGE_SCOPE:
59✔
4232
         irgen_op_package_scope(g, n);
59✔
4233
         break;
59✔
4234
      case MIR_OP_ARRAY_SCOPE:
839✔
4235
         irgen_op_array_scope(g, n);
839✔
4236
         break;
839✔
4237
      case MIR_OP_RECORD_SCOPE:
2,168✔
4238
         irgen_op_record_scope(g, n);
2,168✔
4239
         break;
2,168✔
4240
      case MIR_OP_POP_SCOPE:
3,066✔
4241
         irgen_op_pop_scope(g, n);
3,066✔
4242
         break;
3,066✔
4243
      case MIR_OP_DRIVE_SIGNAL:
12,428✔
4244
         irgen_op_drive_signal(g, n);
12,428✔
4245
         break;
12,428✔
4246
      case MIR_OP_TRANSFER_SIGNAL:
1,554✔
4247
         irgen_op_transfer_signal(g, n);
1,554✔
4248
         break;
1,554✔
4249
      case MIR_OP_RESOLVED:
19,353✔
4250
         irgen_op_resolved(g, n);
19,353✔
4251
         break;
19,353✔
4252
      case MIR_OP_LAST_VALUE:
275✔
4253
         irgen_op_last_value(g, n);
275✔
4254
         break;
275✔
4255
      case MIR_OP_SCHED_WAVEFORM:
14,305✔
4256
         irgen_op_sched_waveform(g, n);
14,305✔
4257
         break;
14,305✔
4258
      case MIR_OP_DISCONNECT:
32✔
4259
         irgen_op_disconnect(g, n);
32✔
4260
         break;
32✔
4261
      case MIR_OP_FORCE:
84✔
4262
         irgen_op_force(g, n);
84✔
4263
         break;
84✔
4264
      case MIR_OP_RELEASE:
40✔
4265
         irgen_op_release(g, n);
40✔
4266
         break;
40✔
4267
      case MIR_OP_DEPOSIT_SIGNAL:
368✔
4268
         irgen_op_deposit_signal(g, n);
368✔
4269
         break;
368✔
4270
      case MIR_OP_PUT_CONVERSION:
556✔
4271
         irgen_op_put_conversion(g, n);
556✔
4272
         break;
556✔
4273
      case MIR_OP_EVENT:
745✔
4274
         irgen_op_event(g, n);
745✔
4275
         break;
745✔
4276
      case MIR_OP_ACTIVE:
292✔
4277
         irgen_op_active(g, n);
292✔
4278
         break;
292✔
4279
      case MIR_OP_SCHED_EVENT:
7,989✔
4280
         irgen_op_sched_event(g, n);
7,989✔
4281
         break;
7,989✔
4282
      case MIR_OP_CLEAR_EVENT:
694✔
4283
         irgen_op_clear_event(g, n);
694✔
4284
         break;
694✔
UNCOV
4285
      case MIR_OP_DEBUG_OUT:
×
UNCOV
4286
         irgen_op_debug_out(g, n);
×
UNCOV
4287
         break;
×
4288
      case MIR_OP_LAST_EVENT:
44✔
4289
         irgen_op_last_event(g, n);
44✔
4290
         break;
44✔
4291
      case MIR_OP_LAST_ACTIVE:
48✔
4292
         irgen_op_last_active(g, n);
48✔
4293
         break;
48✔
4294
      case MIR_OP_DRIVING:
48✔
4295
         irgen_op_driving(g, n);
48✔
4296
         break;
48✔
4297
      case MIR_OP_DRIVING_VALUE:
152✔
4298
         irgen_op_driving_value(g, n);
152✔
4299
         break;
152✔
4300
      case MIR_OP_COVER_STMT:
3,109✔
4301
      case MIR_OP_COVER_BRANCH:
4302
      case MIR_OP_COVER_EXPR:
4303
         irgen_op_cover_increment(g, n);
3,109✔
4304
         break;
3,109✔
4305
      case MIR_OP_COVER_TOGGLE:
518✔
4306
         irgen_op_cover_toggle(g, n);
518✔
4307
         break;
518✔
4308
      case MIR_OP_COVER_STATE:
16✔
4309
         irgen_op_cover_state(g, n);
16✔
4310
         break;
16✔
4311
      case MIR_OP_ENTER_STATE:
1,040✔
4312
         irgen_op_enter_state(g, n);
1,040✔
4313
         break;
1,040✔
4314
      case MIR_OP_FUNCTION_TRIGGER:
286✔
4315
         irgen_op_function_trigger(g, n);
286✔
4316
         break;
286✔
4317
      case MIR_OP_OR_TRIGGER:
44✔
4318
         irgen_op_or_trigger(g, n);
44✔
4319
         break;
44✔
4320
      case MIR_OP_CMP_TRIGGER:
60✔
4321
         irgen_op_cmp_trigger(g, n);
60✔
4322
         break;
60✔
4323
      case MIR_OP_ADD_TRIGGER:
498✔
4324
         irgen_op_add_trigger(g, n);
498✔
4325
         break;
498✔
4326
      case MIR_OP_PORT_CONVERSION:
375✔
4327
         irgen_op_port_conversion(g, n);
375✔
4328
         break;
375✔
4329
      case MIR_OP_CONVERT_IN:
479✔
4330
         irgen_op_convert_in(g, n);
479✔
4331
         break;
479✔
4332
      case MIR_OP_CONVERT_OUT:
535✔
4333
         irgen_op_convert_out(g, n);
535✔
4334
         break;
535✔
4335
      case MIR_OP_BIND_FOREIGN:
1,306✔
4336
         irgen_op_bind_foreign(g, n);
1,306✔
4337
         break;
1,306✔
4338
      case MIR_OP_INSTANCE_NAME:
1,018✔
4339
         irgen_op_instance_name(g, n);
1,018✔
4340
         break;
1,018✔
4341
      case MIR_OP_BIND_EXTERNAL:
257✔
4342
         irgen_op_bind_external(g, n);
257✔
4343
         break;
257✔
4344
      case MIR_OP_PACK:
712✔
4345
         irgen_op_pack(g, n);
712✔
4346
         break;
712✔
4347
      case MIR_OP_UNPACK:
628✔
4348
         irgen_op_unpack(g, n);
628✔
4349
         break;
628✔
4350
      case MIR_OP_BINARY:
528✔
4351
         irgen_op_binary(g, n);
528✔
4352
         break;
528✔
4353
      case MIR_OP_UNARY:
56✔
4354
         irgen_op_unary(g, n);
56✔
4355
         break;
56✔
UNCOV
4356
      default:
×
UNCOV
4357
         DEBUG_ONLY(mir_dump(g->mu));
×
4358
         fatal_trace("cannot generate JIT IR for MIR op %s", mir_op_string(op));
4359
      }
4360
   }
4361

4362
   DEBUG_ONLY(if (nops == 0) j_trap(g));
204,671✔
4363
}
204,671✔
4364

4365
static void irgen_locals(jit_irgen_t *g)
71,490✔
4366
{
4367
   const int nvars = mir_count_vars(g->mu);
71,490✔
4368
   g->vars = xmalloc_array(nvars, sizeof(jit_value_t));
71,490✔
4369

4370
   bool on_stack;
71,490✔
4371
   const mir_unit_kind_t kind = mir_get_kind(g->mu);
71,490✔
4372
   switch (kind) {
71,490✔
4373
   case MIR_UNIT_PROCESS:
12,516✔
4374
   case MIR_UNIT_PROPERTY:
4375
      on_stack = g->stateless;
12,516✔
4376
      break;
12,516✔
4377
   case MIR_UNIT_INSTANCE:
4378
   case MIR_UNIT_PROCEDURE:
4379
   case MIR_UNIT_PACKAGE:
4380
   case MIR_UNIT_PROTECTED:
4381
      on_stack = false;
4382
      break;
4383
   default:
34,646✔
4384
      on_stack = !g->needs_context;
34,646✔
4385
      break;
34,646✔
4386
   }
4387

4388
   if (on_stack) {
47,162✔
4389
      // Local variables on stack
4390
      for (int i = 0; i < nvars; i++) {
65,657✔
4391
         mir_value_t var = mir_get_var(g->mu, i);
23,907✔
4392
         mir_type_t type = mir_get_var_type(g->mu, var);
23,907✔
4393
         const int sz = irgen_size_bytes(g, type);
23,907✔
4394
         if ((mir_get_var_flags(g->mu, var) & MIR_VAR_HEAP)
23,907✔
4395
             || sz > MAX_STACK_ALLOC) {
22,761✔
4396
            g->vars[i] = macro_lalloc(g, jit_value_from_int64(sz));
1,146✔
4397
            g->used_tlab = true;
1,146✔
4398
         }
4399
         else
4400
            g->vars[i] = macro_salloc(g, sz);
22,761✔
4401
      }
4402
   }
4403
   else {
4404
      // Local variables on heap
4405
      size_t sz = 0;
29,740✔
4406
      sz += sizeof(void *);   // Context parameter
29,740✔
4407
      if (kind == MIR_UNIT_PROCESS || kind == MIR_UNIT_PROCEDURE) {
29,740✔
4408
         sz += sizeof(void *);   // Suspended procedure state
5,166✔
4409
         sz += sizeof(int32_t);  // State number
5,166✔
4410
      }
4411

4412
      link_tab_t *linktab = xmalloc_array(nvars, sizeof(link_tab_t));
29,740✔
4413

4414
      for (int i = 0; i < nvars; i++) {
99,272✔
4415
         mir_value_t var = mir_get_var(g->mu, i);
69,532✔
4416
         mir_type_t type = mir_get_var_type(g->mu, var);
69,532✔
4417
         const int align = irgen_align_of(g, type);
69,532✔
4418
         sz = ALIGN_UP(sz, align);
69,532✔
4419
         linktab[i].name = mir_get_name(g->mu, var);
69,532✔
4420
         linktab[i].offset = sz;
69,532✔
4421
         sz += irgen_size_bytes(g, type);
69,532✔
4422
      }
4423

4424
      jit_value_t mem;
29,740✔
4425
      if (kind == MIR_UNIT_PROTECTED) {
29,740✔
4426
         // Protected types must always be allocated on the global heap
4427
         // as the result may be stored in an access
4428
         mem = macro_galloc(g, jit_value_from_int64(sz));
705✔
4429
      }
4430
      else {
4431
         mem = macro_lalloc(g, jit_value_from_int64(sz));
29,035✔
4432
         g->used_tlab = true;
29,035✔
4433
      }
4434

4435
      if (g->statereg.kind != JIT_VALUE_INVALID) {
29,740✔
4436
         // A null state was passed in by the caller
4437
         j_mov(g, jit_value_as_reg(g->statereg), mem);
5,202✔
4438
      }
4439
      else
4440
         g->statereg = mem;
24,538✔
4441

4442
      for (int i = 0; i < nvars; i++)
99,272✔
4443
         g->vars[i] = jit_addr_from_value(g->statereg, linktab[i].offset);
69,532✔
4444

4445
      // Publish the variable offset table early to handle circular references
4446
      // This may be read by another thread while in the COMPILING state
4447
      g->func->nvars = nvars;
29,740✔
4448
      store_release(&(g->func->linktab), linktab);
29,740✔
4449
   }
4450
}
71,490✔
4451

4452
static void irgen_params(jit_irgen_t *g, int first)
20,879✔
4453
{
4454
   // We never need more than the first few argument types
4455
   ffi_type_t types[7];
20,879✔
4456
   types[first] = FFI_POINTER;
20,879✔
4457
   types[0] = FFI_VOID;
20,879✔
4458

4459
   jit_value_t spill = { .kind = JIT_VALUE_INVALID };
20,879✔
4460
   int32_t spilloff = 0;
20,879✔
4461

4462
   const int nparams = mir_count_params(g->mu);
20,879✔
4463
   g->params = xmalloc_array(nparams, sizeof(jit_value_t));
20,879✔
4464

4465
   for (int i = 0, pslot = first; i < nparams; i++) {
72,598✔
4466
      mir_value_t p = mir_get_param(g->mu, i);
51,719✔
4467
      mir_type_t type = mir_get_type(g->mu, p);
51,719✔
4468
      int slots = irgen_slots_for_type(g, type);
51,719✔
4469

4470
      if (pslot + slots >= JIT_MAX_ARGS - 1) {
51,719✔
4471
         // Large number of arguments spill to the heap
4472
         if (spill.kind == JIT_VALUE_INVALID) {
24✔
4473
            spill = j_recv(g, JIT_MAX_ARGS - 1);
4✔
4474
            pslot = JIT_MAX_ARGS;
4✔
4475
         }
4476

4477
         jit_value_t ptr = jit_addr_from_value(spill, spilloff);
24✔
4478
         g->params[p.id] = j_load(g, JIT_SZ_64, ptr);
24✔
4479
         spilloff += sizeof(jit_scalar_t);
24✔
4480

4481
         for (int i = 1; i < slots; i++, spilloff += sizeof(jit_scalar_t)) {
100✔
4482
            jit_value_t ptr = jit_addr_from_value(spill, spilloff);
76✔
4483
            j_load(g, JIT_SZ_64, ptr);   // Must be contiguous registers
76✔
4484
         }
4485
      }
4486
      else {
4487
         g->params[p.id] = j_recv(g, pslot++);
51,695✔
4488
         for (int i = 1; i < slots; i++)
73,504✔
4489
            j_recv(g, pslot++);   // Must be contiguous registers
21,809✔
4490
      }
4491

4492
      if (i + first + 1 < ARRAY_LEN(types))
51,719✔
4493
         types[i + first + 1] = irgen_ffi_type(g, type);
51,305✔
4494
   }
4495

4496
   mir_unit_kind_t kind = mir_get_kind(g->mu);
20,879✔
4497
   if (kind == MIR_UNIT_FUNCTION || kind == MIR_UNIT_THUNK) {
20,879✔
4498
      mir_type_t rtype = mir_get_result(g->mu);
19,609✔
4499
      if (!mir_is_null(rtype))
19,609✔
4500
         types[0] = irgen_ffi_type(g, rtype);
16,923✔
4501
   }
4502

4503
   const int ntypes = MIN(ARRAY_LEN(types), first + nparams + 1);
20,879✔
4504
   g->func->spec = ffi_spec_new(types, ntypes);
20,879✔
4505
}
20,879✔
4506

4507
static void irgen_jump_table(jit_irgen_t *g)
5,166✔
4508
{
4509
   g->statereg = j_recv(g, 0);
5,166✔
4510

4511
   irgen_label_t *cont = irgen_alloc_label(g);
5,166✔
4512
   j_cmp(g, JIT_CC_EQ, g->statereg, jit_value_from_int64(0));
5,166✔
4513
   j_jump(g, JIT_CC_T, cont);
5,166✔
4514

4515
   jit_value_t state_ptr = irgen_state_ptr(g);
5,166✔
4516
   jit_value_t state = j_load(g, JIT_SZ_32, state_ptr);
5,166✔
4517
   jit_reg_t state_reg = jit_value_as_reg(state);
5,166✔
4518

4519
   const bool is_process = (mir_get_kind(g->mu) == MIR_UNIT_PROCESS);
5,166✔
4520
   const int nblocks = mir_count_blocks(g->mu);
5,166✔
4521

4522
   bit_mask_t have;
5,166✔
4523
   mask_init(&have, nblocks);
5,166✔
4524

4525
   for (int i = 0; i < nblocks; i++) {
41,684✔
4526
      mir_block_t b = mir_get_block(g->mu, i);
36,518✔
4527

4528
      const int num_nodes = mir_count_nodes(g->mu, b);
36,518✔
4529
      if (num_nodes == 0)
36,518✔
UNCOV
4530
         continue;
×
4531

4532
      mir_value_t last = mir_get_node(g->mu, b, num_nodes - 1);
36,518✔
4533

4534
      mir_block_t target = MIR_NULL_BLOCK;
36,518✔
4535
      const mir_op_t last_op = mir_get_op(g->mu, last);
36,518✔
4536

4537
      if (last_op == MIR_OP_WAIT || last_op == MIR_OP_PCALL)
36,518✔
4538
         target = mir_cast_block(mir_get_arg(g->mu, last, 0));
13,926✔
4539
      else if (is_process && last_op == MIR_OP_RETURN)
22,592✔
4540
         target = mir_get_block(g->mu, 1);
5,005✔
4541

4542
      if (mir_is_null(target) || mask_test(&have, target.id))
36,518✔
4543
         continue;
18,093✔
4544

4545
      macro_case(g, state_reg, jit_value_from_int64(target.id),
18,425✔
4546
                 g->blocks[target.id]);
18,425✔
4547

4548
      mask_set(&have, target.id);
36,518✔
4549
   }
4550

4551
   DEBUG_ONLY(j_trap(g));
5,166✔
4552

4553
   irgen_bind_label(g, cont);
5,166✔
4554
   mask_free(&have);
5,166✔
4555
}
5,166✔
4556

4557
static void irgen_analyse(jit_irgen_t *g)
71,490✔
4558
{
4559
   // A process is stateless if it has no non-temporary variables and
4560
   // all wait statements resume at the initial block
4561
   const mir_unit_kind_t kind = mir_get_kind(g->mu);
71,490✔
4562
   g->stateless = (kind == MIR_UNIT_PROCESS || kind == MIR_UNIT_PROPERTY);
71,490✔
4563

4564
   const int nvars = mir_count_vars(g->mu);
71,490✔
4565
   for (int i = 0; i < nvars; i++) {
76,145✔
4566
      mir_value_t var = mir_get_var(g->mu, i);
27,806✔
4567
      if (!(mir_get_var_flags(g->mu, var) & MIR_VAR_TEMP)) {
27,806✔
4568
         g->stateless = false;
23,151✔
4569
         break;
23,151✔
4570
      }
4571
   }
4572

4573
   const int nblocks = mir_count_blocks(g->mu);
71,490✔
4574
   for (int i = 0; i < nblocks; i++) {
276,161✔
4575
      mir_block_t b = mir_get_block(g->mu, i);
204,671✔
4576

4577
      const int nops = mir_count_nodes(g->mu, b);
204,671✔
4578
      for (int j = 0; j < nops; j++) {
1,886,408✔
4579
         mir_value_t n = mir_get_node(g->mu, b, j);
1,681,737✔
4580
         const mir_op_t op = mir_get_op(g->mu, n);
1,681,737✔
4581
         if (j == nops - 1 && op == MIR_OP_WAIT) {
1,681,737✔
4582
            mir_block_t target = mir_cast_block(mir_get_arg(g->mu, n, 0));
18,475✔
4583
            if (target.id != 1) {
18,475✔
4584
               // This a kludge: remove it when MIR optimises better
4585
               if (mir_count_nodes(g->mu, target) != 1)
18,023✔
4586
                  g->stateless = false;
7,526✔
4587
               else {
4588
                  mir_value_t n0 = mir_get_node(g->mu, target, 0);
10,497✔
4589
                  if (mir_get_op(g->mu, n0) != MIR_OP_JUMP)
10,497✔
4590
                     g->stateless = false;
242✔
4591
                  else if (mir_cast_block(mir_get_arg(g->mu, n0, 0)).id != 1)
10,255✔
4592
                     g->stateless = false;
353✔
4593
               }
4594
            }
4595
         }
4596
         else if (j == nops - 1 && op == MIR_OP_PCALL)
1,663,262✔
4597
            g->stateless = false;
1,084✔
4598
         else if (op == MIR_OP_CONTEXT_UPREF) {
1,662,178✔
4599
            const int hops = irgen_get_const(g, n, 0);
15,822✔
4600
            if (hops == 0) {
15,822✔
4601
               g->needs_context = true;
3,526✔
4602
               g->stateless = false;
3,526✔
4603
            }
4604
         }
4605
      }
4606
   }
4607
}
71,490✔
4608

4609
static void irgen_instance_entry(jit_irgen_t *g)
12,989✔
4610
{
4611
   const ffi_type_t types[] = { FFI_POINTER, FFI_POINTER };
12,989✔
4612
   g->func->spec = ffi_spec_new(types, ARRAY_LEN(types));
12,989✔
4613

4614
#ifdef DEBUG
4615
   // Instances should only be initialised once
4616
   irgen_label_t *cont = irgen_alloc_label(g);
12,989✔
4617
   jit_value_t priv = macro_getpriv(g, g->func->handle);
12,989✔
4618
   j_cmp(g, JIT_CC_EQ, priv, jit_value_from_int64(0));
12,989✔
4619
   j_jump(g, JIT_CC_T, cont);
12,989✔
4620
   j_trap(g);
12,989✔
4621
   irgen_bind_label(g, cont);
12,989✔
4622
#endif
4623

4624
   irgen_locals(g);
12,989✔
4625

4626
   // Stash context pointer
4627
   jit_value_t context = j_recv(g, 0);
12,989✔
4628
   j_store(g, JIT_SZ_PTR, context, jit_addr_from_value(g->statereg, 0));
12,989✔
4629

4630
   macro_putpriv(g, g->func->handle, g->statereg);
12,989✔
4631
}
12,989✔
4632

4633
static void irgen_process_entry(jit_irgen_t *g)
12,220✔
4634
{
4635
   const ffi_type_t types[] = { FFI_POINTER, FFI_POINTER, FFI_POINTER };
12,220✔
4636
   g->func->spec = ffi_spec_new(types, ARRAY_LEN(types));
12,220✔
4637

4638
   if (!g->stateless)
12,220✔
4639
      irgen_jump_table(g);
4,897✔
4640

4641
   irgen_locals(g);
12,220✔
4642

4643
   if (g->stateless) {
12,220✔
4644
      g->contextarg = j_recv(g, 1);
7,323✔
4645

4646
      jit_value_t state = j_recv(g, 0);
7,323✔
4647
      j_cmp(g, JIT_CC_EQ, state, jit_null_ptr());
7,323✔
4648
      j_jump(g, JIT_CC_F, g->blocks[1]);
7,323✔
4649
   }
4650
   else {
4651
      // Stash context pointer
4652
      jit_value_t context = j_recv(g, 1);
4,897✔
4653
      j_store(g, JIT_SZ_PTR, context, jit_addr_from_value(g->statereg, 0));
4,897✔
4654
   }
4655
}
12,220✔
4656

4657
static void irgen_property_entry(jit_irgen_t *g)
296✔
4658
{
4659
   irgen_params(g, 1);
296✔
4660

4661
   if (g->stateless)
296✔
4662
      irgen_locals(g);
260✔
4663

4664
   jit_value_t state = j_recv(g, 0);
296✔
4665
   j_cmp(g, JIT_CC_EQ, state, jit_null_ptr());
296✔
4666
   j_jump(g, JIT_CC_F, g->blocks[1]);
296✔
4667

4668
   if (g->stateless)
296✔
4669
      g->contextarg = g->params[0];
260✔
4670
   else
4671
      g->statereg = state;
36✔
4672

4673
   if (!g->stateless) {
296✔
4674
      irgen_locals(g);
36✔
4675

4676
      // Stash context pointer
4677
      jit_value_t context = jit_addr_from_value(g->statereg, 0);
36✔
4678
      j_store(g, JIT_SZ_PTR, g->params[0], context);
36✔
4679
   }
4680
}
296✔
4681

4682
static void irgen_function_entry(jit_irgen_t *g)
19,609✔
4683
{
4684
   const bool is_procedure = mir_is_null(mir_get_result(g->mu));
19,609✔
4685
   const int first_param = is_procedure ? 1 : 0;
19,609✔
4686
   irgen_params(g, first_param);
19,609✔
4687

4688
   irgen_locals(g);
19,609✔
4689

4690
   if (g->statereg.kind != JIT_VALUE_INVALID) {
19,609✔
4691
      // Stash context pointer
4692
      j_store(g, JIT_SZ_PTR, g->params[0], jit_addr_from_value(g->statereg, 0));
479✔
4693
   }
4694
}
19,609✔
4695

4696
static void irgen_procedure_entry(jit_irgen_t *g)
269✔
4697
{
4698
   irgen_jump_table(g);
269✔
4699
   irgen_params(g, 1);
269✔
4700
   irgen_locals(g);
269✔
4701

4702
   // Stash context pointer
4703
   j_store(g, JIT_SZ_PTR, g->params[0], jit_addr_from_value(g->statereg, 0));
269✔
4704
}
269✔
4705

4706
static void irgen_thunk_entry(jit_irgen_t *g)
15,037✔
4707
{
4708
   g->contextarg = j_recv(g, 0);
15,037✔
4709
   irgen_locals(g);
15,037✔
4710
}
15,037✔
4711

4712
static void irgen_package_entry(jit_irgen_t *g)
10,365✔
4713
{
4714
   // It's harmless to initialise a package multiple times, just return
4715
   // the existing context pointer
4716
   irgen_label_t *cont = irgen_alloc_label(g);
10,365✔
4717
   jit_value_t priv = macro_getpriv(g, g->func->handle);
10,365✔
4718
   j_cmp(g, JIT_CC_EQ, priv, jit_value_from_int64(0));
10,365✔
4719
   j_jump(g, JIT_CC_T, cont);
10,365✔
4720
   j_send(g, 0, priv);
10,365✔
4721
   j_ret(g);
10,365✔
4722
   irgen_bind_label(g, cont);
10,365✔
4723

4724
   irgen_locals(g);
10,365✔
4725

4726
   // Stash context pointer
4727
   jit_value_t context = j_recv(g, 0);
10,365✔
4728
   j_store(g, JIT_SZ_PTR, context, jit_addr_from_value(g->statereg, 0));
10,365✔
4729

4730
   macro_putpriv(g, g->func->handle, g->statereg);
10,365✔
4731
}
10,365✔
4732

4733
static void irgen_protected_entry(jit_irgen_t *g)
705✔
4734
{
4735
   const ffi_type_t types[] = { FFI_POINTER };
705✔
4736
   g->func->spec = ffi_spec_new(types, ARRAY_LEN(types));
705✔
4737

4738
   irgen_params(g, 1);
705✔
4739
   irgen_locals(g);
705✔
4740

4741
   // Stash context pointer
4742
   jit_value_t context = j_recv(g, 0);
705✔
4743
   j_store(g, JIT_SZ_PTR, context, jit_addr_from_value(g->statereg, 0));
705✔
4744
}
705✔
4745

4746
void jit_irgen(jit_func_t *f, mir_unit_t *mu)
71,490✔
4747
{
4748
   assert(load_acquire(&f->state) == JIT_FUNC_COMPILING);
71,490✔
4749
   assert(f->irbuf == NULL);
71,490✔
4750

4751
   const bool debug_log = opt_get_int(OPT_JIT_LOG) && f->name != NULL;
71,490✔
4752
   const uint64_t start_ticks = debug_log ? get_timestamp_us() : 0;
71,490✔
4753

4754
   const int num_nodes = mir_count_nodes(mu, MIR_NULL_BLOCK);
71,490✔
4755

4756
   jit_irgen_t *g = xcalloc(sizeof(jit_irgen_t));
71,490✔
4757
   g->func = f;
71,490✔
4758
   g->map  = xmalloc_array(num_nodes, sizeof(jit_value_t));
71,490✔
4759
   g->mu   = mu;
71,490✔
4760

4761
   const int nblocks = mir_count_blocks(g->mu);
71,490✔
4762
   g->blocks = xmalloc_array(nblocks, sizeof(irgen_label_t *));
71,490✔
4763

4764
   for (int i = 0; i < nblocks; i++)
276,161✔
4765
      g->blocks[i] = irgen_alloc_label(g);
204,671✔
4766

4767
   irgen_analyse(g);
71,490✔
4768

4769
   switch (mir_get_kind(g->mu)) {
71,490✔
4770
   case MIR_UNIT_INSTANCE:
12,989✔
4771
      irgen_instance_entry(g);
12,989✔
4772
      break;
12,989✔
4773
   case MIR_UNIT_PROCESS:
12,220✔
4774
      irgen_process_entry(g);
12,220✔
4775
      break;
12,220✔
4776
   case MIR_UNIT_FUNCTION:
19,609✔
4777
      irgen_function_entry(g);
19,609✔
4778
      break;
19,609✔
4779
   case MIR_UNIT_PROCEDURE:
269✔
4780
      irgen_procedure_entry(g);
269✔
4781
      break;
269✔
4782
   case MIR_UNIT_THUNK:
15,037✔
4783
      irgen_thunk_entry(g);
15,037✔
4784
      break;
15,037✔
4785
   case MIR_UNIT_PACKAGE:
10,365✔
4786
      irgen_package_entry(g);
10,365✔
4787
      break;
10,365✔
4788
   case MIR_UNIT_PROTECTED:
705✔
4789
      irgen_protected_entry(g);
705✔
4790
      break;
705✔
4791
   case MIR_UNIT_PROPERTY:
296✔
4792
      irgen_property_entry(g);
296✔
4793
      break;
296✔
UNCOV
4794
   default:
×
4795
      should_not_reach_here();
4796
   }
4797

4798
   for (int i = 0; i < nblocks; i++)
276,161✔
4799
      irgen_block(g, mir_get_block(mu, i));
204,671✔
4800

4801
   f->nregs   = g->next_reg;
71,490✔
4802
   f->cpoolsz = g->cpoolptr;
71,490✔
4803
   f->object  = mir_get_object(g->mu);
71,490✔
4804

4805
   for (irgen_label_t *it = g->labels, *tmp; it; it = tmp) {
397,697✔
4806
      assert(it->label < g->func->nirs);
326,207✔
4807
      if (it->uses > 0)
326,207✔
4808
         g->func->irbuf[it->label].target = 1;
216,005✔
4809
      tmp = it->next;
326,207✔
4810
      free(it);
326,207✔
4811
   }
4812
   g->labels = NULL;
71,490✔
4813

4814
   if (mir_get_kind(mu) != MIR_UNIT_THUNK) {
71,490✔
4815
      jit_do_mem2reg(f);
56,453✔
4816
      jit_do_lvn(f);
56,453✔
4817
      jit_do_cprop(f);
56,453✔
4818
      jit_do_dce(f);
56,453✔
4819
      jit_delete_nops(f);
56,453✔
4820
   }
4821

4822
   // Function can be executed immediately after this store
4823
   store_release(&(f->state), JIT_FUNC_READY);
71,490✔
4824

4825
   if (opt_get_verbose(OPT_JIT_VERBOSE, istr(f->name))) {
71,490✔
4826
#ifdef DEBUG
UNCOV
4827
      jit_dump_interleaved(f, mu);
×
4828
#else
4829
      jit_dump(f);
4830
#endif
4831
   }
4832

4833
   if (debug_log) {
71,490✔
UNCOV
4834
      const int ticks = get_timestamp_us() - start_ticks;
×
UNCOV
4835
      diag_t *d = diag_new(DIAG_DEBUG, NULL);
×
UNCOV
4836
      diag_printf(d, "%s: %d instructions", istr(f->name), f->nirs);
×
UNCOV
4837
      if (f->cpoolsz > 0)
×
UNCOV
4838
         diag_printf(d, "; %d cpool bytes", f->cpoolsz);
×
UNCOV
4839
      diag_printf(d, " [%d us]", ticks);
×
UNCOV
4840
      diag_emit(d);
×
4841
   }
4842

4843
   free(g->blocks);
71,490✔
4844
   free(g->map);
71,490✔
4845
   free(g->vars);
71,490✔
4846
   free(g->params);
71,490✔
4847
   free(g);
71,490✔
4848
}
71,490✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc