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

nickg / nvc / 25986469887

17 May 2026 08:44AM UTC coverage: 92.22% (-0.04%) from 92.258%
25986469887

push

github

nickg
Add PicoRV32 to regression tests

78454 of 85073 relevant lines covered (92.22%)

648774.32 hits per line

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

97.59
/src/mir/mir-node.c
1
//
2
//  Copyright (C) 2024-2026  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 "array.h"
20
#include "mir/mir-node.h"
21
#include "mir/mir-structs.h"
22
#include "mir/mir-priv.h"
23

24
#include <assert.h>
25
#include <limits.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <stdlib.h>
29

30
#define SMALL_CONST_BIAS (1 << (_MIR_ID_BITS - 1))
31
#define SMALL_CONST_MIN  (-SMALL_CONST_BIAS)
32
#define SMALL_CONST_MAX  (SMALL_CONST_BIAS - 1)
33

34
block_data_t *mir_block_data(mir_unit_t *mu, mir_block_t block)
20,306,577✔
35
{
36
   assert(block.tag == MIR_TAG_BLOCK);
20,306,577✔
37
   return AREF(mu->blocks, block.id);
20,306,577✔
38
}
39

40
mir_block_t mir_add_block(mir_unit_t *mu)
237,328✔
41
{
42
   mir_block_t b = { .tag = MIR_TAG_BLOCK, .id = mu->blocks.count };
237,328✔
43

44
   block_data_t bd = {
237,328✔
45
      .gap_pos = -1,
46
      .last_loc = mu->cursor.loc,
47
   };
48
   APUSH(mu->blocks, bd);
237,328✔
49

50
   return b;
237,328✔
51
}
52

53
void mir_set_cursor(mir_unit_t *mu, mir_block_t block, unsigned pos)
4,951,717✔
54
{
55
   if (!mir_is_null(mu->cursor.block))
4,951,717✔
56
      mir_block_data(mu, mu->cursor.block)->last_loc = mu->cursor.loc;
4,861,090✔
57

58
   mu->cursor.block = block;
4,951,717✔
59
   mu->cursor.pos   = pos;
4,951,717✔
60

61
   if (mir_is_null(block))
4,951,717✔
62
      mu->cursor.loc = LOC_INVALID;
5,024✔
63
   else
64
      mu->cursor.loc = mir_block_data(mu, block)->last_loc;
4,946,693✔
65
}
4,951,717✔
66

67
mir_block_t mir_get_cursor(mir_unit_t *mu, unsigned *pos)
77,308✔
68
{
69
   if (pos != NULL)
77,308✔
70
      *pos = mu->cursor.pos;
×
71

72
   return mu->cursor.block;
77,308✔
73
}
74

75
void mir_set_loc(mir_unit_t *mu, const loc_t *loc)
2,933,472✔
76
{
77
   mu->cursor.loc = *loc;
2,933,472✔
78
}
2,933,472✔
79

80
void mir_delete(mir_unit_t *mu)
42,189✔
81
{
82
   block_data_t *bd = mir_block_data(mu, mu->cursor.block);
42,189✔
83
   assert(mu->cursor.pos < bd->num_nodes);
42,189✔
84

85
   mir_value_t node = { .tag = MIR_TAG_NODE, .id = bd->nodes[mu->cursor.pos] };
42,189✔
86
   node_data_t *nd = mir_node_data(mu, node);
42,189✔
87
   nd->op = _MIR_DELETED_OP;
42,189✔
88
   nd->nargs = 0;
42,189✔
89

90
   if (bd->gap_pos == -1 || bd->gap_pos > mu->cursor.pos)
42,189✔
91
      bd->gap_pos = mu->cursor.pos;
42,189✔
92
}
42,189✔
93

94
void mir_compact(mir_unit_t *mu)
5,024✔
95
{
96
   for (int i = 0; i < mu->blocks.count; i++) {
24,834✔
97
      block_data_t *bd = &(mu->blocks.items[i]);
19,810✔
98
      if (bd->gap_pos == -1)
19,810✔
99
         continue;
7,001✔
100

101
      int wptr = bd->gap_pos;
102
      for (int j = bd->gap_pos; j < bd->num_nodes; j++) {
256,215✔
103
         if (mu->nodes[bd->nodes[j]].op != _MIR_DELETED_OP)
243,406✔
104
            bd->nodes[wptr++] = bd->nodes[j];
243,406✔
105
      }
106
      bd->num_nodes = wptr;
12,809✔
107
   }
108

109
   mir_set_cursor(mu, MIR_NULL_BLOCK, MIR_APPEND);
5,024✔
110
}
5,024✔
111

112
unsigned mir_count_blocks(mir_unit_t *mu)
175,289✔
113
{
114
   return mu->blocks.count;
175,289✔
115
}
116

117
mir_block_t mir_get_block(mir_unit_t *mu, unsigned nth)
760,756✔
118
{
119
   assert(nth < mu->blocks.count);
760,756✔
120
   return (mir_block_t) { .tag = MIR_TAG_BLOCK, .id = nth };
760,756✔
121
}
122

123
unsigned mir_count_nodes(mir_unit_t *mu, mir_block_t block)
861,996✔
124
{
125
   if (mir_is_null(block))
861,996✔
126
      return mu->num_nodes;
84,508✔
127
   else
128
      return mir_block_data(mu, block)->num_nodes;
777,488✔
129
}
130

131
mir_value_t mir_get_node(mir_unit_t *mu, mir_block_t block, unsigned nth)
6,665,790✔
132
{
133
   const block_data_t *bd = mir_block_data(mu, block);
6,665,790✔
134
   assert(nth < bd->num_nodes);
6,665,790✔
135
   return (mir_value_t) { .tag = MIR_TAG_NODE, .id = bd->nodes[nth] };
6,665,790✔
136
}
137

138
unsigned mir_count_vars(mir_unit_t *mu)
169,016✔
139
{
140
   return mu->vars.count;
169,016✔
141
}
142

143
mir_value_t mir_get_var(mir_unit_t *mu, unsigned nth)
183,727✔
144
{
145
   assert(nth < mu->vars.count);
183,727✔
146
   return (mir_value_t) { .tag = MIR_TAG_VAR, .id = nth };
183,727✔
147
}
148

149
mir_value_t mir_get_param(mir_unit_t *mu, unsigned nth)
68,885✔
150
{
151
   assert(nth < mu->params.count);
68,885✔
152
   return (mir_value_t) { .tag = MIR_TAG_PARAM, .id = nth };
68,885✔
153
}
154

155
unsigned mir_count_params(mir_unit_t *mu)
67,389✔
156
{
157
   return mu->params.count;
67,389✔
158
}
159

160
unsigned mir_count_vregs(mir_unit_t *mu)
234,679✔
161
{
162
   return mu->num_vregs;
234,679✔
163
}
164

165
mir_op_t mir_get_op(mir_unit_t *mu, mir_value_t node)
7,129,852✔
166
{
167
   switch (node.tag) {
7,129,852✔
168
   case MIR_TAG_NODE:
7,101,163✔
169
      return mir_node_data(mu, node)->op;
7,101,163✔
170
   default:
171
      return _MIR_DELETED_OP;
172
   }
173
}
174

175
const loc_t *mir_get_loc(mir_unit_t *mu, mir_value_t node)
2,211,693✔
176
{
177
   switch (node.tag) {
2,211,693✔
178
   case MIR_TAG_NODE:
2,211,693✔
179
      return &(mir_node_data(mu, node)->loc);
2,211,693✔
180
   case MIR_TAG_NULL:
×
181
      return &(mu->cursor.loc);
×
182
   default:
×
183
      should_not_reach_here();
184
   }
185
}
186

187
unsigned mir_count_args(mir_unit_t *mu, mir_value_t node)
382,118✔
188
{
189
   return mir_node_data(mu, node)->nargs;
382,118✔
190
}
191

192
const mir_value_t *mir_get_args(mir_unit_t *mu, const node_data_t *nd)
12,993,740✔
193
{
194
   if (nd->nargs <= MIR_INLINE_ARGS)
12,993,740✔
195
      return nd->args;
9,076,222✔
196
   else {
197
      assert(nd->spilloff < mu->num_argspill);
3,917,518✔
198
      return mu->argspill + nd->spilloff;
3,917,518✔
199
   }
200
}
201

202
mir_value_t mir_get_arg(mir_unit_t *mu, mir_value_t node, unsigned nth)
7,462,624✔
203
{
204
   const node_data_t *nd = mir_node_data(mu, node);
7,462,624✔
205
   if (nth >= nd->nargs)
7,462,624✔
206
      return MIR_NULL_VALUE;
601✔
207
   else
208
      return mir_get_args(mu, nd)[nth];
7,462,023✔
209
}
210

211
mir_value_t mir_add_param(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
49,699✔
212
                          ident_t name)
213
{
214
   mir_value_t p = { .tag = MIR_TAG_PARAM, .id = mu->params.count };
49,699✔
215

216
   param_data_t pd = {
49,699✔
217
      .name  = name,
218
      .type  = type,
219
      .stamp = stamp,
220
   };
221
   APUSH(mu->params, pd);
49,699✔
222

223
   return p;
49,699✔
224
}
225

226
mir_value_t mir_add_var(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
145,540✔
227
                        ident_t name, mir_var_flags_t flags)
228
{
229
   mir_value_t v = { .tag = MIR_TAG_VAR, .id = mu->vars.count };
145,540✔
230

231
   mir_mem_t mem = MIR_MEM_STACK;
145,540✔
232
   if (flags & MIR_VAR_HEAP)
145,540✔
233
      mem = MIR_MEM_LOCAL;
1,572✔
234

235
   var_data_t vd = {
291,080✔
236
      .name    = name,
237
      .type    = type,
238
      .pointer = mir_get_var_pointer(mu, type),
145,540✔
239
      .stamp   = mir_pointer_stamp(mu, mem, stamp),
145,540✔
240
      .flags   = flags,
241
   };
242
   APUSH(mu->vars, vd);
145,540✔
243

244
   return v;
145,540✔
245
}
246

247
bool mir_is_terminator(mir_op_t op)
240,567✔
248
{
249
   switch (op) {
240,567✔
250
   case MIR_OP_RETURN:
251
   case MIR_OP_JUMP:
252
   case MIR_OP_COND:
253
   case MIR_OP_WAIT:
254
   case MIR_OP_CASE:
255
   case MIR_OP_PCALL:
256
   case MIR_OP_UNREACHABLE:
257
      return true;
258
   default:
3,841✔
259
      return false;
3,841✔
260
   }
261
}
262

263
bool mir_block_finished(mir_unit_t *mu, mir_block_t block)
4,381✔
264
{
265
   if (mir_is_null(block))
4,381✔
266
      block = mu->cursor.block;
4,361✔
267

268
   const block_data_t *bd = mir_block_data(mu, block);
4,381✔
269
   if (bd->num_nodes == 0)
4,381✔
270
      return false;
271

272
   return mir_is_terminator(mu->nodes[bd->nodes[bd->num_nodes - 1]].op);
3,857✔
273
}
274

275
mir_vreg_t mir_get_vreg(mir_unit_t *mu, mir_value_t value)
1,256,456✔
276
{
277
   if (mu->vregs == NULL)
1,256,456✔
278
      fatal_trace("%pi has not been optimised", mu->name);
279

280
   assert(value.tag == MIR_TAG_NODE);
1,256,456✔
281
   return mu->vregs[value.id];
1,256,456✔
282
}
283

284
static inline node_id_t mir_node_id(mir_unit_t *mu, node_data_t *n)
2,176,748✔
285
{
286
   assert(n >= mu->nodes && n < mu->nodes + mu->num_nodes);
2,176,748✔
287
   return n - mu->nodes;
2,176,748✔
288
}
289

290
static node_data_t *mir_alloc_node(mir_unit_t *mu)
2,258,638✔
291
{
292
   assert(!mir_is_null(mu->cursor.block));
2,258,638✔
293

294
   node_data_t *n;
2,258,638✔
295
   block_data_t *bd = mir_block_data(mu, mu->cursor.block);
2,258,638✔
296
   if (mu->cursor.pos >= bd->num_nodes) {
2,258,638✔
297
      // Append new node
298
      if (bd->num_nodes == bd->max_nodes) {
2,216,449✔
299
         bd->max_nodes = MAX(4, bd->num_nodes * 2);
478,020✔
300
         bd->nodes = xrealloc_array(bd->nodes, bd->max_nodes,
478,020✔
301
                                    sizeof(node_id_t));
302
      }
303

304
      if (mu->num_nodes == mu->max_nodes) {
2,216,449✔
305
         mu->max_nodes = MAX(8, mu->num_nodes * 2);
177,388✔
306
         mu->nodes = xrealloc_array(mu->nodes, mu->max_nodes,
177,388✔
307
                                    sizeof(node_data_t));
308
      }
309

310
      bd->nodes[bd->num_nodes++] = mu->num_nodes;
2,216,449✔
311
      n = &(mu->nodes[mu->num_nodes++]);
2,216,449✔
312
   }
313
   else {
314
      n = &(mu->nodes[bd->nodes[mu->cursor.pos]]);
42,189✔
315
      assert(n->op == _MIR_DELETED_OP);
42,189✔
316
   }
317

318
   return n;
2,258,638✔
319
}
320

321
static size_t mir_spill_args(mir_unit_t *mu, unsigned num)
145,317✔
322
{
323
   if (mu->num_argspill + num > mu->max_argspill) {
145,317✔
324
      mu->max_argspill = MAX(16, MAX(mu->num_argspill + num,
65,471✔
325
                                     mu->max_argspill * 2));
326
      mu->argspill = xrealloc_array(mu->argspill, mu->max_argspill,
65,471✔
327
                                    sizeof(mir_value_t));
328
   }
329

330
   const size_t off = mu->num_argspill;
145,317✔
331
   mu->num_argspill += num;
145,317✔
332
   return off;
145,317✔
333
}
334

335
static node_data_t *mir_add_node(mir_unit_t *mu, mir_op_t op, mir_type_t type,
2,258,638✔
336
                                 mir_stamp_t stamp, unsigned nargs)
337
{
338
   node_data_t *n = mir_alloc_node(mu);
2,258,638✔
339
   n->loc   = mu->cursor.loc;
2,258,638✔
340
   n->op    = op;
2,258,638✔
341
   n->type  = type;
2,258,638✔
342
   n->stamp = stamp;
2,258,638✔
343
   n->nargs = nargs;
2,258,638✔
344

345
   if (nargs > MIR_INLINE_ARGS)
2,258,638✔
346
      n->spilloff = mir_spill_args(mu, nargs);
145,317✔
347

348
   MIR_ASSERT(mu->vregs == NULL, "cannot add nodes after register allocation");
2,258,638✔
349

350
   return n;
2,258,638✔
351
}
352

353
static mir_value_t mir_build_0(mir_unit_t *mu, mir_op_t op, mir_type_t type,
14,834✔
354
                               mir_stamp_t stamp)
355
{
356
   node_data_t *n = mir_add_node(mu, op, type, stamp, 0);
14,834✔
357
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
14,834✔
358
}
359

360
static mir_value_t mir_build_1(mir_unit_t *mu, mir_op_t op, mir_type_t type,
784,647✔
361
                               mir_stamp_t stamp, mir_value_t arg)
362
{
363
   node_data_t *n = mir_add_node(mu, op, type, stamp, 1);
784,647✔
364
   n->args[0] = arg;
784,647✔
365

366
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
784,647✔
367
}
368

369
static mir_value_t mir_build_2(mir_unit_t *mu, mir_op_t op, mir_type_t type,
515,836✔
370
                               mir_stamp_t stamp, mir_value_t arg1,
371
                               mir_value_t arg2)
372
{
373
   STATIC_ASSERT(MIR_INLINE_ARGS >= 2);
515,836✔
374

375
   node_data_t *n = mir_add_node(mu, op, type, stamp, 2);
515,836✔
376
   n->args[0] = arg1;
515,836✔
377
   n->args[1] = arg2;
515,836✔
378

379
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
515,836✔
380
}
381

382
static mir_value_t mir_build_3(mir_unit_t *mu, mir_op_t op, mir_type_t type,
381,503✔
383
                               mir_stamp_t stamp, mir_value_t arg1,
384
                               mir_value_t arg2, mir_value_t arg3)
385
{
386
   STATIC_ASSERT(MIR_INLINE_ARGS >= 3);
381,503✔
387

388
   node_data_t *n = mir_add_node(mu, op, type, stamp, 3);
381,503✔
389
   n->args[0] = arg1;
381,503✔
390
   n->args[1] = arg2;
381,503✔
391
   n->args[2] = arg3;
381,503✔
392

393
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
381,503✔
394
}
395

396
static mir_value_t mir_build_4(mir_unit_t *mu, mir_op_t op, mir_type_t type,
6,284✔
397
                               mir_stamp_t stamp, mir_value_t arg1,
398
                               mir_value_t arg2, mir_value_t arg3,
399
                               mir_value_t arg4)
400
{
401
   STATIC_ASSERT(MIR_INLINE_ARGS >= 4);
6,284✔
402

403
   node_data_t *n = mir_add_node(mu, op, type, stamp, 4);
6,284✔
404
   n->args[0] = arg1;
6,284✔
405
   n->args[1] = arg2;
6,284✔
406
   n->args[2] = arg3;
6,284✔
407
   n->args[3] = arg4;
6,284✔
408

409
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
6,284✔
410
}
411

412
static mir_value_t mir_build_5(mir_unit_t *mu, mir_op_t op, mir_type_t type,
49,592✔
413
                               mir_stamp_t stamp, mir_value_t arg1,
414
                               mir_value_t arg2, mir_value_t arg3,
415
                               mir_value_t arg4, mir_value_t arg5)
416
{
417
   node_data_t *n = mir_add_node(mu, op, type, stamp, 5);
49,592✔
418
   n->nargs = 5;
49,592✔
419

420
   STATIC_ASSERT(MIR_INLINE_ARGS < 5);
49,592✔
421

422
   mu->argspill[n->spilloff + 0] = arg1;
49,592✔
423
   mu->argspill[n->spilloff + 1] = arg2;
49,592✔
424
   mu->argspill[n->spilloff + 2] = arg3;
49,592✔
425
   mu->argspill[n->spilloff + 3] = arg4;
49,592✔
426
   mu->argspill[n->spilloff + 4] = arg5;
49,592✔
427

428
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
49,592✔
429
}
430

431
static mir_value_t mir_build_6(mir_unit_t *mu, mir_op_t op, mir_type_t type,
35,517✔
432
                               mir_stamp_t stamp, mir_value_t arg1,
433
                               mir_value_t arg2, mir_value_t arg3,
434
                               mir_value_t arg4, mir_value_t arg5,
435
                               mir_value_t arg6)
436
{
437
   node_data_t *n = mir_add_node(mu, op, type, stamp, 6);
35,517✔
438

439
   STATIC_ASSERT(MIR_INLINE_ARGS < 6);
35,517✔
440

441
   mu->argspill[n->spilloff + 0] = arg1;
35,517✔
442
   mu->argspill[n->spilloff + 1] = arg2;
35,517✔
443
   mu->argspill[n->spilloff + 2] = arg3;
35,517✔
444
   mu->argspill[n->spilloff + 3] = arg4;
35,517✔
445
   mu->argspill[n->spilloff + 4] = arg5;
35,517✔
446
   mu->argspill[n->spilloff + 5] = arg6;
35,517✔
447

448
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
35,517✔
449
}
450

451
static mir_value_t mir_add_linkage(mir_unit_t *mu, ident_t ident)
241,435✔
452
{
453
   for (int i = 0; i < mu->linkage.count; i++) {
576,415✔
454
      if (mu->linkage.items[i] == ident)
453,162✔
455
         return (mir_value_t){ .tag = MIR_TAG_LINKAGE, .id = i };
118,182✔
456
   }
457

458
   mir_value_t link = { .tag = MIR_TAG_LINKAGE, .id = mu->linkage.count };
123,253✔
459

460
   APUSH(mu->linkage, ident);
123,253✔
461

462
   return link;
123,253✔
463
}
464

465
static mir_value_t mir_add_extvar(mir_unit_t *mu, ident_t ident)
9,890✔
466
{
467
   for (int i = 0; i < mu->extvars.count; i++) {
19,559✔
468
      if (mu->extvars.items[i] == ident)
11,443✔
469
         return (mir_value_t){ .tag = MIR_TAG_EXTVAR, .id = i };
1,774✔
470
   }
471

472
   mir_value_t var = { .tag = MIR_TAG_EXTVAR, .id = mu->extvars.count };
8,116✔
473

474
   APUSH(mu->extvars, ident);
8,116✔
475

476
   return var;
8,116✔
477
}
478

479
void mir_set_arg(mir_unit_t *mu, node_data_t *n, unsigned nth,
3,521,474✔
480
                 mir_value_t value)
481
{
482
   assert(nth < n->nargs);
3,521,474✔
483

484
   if (n->nargs <= MIR_INLINE_ARGS)
3,521,474✔
485
      n->args[nth] = value;
442,283✔
486
   else {
487
      assert(n->spilloff < mu->num_argspill);
3,079,191✔
488
      mu->argspill[n->spilloff + nth] = value;
3,079,191✔
489
   }
490
}
3,521,474✔
491

492
node_data_t *mir_node_data(mir_unit_t *mu, mir_value_t value)
32,115,533✔
493
{
494
   assert(value.tag == MIR_TAG_NODE);
32,115,533✔
495
   assert(value.id < mu->num_nodes);
32,115,533✔
496

497
   return &(mu->nodes[value.id]);
32,115,533✔
498
}
499

500
const param_data_t *mir_param_data(mir_unit_t *mu, mir_value_t value)
277,346✔
501
{
502
   assert(value.tag == MIR_TAG_PARAM);
277,346✔
503
   return AREF(mu->params, value.id);
277,346✔
504
}
505

506
const var_data_t *mir_var_data(mir_unit_t *mu, mir_value_t value)
1,052,903✔
507
{
508
   assert(value.tag == MIR_TAG_VAR);
1,052,903✔
509
   return AREF(mu->vars, value.id);
1,052,903✔
510
}
511

512
#ifdef DEBUG
513
void mir_comment(mir_unit_t *mu, const char *fmt, ...)
50,718✔
514
{
515
   va_list ap;
50,718✔
516
   va_start(ap, fmt);
50,718✔
517

518
   if (mu->comments == NULL)
50,718✔
519
      mu->comments = tb_new();
8,084✔
520

521
   mir_value_t value = { .tag = MIR_TAG_COMMENT, .id = tb_len(mu->comments) };
50,718✔
522

523
   tb_vprintf(mu->comments, fmt, ap);
50,718✔
524
   tb_append(mu->comments, '\0');
50,718✔
525

526
   va_end(ap);
50,718✔
527

528
   mir_build_1(mu, MIR_OP_COMMENT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
50,718✔
529
}
50,718✔
530
#endif
531

532
mir_saved_loc_t _mir_push_debug_info(mir_unit_t *mu, const loc_t *loc)
129,338✔
533
{
534
   mir_saved_loc_t result = { mu, mu->cursor.loc };
129,338✔
535
   mu->cursor.loc = *loc;
129,338✔
536
   return result;
129,338✔
537
}
538

539
bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result)
7,709,899✔
540
{
541
   switch (value.tag) {
7,709,899✔
542
   case MIR_TAG_CONST:
6,924,098✔
543
      *result = (int64_t)value.id - SMALL_CONST_BIAS;
6,924,098✔
544
      return true;
6,924,098✔
545
   case MIR_TAG_ENUM:
337,292✔
546
      *result = value.id;
337,292✔
547
      return true;
337,292✔
548
   case MIR_TAG_NODE:
435,405✔
549
      {
550
         const node_data_t *n = mir_node_data(mu, value);
435,405✔
551
         if (n->op == MIR_OP_CONST) {
435,405✔
552
            *result = n->iconst;
11,020✔
553
            return true;
11,020✔
554
         }
555
         else
556
            return false;
557
      }
558
   default:
559
      return false;
560
   }
561
}
562

563
bool mir_get_const_real(mir_unit_t *mu, mir_value_t value, double *result)
176,362✔
564
{
565
   switch (value.tag) {
176,362✔
566
   case MIR_TAG_NODE:
132,360✔
567
      {
568
         const node_data_t *n = mir_node_data(mu, value);
132,360✔
569
         if (n->op == MIR_OP_CONST_REAL) {
132,360✔
570
            *result = n->dconst;
30,932✔
571
            return true;
30,932✔
572
         }
573
         else
574
            return false;
575
      }
576
   default:
577
      return false;
578
   }
579
}
580

581
mir_type_t mir_get_type(mir_unit_t *mu, mir_value_t value)
9,192,118✔
582
{
583
   switch (value.tag) {
9,192,118✔
584
   case MIR_TAG_NODE:
8,157,939✔
585
      return mir_node_data(mu, value)->type;
8,157,939✔
586
   case MIR_TAG_PARAM:
243,284✔
587
      return mir_param_data(mu, value)->type;
243,284✔
588
   case MIR_TAG_VAR:
577,560✔
589
      return mir_var_data(mu, value)->pointer;
577,560✔
590
   default:
213,335✔
591
      return MIR_NULL_TYPE;
213,335✔
592
   }
593
}
594

595
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
1,166,107✔
596
{
597
   switch (value.tag) {
1,166,107✔
598
   case MIR_TAG_NODE:
904,669✔
599
      return mir_node_data(mu, value)->stamp;
904,669✔
600
   case MIR_TAG_PARAM:
34,036✔
601
      return mir_param_data(mu, value)->stamp;
34,036✔
602
   case MIR_TAG_VAR:
146,593✔
603
      return mir_var_data(mu, value)->stamp;
146,593✔
604
   case MIR_TAG_CONST:
80,809✔
605
      {
606
         const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
80,809✔
607
         return mir_int_stamp(mu, ival, ival);
80,809✔
608
      }
609
   default:
×
610
      return MIR_NULL_STAMP;
×
611
   }
612
}
613

614
mir_mem_t mir_get_mem(mir_unit_t *mu, mir_value_t value)
322,348✔
615
{
616
   mir_type_t type = mir_get_type(mu, value);
322,348✔
617
   if (mir_is_null(type))
322,348✔
618
      return MIR_MEM_NONE;
619

620
   switch (mir_type_data(mu, type)->class) {
320,777✔
621
   case MIR_TYPE_UARRAY:
622
   case MIR_TYPE_CARRAY:
623
   case MIR_TYPE_RECORD:
624
   case MIR_TYPE_POINTER:
625
   case MIR_TYPE_ACCESS:
626
      break;
318,803✔
627
   default:
628
      return MIR_MEM_NONE;
629
   }
630

631
   mir_stamp_t stamp = mir_get_stamp(mu, value);
318,803✔
632
   if (mir_is_null(stamp))
318,803✔
633
      return MIR_MEM_TOP;
634

635
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
96,243✔
636
   if (sd->kind == MIR_STAMP_POINTER)
96,243✔
637
      return sd->u.pointer.memory;
95,991✔
638

639
   return MIR_MEM_NONE;
640
}
641

642
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
346,956✔
643
{
644
   switch (value.tag) {
346,956✔
645
   case MIR_TAG_PARAM:
26✔
646
      return mir_param_data(mu, value)->name;
26✔
647
   case MIR_TAG_VAR:
118,100✔
648
      return mir_var_data(mu, value)->name;
118,100✔
649
   case MIR_TAG_LINKAGE:
220,541✔
650
      return AGET(mu->linkage, value.id);
220,541✔
651
   case MIR_TAG_EXTVAR:
7,794✔
652
      return AGET(mu->extvars, value.id);
7,794✔
653
   case MIR_TAG_NULL:
495✔
654
      return mu->name;
495✔
655
   default:
656
      return NULL;
657
   }
658
}
659

660
void mir_set_result(mir_unit_t *mu, mir_type_t type)
31,580✔
661
{
662
   assert(mu->kind == MIR_UNIT_FUNCTION || mu->kind == MIR_UNIT_THUNK);
31,580✔
663
   mu->result = type;
31,580✔
664
}
31,580✔
665

666
mir_type_t mir_get_result(mir_unit_t *mu)
41,775✔
667
{
668
   return mu->result;
41,775✔
669
}
670

671
object_t *mir_get_locus(mir_unit_t *mu, mir_value_t value)
131,676✔
672
{
673
   switch (value.tag) {
131,676✔
674
   case MIR_TAG_NODE:
131,676✔
675
      {
676
         node_data_t *n = mir_node_data(mu, value);
131,676✔
677
         assert(n->op == MIR_OP_DEBUG_LOCUS);
131,676✔
678
         return n->locus;
131,676✔
679
      }
680
      break;
×
681
   default:
×
682
      should_not_reach_here();
683
   }
684
}
685

686
void mir_get_bits(mir_unit_t *mu, mir_value_t value, uint64_t *abits,
20,643✔
687
                  uint64_t *bbits)
688
{
689
   switch (value.tag) {
20,643✔
690
   case MIR_TAG_NODE:
20,643✔
691
      {
692
         node_data_t *n = mir_node_data(mu, value);
20,643✔
693
         assert(n->op == MIR_OP_CONST_VEC);
20,643✔
694

695
         *abits = n->bits[0];
20,643✔
696
         *bbits = n->bits[1];
20,643✔
697
      }
698
      break;
20,643✔
699
   default:
×
700
      should_not_reach_here();
701
   }
702
}
20,643✔
703

704
mir_var_flags_t mir_get_var_flags(mir_unit_t *mu, mir_value_t value)
65,660✔
705
{
706
   switch (value.tag) {
65,660✔
707
   case MIR_TAG_VAR:
65,660✔
708
      return mir_var_data(mu, value)->flags;
65,660✔
709
   default:
710
      return 0;
711
   }
712
}
713

714
mir_type_t mir_get_var_type(mir_unit_t *mu, mir_value_t value)
144,990✔
715
{
716
   switch (value.tag) {
144,990✔
717
   case MIR_TAG_VAR:
144,990✔
718
      return mir_var_data(mu, value)->type;
144,990✔
719
   default:
×
720
      return MIR_NULL_TYPE;
×
721
   }
722
}
723

724
bool mir_is_integral(mir_unit_t *mu, mir_value_t value)
197,252✔
725
{
726
   if (value.tag == MIR_TAG_CONST)
197,252✔
727
      return true;
728

729
   mir_type_t type = mir_get_type(mu, value);
120,852✔
730
   if (mir_is_null(type))
120,852✔
731
      return false;
732

733
   switch (mir_type_data(mu, type)->class) {
120,852✔
734
   case MIR_TYPE_INT:
735
   case MIR_TYPE_OFFSET:
736
      return true;
737
   default:
7,717✔
738
      return false;
7,717✔
739
   }
740
}
741

742
bool mir_is_numeric(mir_unit_t *mu, mir_value_t value)
86,548✔
743
{
744
   if (value.tag == MIR_TAG_CONST)
86,548✔
745
      return true;
746

747
   mir_type_t type = mir_get_type(mu, value);
69,137✔
748
   if (mir_is_null(type))
69,137✔
749
      return false;
750

751
   switch (mir_type_data(mu, type)->class) {
69,137✔
752
   case MIR_TYPE_INT:
753
   case MIR_TYPE_OFFSET:
754
   case MIR_TYPE_REAL:
755
   case MIR_TYPE_VEC2:
756
   case MIR_TYPE_VEC4:
757
      return true;
758
   default:
298✔
759
      return false;
298✔
760
   }
761
}
762

763
bool mir_is_scalar(mir_unit_t *mu, mir_value_t value)
309,237✔
764
{
765
   if (value.tag == MIR_TAG_CONST)
309,237✔
766
      return true;
767

768
   mir_type_t type = mir_get_type(mu, value);
291,582✔
769
   if (mir_is_null(type))
291,582✔
770
      return false;
771

772
   switch (mir_type_data(mu, type)->class) {
281,799✔
773
   case MIR_TYPE_INT:
774
   case MIR_TYPE_OFFSET:
775
   case MIR_TYPE_REAL:
776
   case MIR_TYPE_ACCESS:
777
   case MIR_TYPE_POINTER:
778
   case MIR_TYPE_UARRAY:
779
   case MIR_TYPE_SIGNAL:
780
   case MIR_TYPE_CONTEXT:
781
   case MIR_TYPE_RESOLUTION:
782
   case MIR_TYPE_FILE:
783
   case MIR_TYPE_TRIGGER:
784
   case MIR_TYPE_VEC2:
785
   case MIR_TYPE_VEC4:
786
      return true;
787
   default:
×
788
      return false;
×
789
   }
790
}
791

792
bool mir_is_vector(mir_unit_t *mu, mir_value_t value)
277,231✔
793
{
794
   mir_type_t type = mir_get_type(mu, value);
277,231✔
795
   if (mir_is_null(type))
277,231✔
796
      return false;
797

798
   switch (mir_type_data(mu, type)->class) {
277,231✔
799
   case MIR_TYPE_VEC2:
800
   case MIR_TYPE_VEC4:
801
      return true;
802
   default:
73,458✔
803
      return false;
73,458✔
804
   }
805
}
806

807
bool mir_is_bool(mir_unit_t *mu, mir_value_t value)
192,056✔
808
{
809
   if (value.tag == MIR_TAG_CONST)
192,056✔
810
      return value.id == SMALL_CONST_BIAS || value.id == SMALL_CONST_BIAS + 1;
53,635✔
811
   else
812
      return mir_equals(mir_get_type(mu, value), mir_bool_type(mu));
138,421✔
813
}
814

815
bool mir_is_time(mir_unit_t *mu, mir_value_t value)
11,613✔
816
{
817
   if (value.tag == MIR_TAG_CONST)
11,613✔
818
      return true;
819

820
   return mir_equals(mir_get_type(mu, value), mir_time_type(mu));
148✔
821
}
822

823
bool mir_is(mir_unit_t *mu, mir_value_t value, mir_class_t class)
1,198,950✔
824
{
825
   mir_type_t type = mir_get_type(mu, value);
1,198,950✔
826
   if (mir_is_null(type))
1,198,950✔
827
      return false;
828

829
   return mir_type_data(mu, type)->class == class;
1,157,182✔
830
}
831

832
bool mir_points_to(mir_unit_t *mu, mir_value_t value, mir_class_t class)
53,710✔
833
{
834
   mir_type_t type = mir_get_type(mu, value);
53,710✔
835
   if (mir_is_null(type))
53,710✔
836
      return false;
837

838
   const type_data_t *td = mir_type_data(mu, type);
53,710✔
839
   if (td->class != MIR_TYPE_POINTER)
53,710✔
840
      return false;
841

842
   return mir_type_data(mu, td->u.pointer)->class == class;
53,374✔
843
}
844

845
bool mir_points_to_vector(mir_unit_t *mu, mir_value_t value)
688✔
846
{
847
   mir_type_t type = mir_get_type(mu, value);
688✔
848
   if (mir_is_null(type))
688✔
849
      return false;
850

851
   const type_data_t *td = mir_type_data(mu, type);
688✔
852
   if (td->class != MIR_TYPE_POINTER)
688✔
853
      return false;
854

855
   switch (mir_type_data(mu, td->u.pointer)->class) {
72✔
856
   case MIR_TYPE_VEC2:
857
   case MIR_TYPE_VEC4:
858
      return true;
859
   default:
×
860
      return false;
×
861
   }
862
}
863

864
bool mir_is_signal(mir_unit_t *mu, mir_value_t value)
206,538✔
865
{
866
   return mir_is(mu, value, MIR_TYPE_SIGNAL);
206,538✔
867
}
868

869
bool mir_is_offset(mir_unit_t *mu, mir_value_t value)
284,965✔
870
{
871
   if (value.tag == MIR_TAG_CONST)
284,965✔
872
      return true;
873

874
   return mir_is(mu, value, MIR_TYPE_OFFSET);
62,340✔
875
}
876

877
bool mir_is_const(mir_unit_t *mu, mir_value_t value)
2,980,804✔
878
{
879
   switch (value.tag) {
2,980,804✔
880
   case MIR_TAG_CONST:
881
      return true;
882
   case MIR_TAG_NODE:
22,640✔
883
      {
884
         node_data_t *n = mir_node_data(mu, value);
22,640✔
885
         switch (n->op) {
22,640✔
886
         case MIR_OP_CONST:
887
         case MIR_OP_CONST_REAL:
888
         case MIR_OP_CONST_ARRAY:
889
         case MIR_OP_CONST_REP:
890
         case MIR_OP_CONST_RECORD:
891
         case MIR_OP_NULL:
892
            return true;
893
         default:
×
894
            return false;
×
895
         }
896
      }
897
   default:
×
898
      return false;
×
899
   }
900
}
901

902
bool mir_may_alias(mir_unit_t *mu, mir_value_t a, mir_value_t b)
5✔
903
{
904
   const mir_mem_t a_mem = mir_get_mem(mu, a);
5✔
905
   if (a_mem == MIR_MEM_NONE)
5✔
906
      return false;
907

908
   if (mir_equals(a, b))
5✔
909
      return true;
910

911
   const mir_mem_t b_mem = mir_get_mem(mu, b);
5✔
912
   if (b_mem == MIR_MEM_NONE)
5✔
913
      return false;
914

915
   if (a_mem == MIR_MEM_CONST || b_mem == MIR_MEM_CONST) {
5✔
916
      // Aliasing is only relevant in the presence of mutability
917
      return false;
918
   }
919

920
   return a_mem == b_mem || a_mem == MIR_MEM_TOP || b_mem == MIR_MEM_TOP;
3✔
921
}
922

923
#ifdef DEBUG
924
static bool mir_check_type(mir_unit_t *mu, mir_value_t value, mir_type_t type)
3,131,156✔
925
{
926
   if (value.tag == MIR_TAG_CONST) {
3,131,156✔
927
      const mir_class_t class = mir_type_data(mu, type)->class;
2,966,765✔
928
      return class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET;
2,966,765✔
929
   }
930
   else
931
      return mir_equals(mir_get_type(mu, value), type);
164,391✔
932
}
933
#endif
934

935
mir_value_t mir_enum(unsigned value)
432,396✔
936
{
937
   assert(value < MIR_ID_MAX);
432,396✔
938
   return (mir_value_t){ .tag = MIR_TAG_ENUM, .id = value };
432,396✔
939
}
940

941
mir_value_t mir_const(mir_unit_t *mu, mir_type_t type, int64_t value)
799,561✔
942
{
943
   mir_value_t result;
799,561✔
944
   if (value >= SMALL_CONST_MIN && value <= SMALL_CONST_MAX) {
799,561✔
945
      const unsigned biased = value + SMALL_CONST_BIAS;
789,148✔
946
      result = (mir_value_t){ .tag = MIR_TAG_CONST, .id = biased };
789,148✔
947
   }
948
   else {
949
      mir_stamp_t stamp = mir_int_stamp(mu, value, value);
10,413✔
950
      node_data_t *n = mir_add_node(mu, MIR_OP_CONST, type, stamp, 0);
10,413✔
951
      n->iconst = value;
10,413✔
952

953
      result = (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
10,413✔
954
   }
955

956
#ifdef DEBUG
957
   const mir_class_t class = mir_get_class(mu, type);
799,561✔
958
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET,
799,561✔
959
              "constant must have integral type");
960
#endif
961

962
   return result;
799,561✔
963
}
964

965
mir_value_t mir_const_real(mir_unit_t *mu, mir_type_t type, double value)
30,438✔
966
{
967
   mir_stamp_t stamp = mir_real_stamp(mu, value, value);
30,438✔
968
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_REAL, type, stamp, 0);
30,438✔
969
   n->dconst = value;
30,438✔
970

971
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
30,438✔
972
}
973

974
mir_value_t mir_const_vec(mir_unit_t *mu, mir_type_t type, uint64_t abits,
46,262✔
975
                          uint64_t bbits)
976
{
977
   uint64_t mask = ~UINT64_C(0), size = mir_get_size(mu, type);
46,262✔
978
   if (size == 0)
46,262✔
979
      mask = 0;
980
   else if (size < 64)
46,242✔
981
      mask >>= 64 - size;
45,682✔
982

983
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_VEC, type, MIR_NULL_STAMP, 0);
46,262✔
984
   n->bits[0] = abits & mask;
46,262✔
985
   n->bits[1] = bbits & mask;
46,262✔
986

987
#ifdef DEBUG
988
   const type_data_t *td = mir_type_data(mu, type);
46,262✔
989
   MIR_ASSERT(td->class == MIR_TYPE_VEC2 || td->class == MIR_TYPE_VEC4,
46,262✔
990
              "constant vector must have vector type");
991
   MIR_ASSERT(bbits == 0 || td->class == MIR_TYPE_VEC4,
46,262✔
992
              "b-bits cannot be set for two-value vector");
993
   MIR_ASSERT(size <= 64, "constant vector size must be 64 bits or less");
46,262✔
994
#endif
995

996
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
46,262✔
997
}
998

999
mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
50,754✔
1000
                            const mir_value_t *values, size_t count)
1001
{
1002
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
101,508✔
1003
                                 MIR_NULL_STAMP, count);
50,754✔
1004

1005
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
50,754✔
1006
              "constant array must have constrained array type");
1007
   MIR_ASSERT(mir_get_size(mu, type) == count, "expected %d elements but "
50,754✔
1008
              "have %zd", mir_get_size(mu, type), count);
1009

1010
   mir_type_t elem = mir_get_elem(mu, type);
50,754✔
1011

1012
   const bool integral = mir_get_class(mu, elem) == MIR_TYPE_INT;
50,754✔
1013
   int64_t low = INT64_MAX, high = INT64_MIN;
50,754✔
1014
   for (size_t i = 0; i < count; i++) {
3,011,676✔
1015
      mir_set_arg(mu, n, i, values[i]);
2,960,922✔
1016

1017
      MIR_ASSERT(mir_check_type(mu, values[i], elem),
2,960,922✔
1018
                 "element %zd has wrong type", i);
1019
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %zd not const", i);
2,960,922✔
1020

1021
      int64_t cval;
2,960,922✔
1022
      if (integral && mir_get_const(mu, values[i], &cval)) {
2,960,922✔
1023
         low = MIN(low, cval);
2,939,225✔
1024
         high = MAX(high, cval);
2,939,225✔
1025
      }
1026
   }
1027

1028
   mir_stamp_t stamp = MIR_NULL_STAMP;
50,754✔
1029
   if (integral && low <= high)
50,754✔
1030
      stamp = mir_int_stamp(mu, low, high);
49,834✔
1031

1032
   n->stamp = mir_pointer_stamp(mu, MIR_MEM_CONST, stamp);
50,754✔
1033

1034
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
50,754✔
1035
}
1036

1037
mir_value_t mir_const_string(mir_unit_t *mu, const char *str)
5,075✔
1038
{
1039
   int count = 0, low = UINT8_MAX, high = 0;
5,075✔
1040
   for (const char *p = str; *p; p++, count++) {
24,717✔
1041
      low = MIN(low, (unsigned char)*p);
19,642✔
1042
      high = MAX(high, (unsigned char)*p);
19,642✔
1043
   }
1044

1045
   mir_type_t t_char = mir_char_type(mu);
5,075✔
1046
   mir_type_t type = mir_carray_type(mu, count, t_char);
5,075✔
1047
   mir_stamp_t stamp = mir_int_stamp(mu, low, high);
5,075✔
1048

1049
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
5,075✔
1050
                                 stamp, count);
1051

1052
   for (int i = 0; i < count; i++)
24,717✔
1053
      mir_set_arg(mu, n, i, mir_const(mu, t_char, (unsigned char)str[i]));
19,642✔
1054

1055
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
5,075✔
1056
}
1057

1058
mir_value_t mir_build_const_rep(mir_unit_t *mu, mir_type_t type,
411✔
1059
                                mir_value_t value, unsigned rep)
1060
{
1061
   mir_stamp_t stamp = mir_get_stamp(mu, value);
411✔
1062
   mir_value_t result = mir_build_2(mu, MIR_OP_CONST_REP, type, stamp,
411✔
1063
                                    value, mir_enum(rep));
1064

1065
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
411✔
1066
              "constant array must have constrained array class");
1067
   MIR_ASSERT(rep < MIR_ID_MAX, "repetitions out of range");
411✔
1068

1069
   return result;
411✔
1070
}
1071

1072
mir_value_t mir_const_record(mir_unit_t *mu, mir_type_t type,
2,907✔
1073
                             const mir_value_t *values, size_t count)
1074
{
1075
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_RECORD, type,
5,814✔
1076
                                 MIR_NULL_STAMP, count);
2,907✔
1077

1078
   DEBUG_ONLY(const type_data_t *td = mir_type_data(mu, type));
2,907✔
1079

1080
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
2,907✔
1081
              "const record must have record type");
1082
   MIR_ASSERT(td->u.record.count == count, "expected %u fields but have %zu",
2,907✔
1083
              td->u.record.count, count);
1084

1085
   for (int i = 0; i < count; i++) {
10,531✔
1086
      mir_set_arg(mu, n, i, values[i]);
7,624✔
1087

1088
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, values[i]),
7,624✔
1089
                               td->u.record.fields[i]),
1090
                 "wrong type for element %d", i);
1091
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %d is not constant", i);
7,624✔
1092
   }
1093

1094
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,907✔
1095
}
1096

1097
static mir_value_t mir_build_arith(mir_unit_t *mu, mir_op_t op, mir_type_t type,
77,485✔
1098
                                   mir_value_t left, mir_value_t right,
1099
                                   mir_value_t locus, mir_stamp_t stamp)
1100
{
1101
   mir_value_t result;
77,485✔
1102
   if (mir_is_null(locus))
77,485✔
1103
      result = mir_build_2(mu, op, type, stamp, left, right);
67,412✔
1104
   else
1105
      result = mir_build_3(mu, op, type, stamp, left, right, locus);
10,073✔
1106

1107
#ifdef DEBUG
1108
   switch (mir_get_class(mu, type)) {
77,485✔
1109
   case MIR_TYPE_INT:
77,483✔
1110
   case MIR_TYPE_REAL:
1111
   case MIR_TYPE_OFFSET:
1112
      {
1113
         mir_type_t ltype = mir_get_type(mu, left);
77,483✔
1114
         mir_type_t rtype = mir_get_type(mu, right);
77,483✔
1115

1116
         MIR_ASSERT(mir_is_null(ltype) || mir_is_null(rtype)
77,483✔
1117
                    || mir_equals(ltype, rtype),
1118
                    "arguments to %s are not the same type", mir_op_string(op));
1119
      }
1120
      break;
1121

1122
   case MIR_TYPE_VEC2:
2✔
1123
   case MIR_TYPE_VEC4:
1124
      {
1125
         const type_data_t *td = mir_type_data(mu, type);
2✔
1126
         const type_data_t *ltd = mir_type_data(mu, mir_get_type(mu, left));
2✔
1127
         const type_data_t *rtd = mir_type_data(mu, mir_get_type(mu, right));
2✔
1128

1129
         MIR_ASSERT(td->class == ltd->class && td->class == rtd->class,
2✔
1130
                    "cannot mix vector types");
1131
         MIR_ASSERT(td->u.vec.issigned == ltd->u.vec.issigned
2✔
1132
                    && td->u.vec.issigned == rtd->u.vec.issigned,
1133
                    "cannot mix vector signedness");
1134
         MIR_ASSERT(td->u.vec.size >= ltd->u.vec.size
2✔
1135
                    && td->u.vec.size >= rtd->u.vec.size,
1136
                    "implicit narrowing conversions are not allowed");
1137
      }
1138
      break;
1139

1140
   default:
1141
      MIR_ASSERT(false, "arithmetic is not allowed on this type");
×
1142
      break;
1143
   }
1144

1145
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
77,485✔
1146
              "locus argument to %s is not a locus", mir_op_string(op));
1147
#endif
1148

1149
   return result;
77,485✔
1150
}
1151

1152
static mir_value_t mir_build_add_op(mir_unit_t *mu, mir_op_t op,
46,878✔
1153
                                    mir_type_t type, mir_value_t left,
1154
                                    mir_value_t right, mir_value_t locus)
1155
{
1156
   int64_t lval, rval, cval;
46,878✔
1157
   const bool lconst = mir_get_const(mu, left, &lval);
46,878✔
1158
   const bool rconst = mir_get_const(mu, right, &rval);
46,878✔
1159

1160
   if (lconst && lval == 0)
46,878✔
1161
      return right;
17,429✔
1162
   else if (rconst && rval == 0)
29,449✔
1163
      return left;
117✔
1164
   else if (lconst && rconst && !__builtin_add_overflow(lval, rval, &cval))
29,332✔
1165
      return mir_const(mu, type, cval);
1,758✔
1166

1167
   double lreal, rreal;
27,574✔
1168
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
27,574✔
1169
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
27,574✔
1170

1171
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
27,574✔
1172
      return right;
1✔
1173
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
27,573✔
1174
      return left;
2✔
1175
   else if (lconst_real && rconst_real)
27,571✔
1176
      return mir_const_real(mu, type, lreal + rreal);
5✔
1177

1178
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
27,566✔
1179
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
27,566✔
1180
   mir_stamp_t stamp = mir_stamp_add(mu, lstamp, rstamp);
27,566✔
1181

1182
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
27,566✔
1183
}
1184

1185
mir_value_t mir_build_add(mir_unit_t *mu, mir_type_t type, mir_value_t left,
40,261✔
1186
                          mir_value_t right)
1187
{
1188
   return mir_build_add_op(mu, MIR_OP_ADD, type, left, right, MIR_NULL_VALUE);
40,261✔
1189
}
1190

1191
mir_value_t mir_build_trap_add(mir_unit_t *mu, mir_type_t type,
6,617✔
1192
                               mir_value_t left, mir_value_t right,
1193
                               mir_value_t locus)
1194
{
1195
   return mir_build_add_op(mu, MIR_OP_TRAP_ADD, type, left, right, locus);
6,617✔
1196
}
1197

1198
static mir_value_t mir_build_sub_op(mir_unit_t *mu, mir_op_t op,
49,810✔
1199
                                    mir_type_t type, mir_value_t left,
1200
                                    mir_value_t right, mir_value_t locus)
1201
{
1202
   int64_t lval, rval, cval;
49,810✔
1203
   const bool lconst = mir_get_const(mu, left, &lval);
49,810✔
1204
   const bool rconst = mir_get_const(mu, right, &rval);
49,810✔
1205

1206
   if (lconst && lval == 0)
49,810✔
1207
      return mir_build_neg(mu, type, right);
1,467✔
1208
   else if (rconst && rval == 0)
48,343✔
1209
      return left;
2,407✔
1210
   else if (lconst && rconst && !__builtin_sub_overflow(lval, rval, &cval))
45,936✔
1211
      return mir_const(mu, type, cval);
6,254✔
1212
   else if (mir_equals(left, right))
39,682✔
1213
      return mir_get_class(mu, type) == MIR_TYPE_REAL
207✔
1214
         ? mir_const_real(mu, type, 0.0) : mir_const(mu, type, 0);
207✔
1215

1216
   double lreal, rreal;
39,475✔
1217
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
39,475✔
1218
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
39,475✔
1219

1220
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
39,475✔
1221
      return right;
×
1222
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
39,475✔
1223
      return left;
5✔
1224
   else if (lconst_real && rconst_real)
39,470✔
1225
      return mir_const_real(mu, type, lreal - rreal);
×
1226

1227
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
39,470✔
1228
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
39,470✔
1229
   mir_stamp_t stamp = mir_stamp_sub(mu, lstamp, rstamp);
39,470✔
1230

1231
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
39,470✔
1232
}
1233

1234
mir_value_t mir_build_sub(mir_unit_t *mu, mir_type_t type, mir_value_t left,
47,940✔
1235
                          mir_value_t right)
1236
{
1237
   return mir_build_sub_op(mu, MIR_OP_SUB, type, left, right, MIR_NULL_VALUE);
47,940✔
1238
}
1239

1240
mir_value_t mir_build_trap_sub(mir_unit_t *mu, mir_type_t type,
1,870✔
1241
                               mir_value_t left, mir_value_t right,
1242
                               mir_value_t locus)
1243
{
1244
   return mir_build_sub_op(mu, MIR_OP_TRAP_SUB, type, left, right, locus);
1,870✔
1245
}
1246

1247
mir_value_t mir_build_neg(mir_unit_t *mu, mir_type_t type, mir_value_t value)
10,288✔
1248
{
1249
   int64_t cval;
10,288✔
1250
   if (mir_get_const(mu, value, &cval))
10,288✔
1251
      return mir_const(mu, type, -cval);
1,463✔
1252

1253
   mir_value_t result = mir_build_1(mu, MIR_OP_NEG, type,
8,825✔
1254
                                    MIR_NULL_STAMP, value);
8,825✔
1255

1256
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
8,825✔
1257

1258
   return result;
8,825✔
1259
}
1260

1261
mir_value_t mir_build_trap_neg(mir_unit_t *mu, mir_type_t type,
338✔
1262
                               mir_value_t value, mir_value_t locus)
1263
{
1264
   int64_t cval;
338✔
1265
   if (mir_get_const(mu, value, &cval) && cval >= 0)
338✔
1266
      return mir_const(mu, type, -cval);
×
1267
   // TODO: check if stamp bounds are non-negative
1268

1269
   mir_value_t result = mir_build_2(mu, MIR_OP_TRAP_NEG, type,
338✔
1270
                                    MIR_NULL_STAMP, value, locus);
338✔
1271

1272
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
338✔
1273
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
338✔
1274
              "locus argument must be debug locus");
1275

1276
   return result;
338✔
1277
}
1278

1279
mir_value_t mir_build_abs(mir_unit_t *mu, mir_type_t type, mir_value_t value)
893✔
1280
{
1281
   int64_t lconst;
893✔
1282
   if (mir_get_const(mu, value, &lconst))
893✔
1283
      return mir_const(mu, type, llabs(lconst));
×
1284

1285
   mir_value_t result = mir_build_1(mu, MIR_OP_ABS, type, MIR_NULL_STAMP,
893✔
1286
                                    value);
1287

1288
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
893✔
1289

1290
   return result;
893✔
1291
}
1292

1293
static mir_value_t mir_build_mul_op(mir_unit_t *mu, mir_op_t op,
7,453✔
1294
                                    mir_type_t type, mir_value_t left,
1295
                                    mir_value_t right, mir_value_t locus)
1296
{
1297
   int64_t lval, rval, cval;
7,453✔
1298
   const bool lconst = mir_get_const(mu, left, &lval);
7,453✔
1299
   const bool rconst = mir_get_const(mu, right, &rval);
7,453✔
1300

1301
   if (lconst && lval == 0)
7,453✔
1302
      return left;
80✔
1303
   else if (rconst && rval == 0)
7,373✔
1304
      return right;
×
1305
   else if (lconst && lval == 1)
7,373✔
1306
      return right;
1,152✔
1307
   else if (rconst && rval == 1)
6,221✔
1308
      return left;
9✔
1309
   else if (lconst && rconst && !__builtin_mul_overflow(lval, rval, &cval))
6,212✔
1310
      return mir_const(mu, type, cval);
132✔
1311

1312
   double lreal, rreal;
6,080✔
1313
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
6,080✔
1314
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
6,080✔
1315

1316
   if (lconst_real && rconst_real)
6,080✔
1317
      return mir_const_real(mu, type, lreal * rreal);
192✔
1318

1319
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
5,888✔
1320
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
5,888✔
1321
   mir_stamp_t stamp = mir_stamp_mul(mu, lstamp, rstamp);
5,888✔
1322

1323
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
5,888✔
1324
}
1325

1326
mir_value_t mir_build_mul(mir_unit_t *mu, mir_type_t type, mir_value_t left,
6,033✔
1327
                          mir_value_t right)
1328
{
1329
   return mir_build_mul_op(mu, MIR_OP_MUL, type, left, right, MIR_NULL_VALUE);
6,033✔
1330
}
1331

1332
mir_value_t mir_build_trap_mul(mir_unit_t *mu, mir_type_t type,
1,420✔
1333
                               mir_value_t left, mir_value_t right,
1334
                               mir_value_t locus)
1335
{
1336
   return mir_build_mul_op(mu, MIR_OP_TRAP_MUL, type, left, right, locus);
1,420✔
1337
}
1338

1339
mir_value_t mir_build_div(mir_unit_t *mu, mir_type_t type, mir_value_t left,
2,476✔
1340
                          mir_value_t right)
1341
{
1342
   int64_t lval, rval;
2,476✔
1343
   const bool lconst = mir_get_const(mu, left, &lval);
2,476✔
1344
   const bool rconst = mir_get_const(mu, right, &rval);
2,476✔
1345

1346
   if (lconst && rconst && rval != 0)
2,476✔
1347
      return mir_const(mu, type, lval / rval);
×
1348
   else if (rconst && rval == 1)
2,476✔
1349
      return left;
×
1350

1351
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
2,476✔
1352
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
2,476✔
1353
   mir_stamp_t stamp = mir_stamp_div(mu, lstamp, rstamp);
2,476✔
1354

1355
   return mir_build_arith(mu, MIR_OP_DIV, type, left, right,
2,476✔
1356
                          MIR_NULL_VALUE, stamp);
2,476✔
1357
}
1358

1359
mir_value_t mir_build_rem(mir_unit_t *mu, mir_type_t type, mir_value_t left,
1,571✔
1360
                          mir_value_t right)
1361
{
1362
   int64_t lval, rval;
1,571✔
1363
   const bool lconst = mir_get_const(mu, left, &lval);
1,571✔
1364
   const bool rconst = mir_get_const(mu, right, &rval);
1,571✔
1365

1366
   if (lconst && rconst && lval > 0 && rval > 0)
1,571✔
1367
      return mir_const(mu, type, lval % rval);
1✔
1368

1369
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
1,570✔
1370
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
1,570✔
1371
   mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
1,570✔
1372

1373
   return mir_build_arith(mu, MIR_OP_REM, type, left, right,
1,570✔
1374
                          MIR_NULL_VALUE, stamp);
1,570✔
1375
}
1376

1377
mir_value_t mir_build_mod(mir_unit_t *mu, mir_type_t type, mir_value_t left,
168✔
1378
                          mir_value_t right)
1379
{
1380
   int64_t lval, rval;
168✔
1381
   const bool lconst = mir_get_const(mu, left, &lval);
168✔
1382
   const bool rconst = mir_get_const(mu, right, &rval);
168✔
1383

1384
   if (lconst && rconst && lval > 0 && rval > 0)
168✔
1385
      return mir_const(mu, type, lval % rval);
×
1386

1387
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
168✔
1388
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
168✔
1389

1390
   if (!mir_is_null(lstamp) && !mir_is_null(rstamp)) {
168✔
1391
      const stamp_data_t *lsd = mir_stamp_data(mu, lstamp);
16✔
1392
      const stamp_data_t *rsd = mir_stamp_data(mu, rstamp);
16✔
1393

1394
      if (lsd->u.intg.low >= 0 && rsd->u.intg.low >= 0) {
16✔
1395
         // If both arguments are non-negative then rem is equivalent
1396
         // and cheaper to compute
1397
         mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
1✔
1398
         return mir_build_arith(mu, MIR_OP_REM, type, left, right,
1✔
1399
                                MIR_NULL_VALUE, stamp);
1✔
1400
      }
1401
   }
1402

1403
   return mir_build_arith(mu, MIR_OP_MOD, type, left, right,
167✔
1404
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
167✔
1405
}
1406

1407
mir_value_t mir_build_exp(mir_unit_t *mu, mir_type_t type, mir_value_t left,
181✔
1408
                          mir_value_t right)
1409
{
1410
   return mir_build_arith(mu, MIR_OP_EXP, type, left, right,
362✔
1411
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
181✔
1412
}
1413

1414
mir_value_t mir_build_trap_exp(mir_unit_t *mu, mir_type_t type,
166✔
1415
                               mir_value_t left, mir_value_t right,
1416
                               mir_value_t locus)
1417
{
1418
   int64_t rconst;
166✔
1419
   if (mir_get_const(mu, right, &rconst)) {
166✔
1420
      if (rconst == 0)
61✔
1421
         return mir_const(mu, type, 1);
×
1422
      else if (rconst == 1)
61✔
1423
         return left;
×
1424
   }
1425

1426
   mir_value_t result = mir_build_arith(mu, MIR_OP_TRAP_EXP, type, left, right,
166✔
1427
                                        locus, MIR_NULL_STAMP);
166✔
1428

1429
   MIR_ASSERT(mir_is_integral(mu, result),
166✔
1430
              "trapping exp may only be used with integer types");
1431

1432
   return result;
166✔
1433
}
1434

1435
static mir_value_t mir_build_logical(mir_unit_t *mu, mir_op_t op,
9,710✔
1436
                                     mir_type_t type, mir_value_t left,
1437
                                     mir_value_t right)
1438
{
1439
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP, left, right);
9,710✔
1440

1441
   MIR_ASSERT(mir_is_bool(mu, left), "left argument to %s is not bool",
9,710✔
1442
              mir_op_string(op));
1443
   MIR_ASSERT(mir_is_bool(mu, right), "right argument to %s is not bool",
9,710✔
1444
              mir_op_string(op));
1445

1446
   return result;
9,710✔
1447
}
1448

1449
mir_value_t mir_build_and(mir_unit_t *mu, mir_value_t left, mir_value_t right)
11,116✔
1450
{
1451
   int64_t lval, rval;
11,116✔
1452
   const bool lconst = mir_get_const(mu, left, &lval);
11,116✔
1453
   const bool rconst = mir_get_const(mu, right, &rval);
11,116✔
1454

1455
   mir_type_t t_bool = mir_bool_type(mu);
11,116✔
1456

1457
   if (lconst && rconst)
11,116✔
1458
      return mir_const(mu, t_bool, lval && rval);
3,313✔
1459
   else if (lconst)
8,099✔
1460
      return lval ? right : mir_const(mu, t_bool, 0);
1,263✔
1461
   else if (rconst)
6,836✔
1462
      return rval ? left : mir_const(mu, t_bool, 0);
2✔
1463

1464
   return mir_build_logical(mu, MIR_OP_AND, t_bool, left, right);
6,834✔
1465
}
1466

1467
mir_value_t mir_build_or(mir_unit_t *mu, mir_value_t left, mir_value_t right)
2,723✔
1468
{
1469
   int64_t lval, rval;
2,723✔
1470
   const bool lconst = mir_get_const(mu, left, &lval);
2,723✔
1471
   const bool rconst = mir_get_const(mu, right, &rval);
2,723✔
1472

1473
   mir_type_t t_bool = mir_bool_type(mu);
2,723✔
1474

1475
   if (lconst && rconst)
2,723✔
1476
      return mir_const(mu, t_bool, lval || rval);
3✔
1477
   else if (lconst)
2,721✔
1478
      return lval ? mir_const(mu, t_bool, 1) : right;
1✔
1479
   else if (rconst)
2,720✔
1480
      return rval ? mir_const(mu, t_bool, 1) : left;
1✔
1481

1482
   return mir_build_logical(mu, MIR_OP_OR, t_bool, left, right);
2,719✔
1483
}
1484

1485
mir_value_t mir_build_xor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
159✔
1486
{
1487
   int64_t lval, rval;
159✔
1488
   const bool lconst = mir_get_const(mu, left, &lval);
159✔
1489
   const bool rconst = mir_get_const(mu, right, &rval);
159✔
1490

1491
   mir_type_t t_bool = mir_bool_type(mu);
159✔
1492
   if (lconst && rconst)
159✔
1493
      return mir_const(mu, t_bool, lval ^ rval);
1✔
1494
   else if (mir_equals(left, right))
158✔
1495
      return mir_const(mu, t_bool, 0);
1✔
1496

1497
   return mir_build_logical(mu, MIR_OP_XOR, t_bool, left, right);
157✔
1498
}
1499

1500
mir_value_t mir_build_not(mir_unit_t *mu, mir_value_t value)
4,076✔
1501
{
1502
   mir_type_t t_bool = mir_bool_type(mu);
4,076✔
1503

1504
   int64_t cval;
4,076✔
1505
   if (mir_get_const(mu, value, &cval))
4,076✔
1506
      return mir_const(mu, t_bool, !cval);
2✔
1507

1508
   if (mir_get_op(mu, value) == MIR_OP_NOT)
4,074✔
1509
      return mir_get_arg(mu, value, 0);
81✔
1510

1511
   mir_value_t result = mir_build_1(mu, MIR_OP_NOT, t_bool,
3,993✔
1512
                                    MIR_NULL_STAMP, value);
3,993✔
1513

1514
   MIR_ASSERT(mir_is_bool(mu, value), "argument to not is not bool");
3,993✔
1515

1516
   return result;
3,993✔
1517
}
1518

1519
mir_value_t mir_build_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_value_t left,
60,880✔
1520
                          mir_value_t right)
1521
{
1522
   int64_t lval, rval;
60,880✔
1523
   const bool lconst = mir_get_const(mu, left, &lval);
60,880✔
1524
   const bool rconst = mir_get_const(mu, right, &rval);
60,880✔
1525

1526
   mir_type_t t_bool = mir_bool_type(mu);
60,880✔
1527

1528
   if (lconst && rconst) {
60,880✔
1529
      switch (cmp) {
9,425✔
1530
      case MIR_CMP_EQ:  return mir_const(mu, t_bool, lval == rval);
3✔
1531
      case MIR_CMP_NEQ: return mir_const(mu, t_bool, lval != rval);
1,195✔
1532
      case MIR_CMP_LT:  return mir_const(mu, t_bool, lval < rval);
3,082✔
1533
      case MIR_CMP_GT:  return mir_const(mu, t_bool, lval > rval);
4,136✔
1534
      case MIR_CMP_GEQ: return mir_const(mu, t_bool, lval >= rval);
1,007✔
1535
      case MIR_CMP_LEQ: return mir_const(mu, t_bool, lval <= rval);
2✔
1536
      default: should_not_reach_here();
1537
      }
1538
   }
1539

1540
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
51,455✔
1541
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
51,455✔
1542
   mir_stamp_t stamp = mir_stamp_cmp(mu, cmp, lstamp, rstamp);
51,455✔
1543

1544
   int64_t sconst;
51,455✔
1545
   if (mir_stamp_const(mu, stamp, &sconst))
51,455✔
1546
      return mir_const(mu, t_bool, sconst);
35✔
1547

1548
   mir_value_t result = mir_build_3(mu, MIR_OP_CMP, t_bool,
51,420✔
1549
                                    stamp, mir_enum(cmp), left, right);
1550

1551
#ifdef DEBUG
1552
   mir_type_t type = mir_get_type(mu, left);
51,420✔
1553
   MIR_ASSERT(mir_same_type(mu, type, mir_get_type(mu, right)),
51,420✔
1554
              "arguments to cmp are not the same type");
1555
   MIR_ASSERT(mir_is_scalar(mu, left), "cmp arguments must be scalar");
51,420✔
1556
   MIR_ASSERT(mir_get_slots(mu, type) == 1,
51,420✔
1557
              "can only compare single slot types");
1558
#endif
1559

1560
   return result;
51,420✔
1561
}
1562

1563
mir_value_t mir_build_pack(mir_unit_t *mu, mir_type_t type, mir_value_t arg)
20,141✔
1564
{
1565
   mir_value_t result = mir_build_1(mu, MIR_OP_PACK, type, MIR_NULL_STAMP, arg);
20,141✔
1566

1567
#ifdef DEBUG
1568
   const mir_class_t class = mir_get_class(mu, type);
20,141✔
1569
   MIR_ASSERT(class == MIR_TYPE_VEC2 || class == MIR_TYPE_VEC4,
20,141✔
1570
              "pack type must be vector");
1571
   MIR_ASSERT(mir_is(mu, arg, MIR_TYPE_POINTER)
20,141✔
1572
              || (mir_get_size(mu, type) == 1 && mir_is_integral(mu, arg)),
1573
              "pack argument must be pointer if size != 1");
1574
#endif
1575

1576
   return result;
20,141✔
1577
}
1578

1579
mir_value_t mir_build_unpack(mir_unit_t *mu, mir_value_t vec, uint8_t strength,
13,043✔
1580
                             mir_value_t dest)
1581
{
1582
   mir_value_t result = dest;
13,043✔
1583
   if (mir_is_null(dest))
13,043✔
1584
      result = mir_build_2(mu, MIR_OP_UNPACK, mir_logic_type(mu),
6,508✔
1585
                           MIR_NULL_STAMP, vec, mir_enum(strength));
3,254✔
1586
   else
1587
      mir_build_3(mu, MIR_OP_UNPACK, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,789✔
1588
                  vec, mir_enum(strength), dest);
1589

1590
   MIR_ASSERT(mir_is_vector(mu, vec), "unpack argument must be vector");
13,043✔
1591
   MIR_ASSERT(mir_is_null(dest) || mir_points_to(mu, dest, MIR_TYPE_INT),
13,043✔
1592
              "unpack dest must be pointer to logic or null");
1593
   MIR_ASSERT(mir_get_size(mu, mir_get_type(mu, vec)) == 1
13,043✔
1594
              || !mir_is_null(dest),
1595
              "unpack dest must be non-null if wide vector");
1596
   MIR_ASSERT((strength & 3) == 0, "strength lower bits must be zero");
13,043✔
1597

1598
   return result;
13,043✔
1599
}
1600

1601
mir_value_t mir_build_binary(mir_unit_t *mu, mir_vec_op_t op, mir_type_t type,
27,071✔
1602
                             mir_value_t left, mir_value_t right)
1603
{
1604
   mir_type_t otype;
27,071✔
1605
   switch (op) {
27,071✔
1606
   case MIR_VEC_CASE_EQ:
17,477✔
1607
   case MIR_VEC_CASE_NEQ:
1608
   case MIR_VEC_CASEX_EQ:
1609
   case MIR_VEC_CASEZ_EQ:
1610
   case MIR_VEC_LOG_AND:
1611
   case MIR_VEC_LOG_OR:
1612
      // XXX: these should be vec2
1613
   case MIR_VEC_LT:
1614
   case MIR_VEC_LEQ:
1615
   case MIR_VEC_GT:
1616
   case MIR_VEC_GEQ:
1617
   case MIR_VEC_LOG_EQ:
1618
   case MIR_VEC_LOG_NEQ:
1619
      otype = mir_vec4_type(mu, 1, false);
17,477✔
1620
      break;
17,477✔
1621
   default:
9,594✔
1622
      otype = type;
9,594✔
1623
   }
1624

1625
   mir_value_t result = mir_build_3(mu, MIR_OP_BINARY, otype, MIR_NULL_STAMP,
27,071✔
1626
                                    mir_enum(op), left, right);
1627

1628
   MIR_ASSERT(mir_is_vector(mu, result), "binary operation must be vector");
27,071✔
1629
   MIR_ASSERT(mir_is_vector(mu, left), "left argument must be vector");
27,071✔
1630
   MIR_ASSERT(mir_is_vector(mu, right), "right argument must be vector");
27,071✔
1631
   MIR_ASSERT(mir_check_type(mu, left, type), "left type does not match");
27,071✔
1632
   MIR_ASSERT(mir_check_type(mu, right, type), "right type does not match");
27,071✔
1633

1634
   return result;
27,071✔
1635
}
1636

1637
mir_value_t mir_build_unary(mir_unit_t *mu, mir_vec_op_t op, mir_type_t type,
6,689✔
1638
                            mir_value_t arg)
1639
{
1640
   mir_type_t otype;
6,689✔
1641
   switch (op) {
6,689✔
1642
   case MIR_VEC_LOG_NOT:
4,481✔
1643
   case MIR_VEC_BIT_AND:
1644
   case MIR_VEC_BIT_OR:
1645
   case MIR_VEC_BIT_XOR:
1646
      if (mir_get_class(mu, type) == MIR_TYPE_VEC4)
4,481✔
1647
         otype = mir_vec4_type(mu, 1, false);
4,273✔
1648
      else
1649
         otype = mir_vec2_type(mu, 1, false);
208✔
1650
      break;
1651
   default:
2,208✔
1652
      otype = type;
2,208✔
1653
   }
1654

1655
   mir_value_t result = mir_build_2(mu, MIR_OP_UNARY, otype, MIR_NULL_STAMP,
6,689✔
1656
                                    mir_enum(op), arg);
1657

1658
   MIR_ASSERT(mir_is_vector(mu, result), "unary operation must be vector");
6,689✔
1659
   MIR_ASSERT(mir_is_vector(mu, arg), "argument must be vector");
6,689✔
1660
   MIR_ASSERT(mir_check_type(mu, arg, type), "arg type does not match");
6,689✔
1661

1662
   return result;
6,689✔
1663
}
1664

1665
mir_value_t mir_build_insert(mir_unit_t *mu, mir_value_t part, mir_value_t full,
4,260✔
1666
                             mir_value_t pos)
1667
{
1668
   mir_type_t type = mir_get_type(mu, full);
4,260✔
1669
   mir_value_t result = mir_build_3(mu, MIR_OP_INSERT, type, MIR_NULL_STAMP,
4,260✔
1670
                                    part, full, pos);
1671

1672
   MIR_ASSERT(mir_is_vector(mu, full), "full argument must be vector");
4,260✔
1673
   MIR_ASSERT(mir_is_vector(mu, part), "part argument must be vector");
4,260✔
1674

1675
#ifdef DEBUG
1676
   mir_type_t part_type = mir_get_type(mu, part);
4,260✔
1677
   MIR_ASSERT(mir_get_size(mu, part_type) <= mir_get_size(mu, type),
4,260✔
1678
              "out of bounds insert");
1679
   MIR_ASSERT(mir_get_class(mu, part_type) == mir_get_class(mu, type),
4,260✔
1680
              "mismatched vector types");
1681
#endif
1682

1683
   return result;
4,260✔
1684
}
1685

1686
mir_value_t mir_build_extract(mir_unit_t *mu, mir_type_t type, mir_value_t full,
1,339✔
1687
                              mir_value_t pos)
1688
{
1689
   mir_value_t result = mir_build_2(mu, MIR_OP_EXTRACT, type, MIR_NULL_STAMP,
1,339✔
1690
                                    full, pos);
1691

1692
   mir_type_t full_type = mir_get_type(mu, full);
1,339✔
1693
   if (mir_equals(type, full_type)) {
1,339✔
1694
      int64_t pos_const;
1,027✔
1695
      if (mir_get_const(mu, pos, &pos_const) && pos_const == 0)
1,027✔
1696
         return full;
1,027✔
1697
   }
1698

1699
   MIR_ASSERT(mir_is_vector(mu, full), "extract argument must be vector");
312✔
1700
   MIR_ASSERT(mir_is_offset(mu, pos), "extract position must be offset");
312✔
1701
   MIR_ASSERT(mir_get_class(mu, full_type) == mir_get_class(mu, type),
312✔
1702
              "mismatched vector types");
1703

1704
   return result;
312✔
1705
}
1706

1707
mir_value_t mir_build_test(mir_unit_t *mu, mir_value_t vec)
3,609✔
1708
{
1709
   mir_value_t result = mir_build_1(mu, MIR_OP_TEST, mir_bool_type(mu),
3,609✔
1710
                                    MIR_NULL_STAMP, vec);
3,609✔
1711

1712
   MIR_ASSERT(mir_is_vector(mu, vec), "argument must be vector");
3,609✔
1713

1714
   return result;
3,609✔
1715
}
1716

1717
mir_value_t mir_build_defined(mir_unit_t *mu, mir_value_t vec)
2,773✔
1718
{
1719
   mir_type_t t_bool = mir_bool_type(mu);
2,773✔
1720

1721
   const mir_class_t class = mir_get_class(mu, mir_get_type(mu, vec));
2,773✔
1722
   if (class == MIR_TYPE_VEC2)
2,773✔
1723
      return mir_const(mu, t_bool, 1);
×
1724

1725
   if (vec.tag == MIR_TAG_NODE) {
2,773✔
1726
      const node_data_t *n = mir_node_data(mu, vec);
2,773✔
1727
      if (n->op == MIR_OP_CONST_VEC)
2,773✔
1728
         return mir_const(mu, t_bool, n->bits[1] == 0);
2,469✔
1729
   }
1730

1731
   mir_value_t result = mir_build_1(mu, MIR_OP_DEFINED, t_bool,
304✔
1732
                                    MIR_NULL_STAMP, vec);
304✔
1733

1734
   MIR_ASSERT(class == MIR_TYPE_VEC4, "argument must be 4-state vector");
304✔
1735

1736
   return result;
304✔
1737
}
1738

1739
void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
171,474✔
1740
{
1741
   mir_build_2(mu, MIR_OP_STORE, MIR_NULL_TYPE, MIR_NULL_STAMP, dest, src);
171,474✔
1742

1743
#ifdef DEBUG
1744
   mir_type_t type = mir_get_type(mu, dest);
171,474✔
1745
   mir_type_t pointed = mir_get_pointer(mu, type);
171,474✔
1746
#endif
1747

1748
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
171,474✔
1749
              "store destination is not a pointer or variable");
1750
   MIR_ASSERT(mir_same_type(mu, pointed, mir_get_type(mu, src)),
171,474✔
1751
              "source and destination have different types");
1752
}
171,474✔
1753

1754
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
221,275✔
1755
{
1756
   mir_type_t type = mir_get_type(mu, value);
221,275✔
1757
   mir_stamp_t stamp = mir_stamp_elem(mu, mir_get_stamp(mu, value));
221,275✔
1758
   mir_type_t pointed = mir_get_pointer(mu, type);
221,275✔
1759

1760
   mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);
221,275✔
1761

1762
   MIR_ASSERT(!mir_is_null(type), "cannot load this value");
221,275✔
1763
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
221,275✔
1764
              "argument to load is not a pointer or variable");
1765
   MIR_ASSERT(mir_is_scalar(mu, result), "cannot load non-scalar type");
221,275✔
1766
   MIR_ASSERT(mir_get_mem(mu, value) != MIR_MEM_NULL,
221,275✔
1767
              "null pointer dereference");
1768

1769
   return result;
221,275✔
1770
}
1771

1772
void mir_build_copy(mir_unit_t *mu, mir_value_t dest, mir_value_t src,
45,488✔
1773
                    mir_value_t count)
1774
{
1775
   int64_t cval;
45,488✔
1776
   if (!mir_is_null(count) && mir_get_const(mu, count, &cval) && cval == 0)
45,488✔
1777
      return;
239✔
1778
   else if (mir_equals(dest, src))
45,488✔
1779
      return;
1780

1781
   mir_type_t dtype = mir_get_type(mu, dest);
45,249✔
1782
   mir_type_t elem = mir_get_pointer(mu, dtype);
45,249✔
1783

1784
   if (mir_is_null(count))
45,249✔
1785
      mir_build_2(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src);
2,436✔
1786
   else
1787
      mir_build_3(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src, count);
42,813✔
1788

1789
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
45,249✔
1790
              "destination type is not a pointer");
1791
   MIR_ASSERT(mir_is(mu, src, MIR_TYPE_POINTER),
45,249✔
1792
              "source type is not a pointer");
1793
   MIR_ASSERT(mir_equals(mir_get_type(mu, src), dtype),
45,249✔
1794
              "source and destination types do not match");
1795
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
45,249✔
1796
              "count is not offset type");
1797
}
1798

1799
void mir_build_set(mir_unit_t *mu, mir_value_t dest, mir_value_t value,
7,444✔
1800
                   mir_value_t count)
1801
{
1802
   int64_t cval;
7,444✔
1803
   if (mir_get_const(mu, count, &cval) && cval == 0)
7,444✔
1804
      return;
×
1805

1806
   mir_type_t dtype = mir_get_type(mu, dest);
7,444✔
1807
   mir_type_t elem = mir_get_pointer(mu, dtype);
7,444✔
1808

1809
   mir_build_3(mu, MIR_OP_SET, elem, MIR_NULL_STAMP, dest, value, count);
7,444✔
1810

1811
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
7,444✔
1812
              "destination type is not a pointer");
1813
   MIR_ASSERT(mir_is_scalar(mu, value), "memset value must have scalar type");
7,444✔
1814
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
7,444✔
1815
}
1816

1817
mir_value_t mir_build_alloc(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
10,898✔
1818
                            mir_value_t count)
1819
{
1820
   mir_type_t ptr = mir_pointer_type(mu, type);
10,898✔
1821
   mir_value_t result = mir_build_1(mu, MIR_OP_ALLOC, ptr, stamp, count);
10,898✔
1822

1823
   MIR_ASSERT(mir_get_class(mu, type) != MIR_TYPE_CARRAY,
10,898✔
1824
              "alloc element type cannot be array");
1825
   MIR_ASSERT(mir_is_offset(mu, count), "count must be offset type");
10,898✔
1826

1827
   return result;
10,898✔
1828
}
1829

1830
mir_value_t mir_build_null(mir_unit_t *mu, mir_type_t type)
8,058✔
1831
{
1832
   mir_stamp_t stamp = mir_pointer_stamp(mu, MIR_MEM_NULL, MIR_NULL_STAMP);
8,058✔
1833
   mir_value_t result = mir_build_0(mu, MIR_OP_NULL, type, stamp);
8,058✔
1834

1835
#ifdef DEBUG
1836
   const mir_class_t class = mir_get_class(mu, type);
8,058✔
1837
   MIR_ASSERT(class == MIR_TYPE_POINTER || class == MIR_TYPE_FILE
8,058✔
1838
              || class == MIR_TYPE_ACCESS || class == MIR_TYPE_CONTEXT,
1839
              "null type must be file, access, context, or pointer");
1840
#endif
1841

1842
   return result;
8,058✔
1843
}
1844

1845
mir_value_t mir_build_new(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
893✔
1846
                          mir_value_t count)
1847
{
1848
   mir_type_t access = mir_access_type(mu, type);
893✔
1849

1850
   mir_value_t result;
893✔
1851
   if (mir_is_null(count))
893✔
1852
      result = mir_build_0(mu, MIR_OP_NEW, access, stamp);
118✔
1853
   else
1854
      result = mir_build_1(mu, MIR_OP_NEW, access, stamp, count);
775✔
1855

1856
#ifdef DEBUG
1857
   const mir_class_t class = mir_get_class(mu, type);
893✔
1858
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_RECORD
893✔
1859
              || class == MIR_TYPE_UARRAY || class == MIR_TYPE_ACCESS
1860
              || class == MIR_TYPE_REAL || class == MIR_TYPE_CONTEXT,
1861
              "new type must be int, real, record, access, or uarray");
1862
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
893✔
1863
              "new count must have offset type");
1864
#endif
1865

1866
   return result;
893✔
1867
}
1868

1869
mir_value_t mir_build_all(mir_unit_t *mu, mir_value_t access)
3,931✔
1870
{
1871
   mir_type_t type = mir_get_type(mu, access);
3,931✔
1872
   mir_stamp_t stamp = mir_get_stamp(mu, access);
3,931✔
1873
   mir_type_t pointed = mir_get_pointer(mu, type);
3,931✔
1874
   mir_value_t result = mir_build_1(mu, MIR_OP_ALL, pointed, stamp, access);
3,931✔
1875

1876
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_ACCESS,
3,931✔
1877
              "argument to all must be access type");
1878

1879
   return result;
3,931✔
1880
}
1881

1882
mir_value_t mir_build_address_of(mir_unit_t *mu, mir_value_t array)
57,782✔
1883
{
1884
   mir_type_t type = mir_get_type(mu, array);
57,782✔
1885
   mir_type_t pointer = mir_get_pointer(mu, type);
57,782✔
1886
   mir_stamp_t stamp = mir_get_stamp(mu, array);
57,782✔
1887

1888
   if (mir_is_null(pointer))
57,782✔
1889
      pointer = mir_pointer_type(mu, type);
2,208✔
1890

1891
   mir_value_t result = mir_build_1(mu, MIR_OP_ADDRESS_OF,
57,782✔
1892
                                    pointer, stamp, array);
1893

1894
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_CARRAY)
57,782✔
1895
              || mir_is(mu, array, MIR_TYPE_RECORD),
1896
              "argument to address of must be array or record");
1897

1898
   return result;
57,782✔
1899
}
1900

1901
mir_value_t mir_build_array_ref(mir_unit_t *mu, mir_value_t array,
94,384✔
1902
                                mir_value_t offset)
1903
{
1904
   int64_t cval;
94,384✔
1905
   if (mir_get_const(mu, offset, &cval) && cval == 0)
94,384✔
1906
      return array;
47,821✔
1907

1908
   mir_type_t type = mir_get_type(mu, array);
46,563✔
1909
   mir_stamp_t stamp = mir_get_stamp(mu, array);
46,563✔
1910

1911
   mir_value_t result = mir_build_2(mu, MIR_OP_ARRAY_REF, type, stamp,
46,563✔
1912
                                    array, offset);
1913

1914
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER) || mir_is_signal(mu, array),
46,563✔
1915
              "argument to array ref must be pointer or signal");
1916
   MIR_ASSERT(mir_is_offset(mu, offset),
46,563✔
1917
              "offset argument to array ref must be offset");
1918

1919
   return result;
46,563✔
1920
}
1921

1922
mir_value_t mir_build_table_ref(mir_unit_t *mu, mir_value_t array,
1,045✔
1923
                                mir_value_t stride, const mir_value_t *args,
1924
                                int nargs)
1925
{
1926
   mir_type_t type = mir_get_type(mu, array);
1,045✔
1927
   mir_stamp_t stamp = mir_get_stamp(mu, array);
1,045✔
1928

1929
   node_data_t *n = mir_add_node(mu, MIR_OP_TABLE_REF, type, stamp, nargs + 2);
1,045✔
1930

1931
   mir_set_arg(mu, n, 0, array);
1,045✔
1932
   mir_set_arg(mu, n, 1, stride);
1,045✔
1933

1934
   for (int i = 0; i < nargs; i++)
2,634✔
1935
      mir_set_arg(mu, n, i + 2, args[i]);
1,589✔
1936

1937
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER),
1,045✔
1938
              "argument to table ref must be pointer");
1939
   MIR_ASSERT(mir_is_offset(mu, stride),
1,045✔
1940
              "stride argument to table ref must be offset");
1941

1942
   for (int i = 0; i < nargs; i++)
2,634✔
1943
      MIR_ASSERT(mir_is_integral(mu, args[i]),
1,589✔
1944
                 "table ref indices must be integral");
1945

1946
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1,045✔
1947
}
1948

1949
mir_value_t mir_build_record_ref(mir_unit_t *mu, mir_value_t record,
51,773✔
1950
                                 unsigned field)
1951
{
1952
   mir_type_t pointer = mir_get_type(mu, record);
51,773✔
1953

1954
   mir_mem_t mem = mir_get_mem(mu, record);
51,773✔
1955
   mir_stamp_t stamp = MIR_NULL_STAMP;
51,773✔
1956
   if (mem != MIR_MEM_TOP)
51,773✔
1957
      stamp = mir_pointer_stamp(mu, mem, MIR_NULL_STAMP);
24,239✔
1958

1959
   const type_data_t *td = mir_type_data(mu, mir_get_elem(mu, pointer));
51,773✔
1960

1961
   mir_type_t type = MIR_NULL_TYPE;
51,773✔
1962
   if (td->class == MIR_TYPE_RECORD && field < td->u.record.count)
51,773✔
1963
      type = td->u.record.fields[field + td->u.record.count];
51,773✔
1964

1965
   mir_value_t result = mir_build_2(mu, MIR_OP_RECORD_REF, type, stamp,
51,773✔
1966
                                    record, mir_enum(field));
1967

1968
   MIR_ASSERT(mir_get_class(mu, pointer) == MIR_TYPE_POINTER,
51,773✔
1969
              "record ref argument must be pointer to record");
1970
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
51,773✔
1971
              "record ref argument must be pointer to record");
1972
   MIR_ASSERT(field < td->u.record.count, "field index %d out of range", field);
51,773✔
1973

1974
   return result;
51,773✔
1975
}
1976

1977
mir_value_t mir_build_wrap(mir_unit_t *mu, mir_value_t data,
46,329✔
1978
                           const mir_dim_t *dims, int ndims)
1979
{
1980
   mir_type_t type = mir_get_type(mu, data);
46,329✔
1981
   mir_stamp_t stamp = mir_get_stamp(mu, data);
46,329✔
1982

1983
   const type_data_t *td = mir_type_data(mu, type);
46,329✔
1984
   mir_type_t elem = td->class == MIR_TYPE_POINTER ? td->u.pointer : type;
46,329✔
1985

1986
   mir_type_t uarray = mir_uarray_type(mu, ndims, elem);
46,329✔
1987

1988
   node_data_t *n = mir_add_node(mu, MIR_OP_WRAP, uarray, stamp,
92,658✔
1989
                                  ndims * 3 + 1);
46,329✔
1990

1991
   mir_set_arg(mu, n, 0, data);
46,329✔
1992

1993
   for (int i = 0; i < ndims; i++) {
93,409✔
1994
      mir_set_arg(mu, n, i*3 + 1, dims[i].left);
47,080✔
1995
      mir_set_arg(mu, n, i*3 + 2, dims[i].right);
47,080✔
1996
      mir_set_arg(mu, n, i*3 + 3, dims[i].dir);
47,080✔
1997
   }
1998

1999
   MIR_ASSERT(td->class == MIR_TYPE_POINTER || td->class == MIR_TYPE_SIGNAL,
46,329✔
2000
              "wrapped data is not pointer or signal");
2001

2002
   for (int i = 0; i < ndims; i++) {
93,409✔
2003
      MIR_ASSERT(mir_is_integral(mu, dims[i].left),
47,080✔
2004
                 "dimension %d left bound must be integral", i + 1);
2005
      MIR_ASSERT(mir_is_integral(mu, dims[i].right),
47,080✔
2006
                 "dimension %d right bound must be integral", i + 1);
2007
      MIR_ASSERT(mir_is_bool(mu, dims[i].dir),
47,080✔
2008
                 "dimension %d direction must be bool", i + 1);
2009
   }
2010

2011
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
46,329✔
2012
}
2013

2014
mir_value_t mir_build_unwrap(mir_unit_t *mu, mir_value_t array)
38,426✔
2015
{
2016
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
38,426✔
2017
      return mir_get_arg(mu, array, 0);
2,266✔
2018

2019
   mir_type_t type = mir_get_type(mu, array);
36,160✔
2020
   mir_type_t pointer = mir_get_pointer(mu, type);
36,160✔
2021
   mir_stamp_t stamp = mir_get_stamp(mu, array);
36,160✔
2022

2023
   mir_value_t result = mir_build_1(mu, MIR_OP_UNWRAP, pointer, stamp, array);
36,160✔
2024

2025
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_UARRAY,
36,160✔
2026
              "unwrap argument must be uarray");
2027

2028
   return result;
36,160✔
2029
}
2030

2031
mir_value_t mir_build_uarray_len(mir_unit_t *mu, mir_value_t array, int dim)
30,329✔
2032
{
2033
   mir_type_t t_offset = mir_offset_type(mu);
30,329✔
2034
   mir_value_t result = mir_build_2(mu, MIR_OP_UARRAY_LEN, t_offset,
30,329✔
2035
                                    MIR_NULL_STAMP, array,
30,329✔
2036
                                    mir_const(mu, t_offset, dim));
2037

2038
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
30,329✔
2039
              "uarray len argument must be uarrray");
2040

2041
#ifdef DEBUG
2042
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
30,329✔
2043
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
30,329✔
2044
#endif
2045

2046
   return result;
30,329✔
2047
}
2048

2049
static mir_value_t mir_build_uarray_op(mir_unit_t *mu, mir_op_t op,
62,823✔
2050
                                       mir_type_t type, int arg_index,
2051
                                       mir_value_t array, int dim)
2052
{
2053
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
62,823✔
2054
      return mir_get_arg(mu, array, 1 + (dim * 3) + arg_index);
1,799✔
2055

2056
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP,
61,024✔
2057
                                    array, mir_enum(dim));
2058

2059
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
61,024✔
2060
              "cannot use %s with non-uarray type", mir_op_string(op));
2061

2062
#ifdef DEBUG
2063
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
61,024✔
2064
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
61,024✔
2065
#endif
2066

2067
   return result;
61,024✔
2068
}
2069

2070
mir_value_t mir_build_uarray_left(mir_unit_t *mu, mir_value_t array, int dim)
22,263✔
2071
{
2072
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_LEFT, mir_offset_type(mu),
22,263✔
2073
                              0, array, dim);
2074
}
2075

2076
mir_value_t mir_build_uarray_right(mir_unit_t *mu, mir_value_t array, int dim)
18,266✔
2077
{
2078
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_RIGHT, mir_offset_type(mu),
18,266✔
2079
                              1, array, dim);
2080
}
2081

2082
mir_value_t mir_build_uarray_dir(mir_unit_t *mu, mir_value_t array, int dim)
22,294✔
2083
{
2084
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_DIR, mir_bool_type(mu),
22,294✔
2085
                              2, array, dim);
2086
}
2087

2088
mir_value_t mir_build_range_length(mir_unit_t *mu, mir_value_t left,
9,355✔
2089
                                   mir_value_t right, mir_value_t dir)
2090
{
2091
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_LENGTH,
9,355✔
2092
                                    mir_offset_type(mu), MIR_NULL_STAMP,
9,355✔
2093
                                    left, right, dir);
2094

2095
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
9,355✔
2096
                            mir_get_type(mu, right)),
2097
              "left and right are not the same type");
2098
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
9,355✔
2099
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
9,355✔
2100

2101
   return result;
9,355✔
2102
}
2103

2104
mir_value_t mir_build_range_null(mir_unit_t *mu, mir_value_t left,
4,180✔
2105
                                 mir_value_t right, mir_value_t dir)
2106
{
2107
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_NULL,
4,180✔
2108
                                    mir_bool_type(mu), MIR_NULL_STAMP,
4,180✔
2109
                                    left, right, dir);
2110

2111
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
4,180✔
2112
                            mir_get_type(mu, right)),
2113
              "left and right are not the same type");
2114
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
4,180✔
2115
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
4,180✔
2116

2117
   return result;
4,180✔
2118
}
2119

2120
void mir_build_jump(mir_unit_t *mu, mir_block_t target)
59,299✔
2121
{
2122
   mir_build_1(mu, MIR_OP_JUMP, MIR_NULL_TYPE, MIR_NULL_STAMP,
59,299✔
2123
               mir_cast_value(target));
59,299✔
2124

2125
   MIR_ASSERT(!mir_is_null(target), "invalid jump target");
59,299✔
2126
}
59,299✔
2127

2128
void mir_build_cond(mir_unit_t *mu, mir_value_t test, mir_block_t btrue,
50,523✔
2129
                    mir_block_t bfalse)
2130
{
2131
   int64_t tconst;
50,523✔
2132
   if (mir_get_const(mu, test, &tconst)) {
50,523✔
2133
      mir_build_jump(mu, !!tconst ? btrue : bfalse);
39✔
2134
      return;
39✔
2135
   }
2136

2137
   mir_build_3(mu, MIR_OP_COND, MIR_NULL_TYPE, MIR_NULL_STAMP,
50,484✔
2138
               test, mir_cast_value(btrue), mir_cast_value(bfalse));
50,484✔
2139

2140
   MIR_ASSERT(mir_is_bool(mu, test), "cond test is not a bool");
50,484✔
2141
   MIR_ASSERT(!mir_is_null(btrue) && !mir_is_null(bfalse),
50,484✔
2142
              "invalid cond targets");
2143
}
2144

2145
mir_value_t mir_build_select(mir_unit_t *mu, mir_type_t type, mir_value_t test,
26,991✔
2146
                             mir_value_t vtrue, mir_value_t vfalse)
2147
{
2148
   int64_t tconst;
26,991✔
2149
   if (mir_get_const(mu, test, &tconst))
26,991✔
2150
      return tconst ? vtrue : vfalse;
8,788✔
2151
   else if (mir_equals(vtrue, vfalse))
18,203✔
2152
      return vtrue;
1✔
2153

2154
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
18,202✔
2155
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
18,202✔
2156
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
18,202✔
2157

2158
   mir_value_t result = mir_build_3(mu, MIR_OP_SELECT, type, stamp, test,
18,202✔
2159
                                    vtrue, vfalse);
2160

2161
   MIR_ASSERT(mir_is_bool(mu, test), "select test is not a bool");
18,202✔
2162
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
18,202✔
2163
              "true argument to select is not expected type");
2164
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
18,202✔
2165
              "false argument to select is not expected type");
2166

2167
   return result;
18,202✔
2168
}
2169

2170
mir_value_t mir_build_ternary(mir_unit_t *mu, mir_type_t type,
852✔
2171
                              mir_value_t test, mir_value_t vtrue,
2172
                              mir_value_t vfalse)
2173
{
2174
   if (mir_equals(vtrue, vfalse))
852✔
2175
      return vtrue;
×
2176

2177
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
852✔
2178
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
852✔
2179
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
852✔
2180

2181
   mir_value_t result = mir_build_3(mu, MIR_OP_TERNARY, type, stamp, test,
852✔
2182
                                    vtrue, vfalse);
2183

2184
   MIR_ASSERT(mir_is(mu, test, MIR_TYPE_VEC4), "ternary test is not a vec4");
852✔
2185
   MIR_ASSERT(mir_get_size(mu, mir_get_type(mu, test)) == 1,
852✔
2186
              "test must be one bit vector");
2187
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
852✔
2188
              "true argument to ternary is not expected type");
2189
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
852✔
2190
              "false argument to ternary is not expected type");
2191

2192
   return result;
852✔
2193
}
2194

2195
mir_value_t mir_build_phi(mir_unit_t *mu, mir_type_t type, unsigned ninputs)
1✔
2196
{
2197
   node_data_t *n = mir_add_node(mu, MIR_OP_PHI, type, MIR_NULL_STAMP,
1✔
2198
                                 ninputs * 2);
2199

2200
   for (int i = 0; i < ninputs; i++)
3✔
2201
      mir_set_arg(mu, n, i, MIR_NULL_VALUE);
2✔
2202

2203
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1✔
2204
}
2205

2206
void mir_set_input(mir_unit_t *mu, mir_value_t phi, unsigned nth,
2✔
2207
                   mir_block_t block, mir_value_t value)
2208
{
2209
   node_data_t *n = mir_node_data(mu, phi);
2✔
2210
   assert(n->op == MIR_OP_PHI);
2✔
2211
   assert(nth * 2 < n->nargs);
2✔
2212

2213
   mir_set_arg(mu, n, nth * 2,  mir_cast_value(block));
2✔
2214
   mir_set_arg(mu, n, nth * 2 + 1, value);
2✔
2215

2216
   n->stamp = mir_stamp_union(mu, n->stamp, mir_get_stamp(mu, value));
2✔
2217

2218
   MIR_ASSERT(mir_equals(n->type, mir_get_type(mu, value)),
2✔
2219
              "phi input %d has wrong type", nth);
2220

2221
#ifdef DEBUG
2222
   if (value.tag != MIR_TAG_CONST) {
2✔
2223
      const block_data_t *bd = mir_block_data(mu, block);
2✔
2224
      for (int i = 0; i < bd->num_nodes; i++) {
2✔
2225
         if (bd->nodes[i] == value.id)
2✔
2226
         return;
2227
      }
2228

2229
      MIR_ASSERT(false, "phi input %d not in block %d", nth, block.id);
×
2230
   }
2231
#endif
2232
}
2233

2234
void mir_build_case(mir_unit_t *mu, mir_value_t value, mir_block_t def,
2,009✔
2235
                    const mir_value_t *cases, const mir_block_t *blocks,
2236
                    int ncases)
2237
{
2238
   int64_t cval;
2,009✔
2239
   if (mir_get_const(mu, value, &cval)) {
2,009✔
2240
      for (int i = 0; i < ncases; i++) {
3✔
2241
         int64_t cmp;
2✔
2242
         if (mir_get_const(mu, cases[i], &cmp) && cmp == cval) {
2✔
2243
            mir_build_jump(mu, blocks[i]);
1✔
2244
            return;
1✔
2245
         }
2246
      }
2247

2248
      mir_build_jump(mu, def);
1✔
2249
      return;
1✔
2250
   }
2251

2252
   node_data_t *n = mir_add_node(mu, MIR_OP_CASE, MIR_NULL_TYPE,
4,014✔
2253
                                 MIR_NULL_STAMP, (ncases + 1) * 2);
2,007✔
2254

2255
   mir_set_arg(mu, n, 0, value);
2,007✔
2256
   mir_set_arg(mu, n, 1, mir_cast_value(def));
2,007✔
2257

2258
   for (int i = 0; i < ncases; i++) {
14,265✔
2259
      mir_set_arg(mu, n, (i + 1) * 2, cases[i]);
12,258✔
2260
      mir_set_arg(mu, n, (i + 1) * 2 + 1, mir_cast_value(blocks[i]));
12,258✔
2261
   }
2262

2263
   MIR_ASSERT(mir_is_integral(mu, value), "case choice must be integral");
2,007✔
2264

2265
#ifdef DEBUG
2266
   mir_type_t type = mir_get_type(mu, value);
2,007✔
2267
   for (int i = 0; i < ncases; i++) {
14,265✔
2268
      MIR_ASSERT(mir_is_const(mu, cases[i]), "case choice is not constant");
12,258✔
2269
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, cases[i]), type),
12,258✔
2270
                 "choice and value types do not match");
2271

2272
      for (int j = 0; j < i; j++)
588,899✔
2273
         MIR_ASSERT(!mir_equals(cases[i], cases[j]), "duplicate case choice");
576,641✔
2274
   }
2275
#endif
2276
}
2277

2278
void mir_build_return(mir_unit_t *mu, mir_value_t value)
98,114✔
2279
{
2280
   if (mir_is_null(value))
98,114✔
2281
      mir_add_node(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, 0);
56,115✔
2282
   else
2283
      mir_build_1(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
41,999✔
2284

2285
   MIR_ASSERT(mir_is_null(mu->result) || mir_check_type(mu, value, mu->result),
98,114✔
2286
              "wrong result type");
2287
   MIR_ASSERT(!mir_is_null(mu->result) || mu->kind == MIR_UNIT_PROPERTY
98,114✔
2288
              || mir_is_null(value), "cannot return a result");
2289
}
98,114✔
2290

2291
void mir_build_wait(mir_unit_t *mu, mir_block_t target)
24,135✔
2292
{
2293
   mir_build_1(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
24,135✔
2294
               mir_cast_value(target));
24,135✔
2295

2296
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
24,135✔
2297
              "wait only allowed in process or procedure");
2298
}
24,135✔
2299

2300
void mir_build_consume(mir_unit_t *mu, mir_value_t value)
9,825✔
2301
{
2302
   if (value.tag != MIR_TAG_NODE)
9,825✔
2303
      return;   // Only useful for keeping nodes alive
2304

2305
   mir_build_1(mu, MIR_OP_CONSUME, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
3,136✔
2306
}
2307

2308
mir_value_t mir_build_fcall(mir_unit_t *mu, ident_t name, mir_type_t type,
47,961✔
2309
                            mir_stamp_t stamp, const mir_value_t *args,
2310
                            unsigned nargs)
2311
{
2312
   node_data_t *n = mir_add_node(mu, MIR_OP_FCALL, type, stamp, nargs + 1);
47,961✔
2313

2314
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
47,961✔
2315

2316
   for (int i = 0; i < nargs; i++)
168,593✔
2317
      mir_set_arg(mu, n, i + 1, args[i]);
120,632✔
2318

2319
   if (mir_is_null(type))
47,961✔
2320
      return MIR_NULL_VALUE;
7,673✔
2321
   else
2322
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
40,288✔
2323
}
2324

2325
void mir_build_pcall(mir_unit_t *mu, ident_t name, mir_block_t resume,
1,275✔
2326
                     const mir_value_t *args, unsigned nargs)
2327
{
2328
   node_data_t *n = mir_add_node(mu, MIR_OP_PCALL, MIR_NULL_TYPE,
2,550✔
2329
                                 MIR_NULL_STAMP, nargs + 2);
1,275✔
2330
   mir_set_arg(mu, n, 0, mir_cast_value(resume));
1,275✔
2331
   mir_set_arg(mu, n, 1, mir_add_linkage(mu, name));
1,275✔
2332

2333
   for (int i = 0; i < nargs; i++)
4,229✔
2334
      mir_set_arg(mu, n, i + 2, args[i]);
2,954✔
2335

2336
   MIR_ASSERT(nargs > 0 && mir_is(mu, args[0], MIR_TYPE_CONTEXT),
1,275✔
2337
              "first argument to VHDL procedure must be context pointer");
2338
}
1,275✔
2339

2340
void mir_build_resume(mir_unit_t *mu, ident_t name)
1,275✔
2341
{
2342
   mir_value_t link = mir_add_linkage(mu, name);
1,275✔
2343
   mir_build_1(mu, MIR_OP_RESUME, MIR_NULL_TYPE, MIR_NULL_STAMP, link);
1,275✔
2344

2345
   MIR_ASSERT(mir_count_nodes(mu, mu->cursor.block) == 1,
1,275✔
2346
              "resume must be first op in a block");
2347
}
1,275✔
2348

2349
mir_value_t mir_build_syscall(mir_unit_t *mu, ident_t func, mir_type_t type,
9,516✔
2350
                              mir_stamp_t stamp, mir_value_t locus,
2351
                              const mir_value_t *args, int nargs)
2352
{
2353
   node_data_t *n = mir_add_node(mu, MIR_OP_SYSCALL, type, stamp, nargs + 2);
9,516✔
2354

2355
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
9,516✔
2356
   mir_set_arg(mu, n, 1, locus);
9,516✔
2357

2358
   for (int i = 0; i < nargs; i++)
12,048✔
2359
      mir_set_arg(mu, n, i + 2, args[i]);
2,532✔
2360

2361
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
9,516✔
2362
              "locus argument to syscall must be a debug locus");
2363

2364
   for (int i = 0; i < nargs; i++)
12,048✔
2365
      MIR_ASSERT(!mir_is_null(args[i]), "invalid argument to syscall");
2,532✔
2366

2367
   if (mir_is_null(type))
9,516✔
2368
      return MIR_NULL_VALUE;
6,688✔
2369
   else
2370
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,828✔
2371
}
2372

2373
void mir_build_unreachable(mir_unit_t *mu, mir_value_t locus)
2,605✔
2374
{
2375
   if (mir_is_null(locus))
2,605✔
2376
      mir_build_0(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP);
2,430✔
2377
   else
2378
      mir_build_1(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
175✔
2379

2380
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
2,605✔
2381
              "locus argument to unreachable must be debug locus");
2382
}
2,605✔
2383

2384
static void mir_build_bounds_op(mir_unit_t *mu, mir_op_t op, mir_value_t value,
25,374✔
2385
                                mir_value_t left, mir_value_t right,
2386
                                mir_value_t dir, mir_value_t locus,
2387
                                mir_value_t hint)
2388
{
2389
   // TODO: check if can elide bounds
2390

2391
   mir_build_6(mu, op, MIR_NULL_TYPE, MIR_NULL_STAMP, value, left, right,
25,374✔
2392
               dir, locus, hint);
2393

2394
   MIR_ASSERT(mir_is_numeric(mu, value), "value must be numeric");
25,374✔
2395
   MIR_ASSERT(mir_is_numeric(mu, left), "left bound must be numeric");
25,374✔
2396
   MIR_ASSERT(mir_is_numeric(mu, right), "right bound must be numeric");
25,374✔
2397
   MIR_ASSERT(mir_check_type(mu, dir, mir_bool_type(mu)),
25,374✔
2398
              "direction must be a bool");
2399
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS), "locus must be a debug locus");
25,374✔
2400
}
25,374✔
2401

2402
void mir_build_range_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
5,121✔
2403
                           mir_value_t right, mir_value_t dir,
2404
                           mir_value_t locus, mir_value_t hint)
2405
{
2406
   mir_build_bounds_op(mu, MIR_OP_RANGE_CHECK, value, left, right, dir,
5,121✔
2407
                       locus, hint);
2408
}
5,121✔
2409

2410
void mir_build_index_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
20,253✔
2411
                           mir_value_t right, mir_value_t dir,
2412
                           mir_value_t locus, mir_value_t hint)
2413
{
2414
   mir_build_bounds_op(mu, MIR_OP_INDEX_CHECK, value, left, right, dir,
20,253✔
2415
                       locus, hint);
2416
}
20,253✔
2417

2418
void mir_build_dir_check(mir_unit_t *mu, mir_value_t value, mir_value_t dir,
3,261✔
2419
                         mir_value_t locus)
2420
{
2421
   if (mir_equals(value, dir)) {
3,261✔
2422
      mir_comment(mu, "Elided direction check");
1,160✔
2423
      return;
1,160✔
2424
   }
2425

2426
   mir_build_3(mu, MIR_OP_DIR_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,101✔
2427
               value, dir, locus);
2428

2429
   MIR_ASSERT(mir_check_type(mu, value, mir_bool_type(mu)),
2,101✔
2430
              "null check argument must be a bool");
2431
   MIR_ASSERT(mir_check_type(mu, dir, mir_bool_type(mu)),
2,101✔
2432
              "null check direction must be a bool");
2433
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,101✔
2434
              "locus argument to null check must be a debug locus");
2435
}
2436

2437
void mir_build_null_check(mir_unit_t *mu, mir_value_t ptr, mir_value_t locus)
3,038✔
2438
{
2439
   mir_build_2(mu, MIR_OP_NULL_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
3,038✔
2440
               ptr, locus);
2441

2442
   MIR_ASSERT(mir_is(mu, ptr, MIR_TYPE_ACCESS),
3,038✔
2443
              "null check argument must be an access");
2444
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
3,038✔
2445
              "locus argument to null check must be a debug locus");
2446
}
3,038✔
2447

2448
void mir_build_zero_check(mir_unit_t *mu, mir_value_t value, mir_value_t locus)
115✔
2449
{
2450
   int64_t cval;
115✔
2451
   if (mir_get_const(mu, value, &cval) && cval != 0)
115✔
2452
      return;
×
2453

2454
   mir_build_2(mu, MIR_OP_ZERO_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
115✔
2455
               value, locus);
2456

2457
   MIR_ASSERT(mir_is_integral(mu, value),
115✔
2458
              "argument to zero check must be integral");
2459
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
115✔
2460
              "locus argument to zero check must be a debug locus");
2461
}
2462

2463
void mir_build_length_check(mir_unit_t *mu, mir_value_t llen, mir_value_t rlen,
10,087✔
2464
                            mir_value_t locus, mir_value_t dim)
2465
{
2466
   if (mir_equals(llen, rlen))
10,087✔
2467
      return;
2468

2469
   if (mir_is_null(dim))
9,776✔
2470
      mir_build_3(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,740✔
2471
                  llen, rlen, locus);
2472
   else
2473
      mir_build_4(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
36✔
2474
                  llen, rlen, locus, dim);
2475

2476
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
9,776✔
2477
              "locus argument to length check must be a debug locus");
2478
}
2479

2480
void mir_build_exponent_check(mir_unit_t *mu, mir_value_t exp,
160✔
2481
                              mir_value_t locus)
2482
{
2483
   int64_t cval;
160✔
2484
   if (mir_get_const(mu, exp, &cval) && cval >= 0)
160✔
2485
      return;
×
2486

2487
   mir_build_2(mu, MIR_OP_EXPONENT_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
160✔
2488
               exp, locus);
2489

2490
   MIR_ASSERT(mir_is_integral(mu, exp),
160✔
2491
              "exp argument to exponent check must be a integer");
2492
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
160✔
2493
              "locus argument to exponent check must be a debug locus");
2494
}
2495

2496
void mir_build_file_open(mir_unit_t *mu, mir_value_t file, mir_value_t name,
2,135✔
2497
                         mir_value_t length, mir_value_t kind,
2498
                         mir_value_t status)
2499
{
2500
   if (mir_is_null(status))
2,135✔
2501
      mir_build_4(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,102✔
2502
                  file, name, length, kind);
2503
   else
2504
      mir_build_5(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
33✔
2505
                  file, name, length, kind, status);
2506

2507
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
2,135✔
2508
              "file open first argument must be pointer to file");
2509
}
2,135✔
2510

2511
void mir_build_file_read(mir_unit_t *mu, mir_value_t file, mir_value_t ptr,
120✔
2512
                         mir_value_t inlen, mir_value_t outlen)
2513
{
2514
   if (mir_is_null(inlen))
120✔
2515
      mir_build_2(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
64✔
2516
                  file, ptr);
2517
   else if (mir_is_null(outlen))
56✔
2518
      mir_build_3(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
12✔
2519
                  file, ptr, inlen);
2520
   else
2521
      mir_build_4(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
44✔
2522
                  file, ptr, inlen, outlen);
2523

2524
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
120✔
2525
              "file read first argument must have file pointer type");
2526
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
120✔
2527
              "file read pointer argument must have pointer type");
2528
   MIR_ASSERT(mir_is_null(inlen) || mir_is_integral(mu, inlen),
120✔
2529
              "file read inlen argument must be integral");
2530
   MIR_ASSERT(mir_is_null(outlen) || mir_is(mu, outlen, MIR_TYPE_POINTER),
120✔
2531
              "file read outlen argument must have pointer type");
2532
}
120✔
2533

2534
void mir_build_file_write(mir_unit_t *mu, mir_value_t file, mir_value_t value,
371✔
2535
                          mir_value_t length)
2536
{
2537
   if (mir_is_null(length))
371✔
2538
      mir_build_2(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
76✔
2539
                  file, value);
2540
   else
2541
      mir_build_3(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
295✔
2542
                  file, value, length);
2543

2544
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
371✔
2545
              "file write first argument must have file pointer type");
2546
}
371✔
2547

2548
mir_value_t mir_build_init_signal(mir_unit_t *mu, mir_type_t type,
35,068✔
2549
                                  mir_value_t count, mir_value_t size,
2550
                                  mir_value_t value, mir_value_t flags,
2551
                                  mir_value_t locus, mir_value_t offset)
2552
{
2553
   mir_type_t stype = mir_signal_type(mu, type);
35,068✔
2554

2555
   mir_value_t result;
35,068✔
2556
   if (mir_is_null(offset))
35,068✔
2557
      result = mir_build_5(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
24,925✔
2558
                           count, size, value, flags, locus);
2559
   else
2560
      result = mir_build_6(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
10,143✔
2561
                           count, size, value, flags, locus, offset);
2562

2563
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_INT
35,068✔
2564
              || mir_get_class(mu, type) == MIR_TYPE_REAL,
2565
              "signal must have integer or real type");
2566
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
35,068✔
2567
   MIR_ASSERT(mir_is_offset(mu, size), "size argument must be offset");
35,068✔
2568
   MIR_ASSERT(mir_is_offset(mu, flags), "flags argument must be offset");
35,068✔
2569
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
35,068✔
2570
              "locus argument to init signal is not debug locus");
2571
   MIR_ASSERT(mir_is_null(offset) || mir_is(mu, offset, MIR_TYPE_POINTER),
35,068✔
2572
              "offset argument must be pointer or null");
2573

2574
   return result;
35,068✔
2575
}
2576

2577
void mir_build_drive_signal(mir_unit_t *mu, mir_value_t target,
11,839✔
2578
                            mir_value_t count)
2579
{
2580
   mir_build_2(mu, MIR_OP_DRIVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
11,839✔
2581
               target, count);
2582

2583
   MIR_ASSERT(mir_is_signal(mu, target), "target must be signal");
11,839✔
2584
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
11,839✔
2585
}
11,839✔
2586

2587
void mir_build_sched_waveform(mir_unit_t *mu, mir_value_t target,
12,438✔
2588
                              mir_value_t count, mir_value_t values,
2589
                              mir_value_t reject, mir_value_t after)
2590
{
2591
   int64_t nconst;
12,438✔
2592
   if (mir_get_const(mu, count, &nconst) && nconst == 0) {
12,438✔
2593
      mir_comment(mu, "Skip empty waveform");
×
2594
      return;
×
2595
   }
2596

2597
   mir_build_5(mu, MIR_OP_SCHED_WAVEFORM, MIR_NULL_TYPE, MIR_NULL_STAMP,
12,438✔
2598
               target, count, values, reject, after);
2599

2600
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
12,438✔
2601
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
12,438✔
2602
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
12,438✔
2603
}
2604

2605
void mir_build_put_driver(mir_unit_t *mu, mir_value_t target,
2,115✔
2606
                          mir_value_t count, mir_value_t values)
2607
{
2608
   mir_build_3(mu, MIR_OP_PUT_DRIVER, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,115✔
2609
               target, count, values);
2610

2611
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
2,115✔
2612
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
2,115✔
2613
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
2,115✔
2614
}
2,115✔
2615

2616
void mir_build_deposit_signal(mir_unit_t *mu, mir_value_t target,
10,551✔
2617
                              mir_value_t count, mir_value_t values)
2618
{
2619
   mir_build_3(mu, MIR_OP_DEPOSIT_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
10,551✔
2620
               target, count, values);
2621

2622
   MIR_ASSERT(mir_is_signal(mu, target),
10,551✔
2623
              "deposit signal target is not signal");
2624
   MIR_ASSERT(mir_is_offset(mu, count),
10,551✔
2625
              "deposit signal count is not offset type");
2626
   MIR_ASSERT(!mir_is_signal(mu, values),
10,551✔
2627
              "signal cannot be values argument for deposit signal");
2628
}
10,551✔
2629

2630
void mir_build_sched_deposit(mir_unit_t *mu, mir_value_t target,
320✔
2631
                             mir_value_t count, mir_value_t values,
2632
                             mir_value_t after)
2633
{
2634
   mir_build_4(mu, MIR_OP_SCHED_DEPOSIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
320✔
2635
               target, count, values, after);
2636

2637
   MIR_ASSERT(mir_is_signal(mu, target),
320✔
2638
              "sched deposit target is not signal");
2639
   MIR_ASSERT(mir_is_offset(mu, count),
320✔
2640
              "sched deposit count is not offset type");
2641
   MIR_ASSERT(!mir_is_signal(mu, values),
320✔
2642
              "signal cannot be values argument for sched deposit");
2643
}
320✔
2644

2645
mir_value_t mir_build_resolved(mir_unit_t *mu, mir_value_t signal)
37,623✔
2646
{
2647
   mir_type_t type = mir_get_type(mu, signal);
37,623✔
2648
   mir_type_t pointer = mir_get_pointer(mu, type);
37,623✔
2649
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
37,623✔
2650

2651
   mir_value_t result = mir_build_1(mu, MIR_OP_RESOLVED, pointer,
37,623✔
2652
                                    stamp, signal);
2653

2654
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
37,623✔
2655
              "argument to resolved must be signal");
2656

2657
   return result;
37,623✔
2658
}
2659

2660
mir_value_t mir_build_last_value(mir_unit_t *mu, mir_value_t signal)
401✔
2661
{
2662
   mir_type_t type = mir_get_type(mu, signal);
401✔
2663
   mir_type_t pointer = mir_get_pointer(mu, type);
401✔
2664
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
401✔
2665

2666
   mir_value_t result = mir_build_1(mu, MIR_OP_LAST_VALUE, pointer,
401✔
2667
                                    stamp, signal);
2668

2669
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
401✔
2670
              "argument to resolved must be signal");
2671

2672
   return result;
401✔
2673
}
2674

2675
mir_value_t mir_build_driving_value(mir_unit_t *mu, mir_value_t signal,
436✔
2676
                                    mir_value_t count)
2677
{
2678
   mir_type_t type = mir_get_pointer(mu, mir_get_type(mu, signal));
436✔
2679
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
436✔
2680

2681
   mir_value_t result = mir_build_2(mu, MIR_OP_DRIVING_VALUE, type, stamp,
436✔
2682
                                    signal, count);
2683

2684
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
436✔
2685
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must have offset type");
436✔
2686

2687
   return result;
436✔
2688
}
2689

2690
void mir_build_force(mir_unit_t *mu, mir_value_t target, mir_value_t count,
93✔
2691
                     mir_value_t values)
2692
{
2693
   mir_build_3(mu, MIR_OP_FORCE, MIR_NULL_TYPE, MIR_NULL_STAMP,
93✔
2694
               target, count, values);
2695

2696
   MIR_ASSERT(mir_is_signal(mu, target), "force target is not signal");
93✔
2697
   MIR_ASSERT(mir_is_offset(mu, count), "force count is not offset type");
93✔
2698
}
93✔
2699

2700
void mir_build_release(mir_unit_t *mu, mir_value_t target, mir_value_t count)
56✔
2701
{
2702
   mir_build_2(mu, MIR_OP_RELEASE, MIR_NULL_TYPE, MIR_NULL_STAMP,
56✔
2703
               target, count);
2704

2705
   MIR_ASSERT(mir_is_signal(mu, target), "release target is not signal");
56✔
2706
   MIR_ASSERT(mir_is_offset(mu, count), "release net count is not offset type");
56✔
2707
}
56✔
2708

2709
void mir_build_disconnect(mir_unit_t *mu, mir_value_t target, mir_value_t count,
32✔
2710
                          mir_value_t reject, mir_value_t after)
2711
{
2712
   mir_build_4(mu, MIR_OP_DISCONNECT, MIR_NULL_TYPE, MIR_NULL_STAMP,
32✔
2713
               target, count, reject, after);
2714

2715
   MIR_ASSERT(mir_is_signal(mu, target), "disconnect target is not signal");
32✔
2716
   MIR_ASSERT(mir_is_offset(mu, count), "disconnect count is not offset type");
32✔
2717
}
32✔
2718

2719

2720
mir_value_t mir_build_last_event(mir_unit_t *mu, mir_value_t signal,
56✔
2721
                                 mir_value_t count)
2722
{
2723
   mir_type_t type = mir_time_type(mu);
56✔
2724

2725
   mir_value_t result;
56✔
2726
   if (mir_is_null(count))
56✔
2727
      result = mir_build_1(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP, signal);
44✔
2728
   else
2729
      result = mir_build_2(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP,
12✔
2730
                           signal, count);
2731

2732
   MIR_ASSERT(mir_is_signal(mu, signal),
56✔
2733
              "signal argument to last event must have signal type");
2734
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
56✔
2735
              "length argument to last event must have offset type");
2736

2737
   return result;
56✔
2738
}
2739

2740
mir_value_t mir_build_last_active(mir_unit_t *mu, mir_value_t signal,
60✔
2741
                                  mir_value_t count)
2742
{
2743
   mir_type_t type = mir_time_type(mu);
60✔
2744

2745
   mir_value_t result;
60✔
2746
   if (mir_is_null(count))
60✔
2747
      result = mir_build_1(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
52✔
2748
                           signal);
2749
   else
2750
      result = mir_build_2(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
8✔
2751
                           signal, count);
2752

2753
   MIR_ASSERT(mir_is_signal(mu, signal),
60✔
2754
              "signal argument to last event must have signal type");
2755
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
60✔
2756
              "length argument to last event must have offset type");
2757

2758
   return result;
60✔
2759
}
2760

2761

2762
static mir_value_t mir_build_signal_flag(mir_unit_t *mu, mir_op_t op,
1,119✔
2763
                                         mir_value_t signal, mir_value_t count)
2764
{
2765
   mir_type_t t_bool = mir_bool_type(mu);
1,119✔
2766
   mir_value_t result = mir_build_2(mu, op, t_bool, MIR_NULL_STAMP,
1,119✔
2767
                                    signal, count);
2768

2769
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument must be signal");
1,119✔
2770
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
1,119✔
2771

2772
   return result;
1,119✔
2773
}
2774

2775
mir_value_t mir_build_event_flag(mir_unit_t *mu, mir_value_t signal,
750✔
2776
                                 mir_value_t count)
2777
{
2778
   return mir_build_signal_flag(mu, MIR_OP_EVENT, signal, count);
750✔
2779
}
2780

2781
mir_value_t mir_build_active_flag(mir_unit_t *mu, mir_value_t signal,
321✔
2782
                                  mir_value_t count)
2783
{
2784
   return mir_build_signal_flag(mu, MIR_OP_ACTIVE, signal, count);
321✔
2785
}
2786

2787
mir_value_t mir_build_driving_flag(mir_unit_t *mu, mir_value_t signal,
48✔
2788
                                   mir_value_t count)
2789
{
2790
   return mir_build_signal_flag(mu, MIR_OP_DRIVING, signal, count);
48✔
2791
}
2792

2793
void mir_build_resolve_signal(mir_unit_t *mu, mir_value_t signal,
8,126✔
2794
                              mir_value_t resolution)
2795
{
2796
   mir_build_2(mu, MIR_OP_RESOLVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,126✔
2797
               signal, resolution);
2798

2799
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument has wrong type");
8,126✔
2800
   MIR_ASSERT(mir_points_to(mu, resolution, MIR_TYPE_RESOLUTION),
8,126✔
2801
              "resolution wrapper argument has wrong type");
2802
}
8,126✔
2803

2804
void mir_build_transfer_signal(mir_unit_t *mu, mir_value_t target,
657✔
2805
                               mir_value_t source, mir_value_t count,
2806
                               mir_value_t reject, mir_value_t after)
2807
{
2808
   mir_build_5(mu, MIR_OP_TRANSFER_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
657✔
2809
               target, source, count, reject, after);
2810

2811
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
657✔
2812
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
657✔
2813
   MIR_ASSERT(mir_is_signal(mu, source), "source is not a signal");
657✔
2814
}
657✔
2815

2816
mir_value_t mir_build_get_counters(mir_unit_t *mu, ident_t block)
1,065✔
2817
{
2818
   mir_type_t t_int32 = mir_int_type(mu, INT32_MIN, INT32_MAX);
1,065✔
2819
   mir_type_t t_ptr = mir_pointer_type(mu, t_int32);
1,065✔
2820

2821
   mir_value_t link = mir_add_linkage(mu, block);
1,065✔
2822
   return mir_build_1(mu, MIR_OP_GET_COUNTERS, t_ptr, MIR_NULL_STAMP, link);
1,065✔
2823
}
2824

2825
void mir_build_cover_stmt(mir_unit_t *mu, mir_value_t counters, uint32_t tag)
1,617✔
2826
{
2827
   mir_build_2(mu, MIR_OP_COVER_STMT, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,617✔
2828
               counters, mir_enum(tag));
2829
}
1,617✔
2830

2831
void mir_build_cover_branch(mir_unit_t *mu, mir_value_t counters, uint32_t tag)
695✔
2832
{
2833
   mir_build_2(mu, MIR_OP_COVER_BRANCH, MIR_NULL_TYPE, MIR_NULL_STAMP,
695✔
2834
               counters, mir_enum(tag));
2835
}
695✔
2836

2837
void mir_build_cover_expr(mir_unit_t *mu, mir_value_t counters, uint32_t tag)
1,144✔
2838
{
2839
   mir_build_2(mu, MIR_OP_COVER_EXPR, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,144✔
2840
               counters, mir_enum(tag));
2841
}
1,144✔
2842

2843
void mir_build_cover_toggle(mir_unit_t *mu, mir_value_t signal,
1,364✔
2844
                            mir_value_t count, uint32_t tag)
2845
{
2846
   mir_build_3(mu, MIR_OP_COVER_TOGGLE, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,364✔
2847
               signal, count, mir_enum(tag));
2848

2849
   MIR_ASSERT(mir_is_signal(mu, signal),
1,364✔
2850
              "argument to cover toggle must be signal");
2851
}
1,364✔
2852

2853
void mir_build_cover_state(mir_unit_t *mu, mir_value_t signal, mir_value_t low,
18✔
2854
                           uint32_t tag)
2855
{
2856
   mir_build_3(mu, MIR_OP_COVER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
18✔
2857
               signal, low, mir_enum(tag));
2858

2859
   MIR_ASSERT(mir_is_signal(mu, signal),
18✔
2860
              "argument to cover state must be signal");
2861
}
18✔
2862

2863
mir_value_t mir_build_package_init(mir_unit_t *mu, ident_t name,
41,949✔
2864
                                   mir_value_t context)
2865
{
2866
   mir_value_t link = mir_add_linkage(mu, name);
41,949✔
2867
   mir_type_t type = mir_context_type(mu, name);
41,949✔
2868

2869
   mir_value_t result;
41,949✔
2870
   if (mir_is_null(context))
41,949✔
2871
      result = mir_build_1(mu, MIR_OP_PACKAGE_INIT, type,
41,634✔
2872
                           MIR_NULL_STAMP, link);
41,634✔
2873
   else
2874
      result = mir_build_2(mu, MIR_OP_PACKAGE_INIT, type,
315✔
2875
                           MIR_NULL_STAMP, link, context);
315✔
2876

2877
   MIR_ASSERT(mir_is_null(context) || mir_is(mu, context, MIR_TYPE_CONTEXT),
41,949✔
2878
              "invalid package init context argument");
2879
   MIR_ASSERT(name != mu->name, "cyclic package init");
41,949✔
2880

2881
   return result;
41,949✔
2882
}
2883

2884
void mir_build_process_init(mir_unit_t *mu, mir_value_t closure,
3,929✔
2885
                            mir_value_t locus)
2886
{
2887
   mir_build_2(mu, MIR_OP_PROCESS_INIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
3,929✔
2888
               closure, locus);
2889

2890
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
3,929✔
2891
              "closure argument to process init must be a closure");
2892
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
3,929✔
2893
              "locus argument to process init must be a debug locus");
2894
}
3,929✔
2895

2896
mir_value_t mir_build_protected_init(mir_unit_t *mu, mir_type_t type,
1,052✔
2897
                                     mir_value_t context, mir_value_t path_name,
2898
                                     mir_value_t inst_name)
2899
{
2900
   mir_value_t link = mir_add_linkage(mu, mir_type_data(mu, type)->u.context);
1,052✔
2901

2902
   mir_value_t result;
1,052✔
2903
   if (mir_is_null(path_name) && mir_is_null(inst_name))
1,052✔
2904
      result = mir_build_2(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
230✔
2905
                           link, context);
2906
   else {
2907
      result = mir_build_4(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
822✔
2908
                           link, context, path_name, inst_name);
2909

2910
      MIR_ASSERT(mir_is(mu, path_name, MIR_TYPE_UARRAY),
822✔
2911
                 "path name argument must be array");
2912
      MIR_ASSERT(mir_is(mu, inst_name, MIR_TYPE_UARRAY),
822✔
2913
                 "inst name argument must be array");
2914
   }
2915

2916
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CONTEXT,
1,052✔
2917
                "protected init type must be context");
2918
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
1,052✔
2919
              "invalid protected init context argument");
2920

2921
   return result;
1,052✔
2922
}
2923

2924
mir_value_t mir_build_instance_init(mir_unit_t *mu, ident_t name,
1,370✔
2925
                                    const mir_value_t *args, unsigned nargs)
2926
{
2927
   node_data_t *n = mir_add_node(mu, MIR_OP_INSTANCE_INIT,
1,370✔
2928
                                 mir_context_type(mu, name),
2929
                                 MIR_NULL_STAMP, nargs + 1);
1,370✔
2930
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
1,370✔
2931

2932
   for (int i = 0; i < nargs; i++)
3,747✔
2933
      mir_set_arg(mu, n, i + 1, args[i]);
2,377✔
2934

2935
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1,370✔
2936
}
2937

2938
void mir_build_record_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
2,961✔
2939
{
2940
   mir_build_1(mu, MIR_OP_RECORD_SCOPE, type, MIR_NULL_STAMP, locus);
2,961✔
2941

2942
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,961✔
2943
              "locus argument to record scope must be a debug locus");
2944
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_RECORD,
2,961✔
2945
              "record scope type must be record");
2946
}
2,961✔
2947

2948
void mir_build_array_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
1,103✔
2949
{
2950
   mir_build_1(mu, MIR_OP_ARRAY_SCOPE, type, MIR_NULL_STAMP, locus);
1,103✔
2951

2952
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
1,103✔
2953
              "locus argument to array scope must be a debug locus");
2954
}
1,103✔
2955

2956
void mir_build_package_scope(mir_unit_t *mu, mir_value_t locus)
72✔
2957
{
2958
   mir_build_1(mu, MIR_OP_PACKAGE_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
72✔
2959

2960
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
72✔
2961
              "locus argument to package scope must be a debug locus");
2962
}
72✔
2963

2964
void mir_build_pop_scope(mir_unit_t *mu)
4,136✔
2965
{
2966
   mir_build_0(mu, MIR_OP_POP_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP);
4,136✔
2967
}
4,136✔
2968

2969
void mir_build_alias_signal(mir_unit_t *mu, mir_value_t signal,
7,410✔
2970
                            mir_value_t locus)
2971
{
2972
   mir_build_2(mu, MIR_OP_ALIAS_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,410✔
2973
               signal, locus);
2974

2975
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
7,410✔
2976
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
7,410✔
2977
              "locus argument must have debug locus type");
2978
}
7,410✔
2979

2980
void mir_build_map_signal(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
9,246✔
2981
                          mir_value_t count)
2982
{
2983
   mir_build_3(mu, MIR_OP_MAP_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,246✔
2984
               src, dst, count);
2985

2986
   MIR_ASSERT(mir_is_signal(mu, src),
9,246✔
2987
              "src argument to map signal is not a signal");
2988
   MIR_ASSERT(mir_is_signal(mu, dst),
9,246✔
2989
              "dst argument to map signal is not a signal");
2990
   MIR_ASSERT(mir_is_offset(mu, count),
9,246✔
2991
              "count argument to map signal is not offset type");
2992
}
9,246✔
2993

2994
void mir_build_map_const(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
338✔
2995
                         mir_value_t count)
2996
{
2997
   mir_build_3(mu, MIR_OP_MAP_CONST, MIR_NULL_TYPE, MIR_NULL_STAMP,
338✔
2998
               src, dst, count);
2999

3000
   MIR_ASSERT(mir_is_signal(mu, dst),
338✔
3001
              "dst argument to map const is not a signal");
3002
   MIR_ASSERT(mir_is_offset(mu, count),
338✔
3003
              "count argument to map const is not offset type");
3004
}
338✔
3005

3006
mir_value_t mir_build_level_trigger(mir_unit_t *mu, mir_value_t signal,
385✔
3007
                                    mir_value_t count)
3008
{
3009
   mir_type_t type = mir_trigger_type(mu);
385✔
3010
   mir_value_t result = mir_build_2(mu, MIR_OP_LEVEL_TRIGGER, type,
385✔
3011
                                    MIR_NULL_STAMP, signal, count);
385✔
3012

3013
   MIR_ASSERT(mir_is_signal(mu, signal),
385✔
3014
              "level trigger argument must be signal");
3015
   MIR_ASSERT(mir_is_offset(mu, count),
385✔
3016
              "level trigger count argument must be offset");
3017

3018
   return result;
385✔
3019
}
3020

3021
mir_value_t mir_build_cmp_trigger(mir_unit_t *mu, mir_value_t left,
62✔
3022
                                  mir_value_t right)
3023
{
3024
   mir_type_t type = mir_trigger_type(mu);
62✔
3025
   mir_value_t result = mir_build_2(mu, MIR_OP_CMP_TRIGGER, type,
62✔
3026
                                    MIR_NULL_STAMP, left, right);
62✔
3027

3028
   MIR_ASSERT(mir_is_signal(mu, left),
62✔
3029
              "cmp trigger left argument must be signal");
3030
   MIR_ASSERT(mir_is_integral(mu, right),
62✔
3031
              "cmp trigger right argument must be integer");
3032

3033
   return result;
62✔
3034
}
3035

3036
mir_value_t mir_build_function_trigger(mir_unit_t *mu, ident_t name,
504✔
3037
                                       const mir_value_t *args, unsigned nargs)
3038
{
3039
   mir_type_t type = mir_trigger_type(mu);
504✔
3040
   node_data_t *n = mir_add_node(mu, MIR_OP_FUNCTION_TRIGGER, type,
1,008✔
3041
                                 MIR_NULL_STAMP, nargs + 1);
504✔
3042

3043
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
504✔
3044

3045
   for (int i = 0; i < nargs; i++)
1,272✔
3046
      mir_set_arg(mu, n, i + 1, args[i]);
768✔
3047

3048
   MIR_ASSERT(nargs >= 1, "function trigger requires at least one argument");
504✔
3049

3050
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
504✔
3051
}
3052

3053
mir_value_t mir_build_or_trigger(mir_unit_t *mu, mir_value_t left,
225✔
3054
                                 mir_value_t right)
3055
{
3056
   mir_type_t type = mir_trigger_type(mu);
225✔
3057
   mir_value_t result = mir_build_2(mu, MIR_OP_OR_TRIGGER, type,
225✔
3058
                                    MIR_NULL_STAMP, left, right);
225✔
3059

3060
   MIR_ASSERT(mir_is(mu, left, MIR_TYPE_TRIGGER),
225✔
3061
              "or trigger left argument must be trigger");
3062
   MIR_ASSERT(mir_is(mu, right, MIR_TYPE_TRIGGER),
225✔
3063
              "or trigger right argument must be trigger");
3064

3065
   return result;
225✔
3066
}
3067

3068
void mir_build_add_trigger(mir_unit_t *mu, mir_value_t trigger)
505✔
3069
{
3070
   mir_build_1(mu, MIR_OP_ADD_TRIGGER, MIR_NULL_TYPE, MIR_NULL_STAMP, trigger);
505✔
3071

3072
   MIR_ASSERT(mir_is(mu, trigger, MIR_TYPE_TRIGGER),
505✔
3073
              "add trigger argument must be trigger");
3074
}
505✔
3075

3076
mir_value_t mir_build_link_package(mir_unit_t *mu, ident_t name)
9,832✔
3077
{
3078
   mir_value_t link = mir_add_linkage(mu, name);
9,832✔
3079
   mir_type_t type = mir_context_type(mu, name);
9,832✔
3080

3081
   mir_value_t result = mir_build_1(mu, MIR_OP_LINK_PACKAGE, type,
9,832✔
3082
                                    MIR_NULL_STAMP, link);
9,832✔
3083

3084
   MIR_ASSERT(name != mu->name, "cannot link the current unit");
9,832✔
3085

3086
   return result;
9,832✔
3087
}
3088

3089
mir_value_t mir_build_link_var(mir_unit_t *mu, mir_value_t context,
9,890✔
3090
                               ident_t name, mir_type_t type)
3091
{
3092
   mir_type_t pointer = mir_get_var_pointer(mu, type);
9,890✔
3093
   mir_type_t context_type = mir_get_type(mu, context);
9,890✔
3094

3095
   ident_t unit_name = mir_type_data(mu, context_type)->u.context;
9,890✔
3096

3097
   mir_value_t link = mir_add_linkage(mu, unit_name);
9,890✔
3098
   mir_value_t var = mir_add_extvar(mu, name);
9,890✔
3099
   mir_value_t result = mir_build_3(mu, MIR_OP_LINK_VAR, pointer,
9,890✔
3100
                                    MIR_NULL_STAMP, link, context, var);
9,890✔
3101

3102
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
9,890✔
3103
              "first argument to link var must be context");
3104

3105
   return result;
9,890✔
3106
}
3107

3108
void mir_build_bind_foreign(mir_unit_t *mu, mir_value_t spec,
1,513✔
3109
                            mir_value_t length, mir_value_t locus)
3110
{
3111
   if (mir_is_null(locus))
1,513✔
3112
      mir_build_2(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
226✔
3113
                  spec, length);
3114
   else
3115
      mir_build_3(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,287✔
3116
                  spec, length, locus);
3117

3118
   MIR_ASSERT(mir_is(mu, spec, MIR_TYPE_POINTER),
1,513✔
3119
              "spec argument to bind foreign must be a pointer");
3120
   MIR_ASSERT(mir_is_offset(mu, length),
1,513✔
3121
              "legnth argument to bind foreign must be offset");
3122
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
1,513✔
3123
              "locus argument to bind foreign value must be a debug locus");
3124
}
1,513✔
3125

3126
mir_value_t mir_build_bind_external(mir_unit_t *mu, mir_value_t locus,
239✔
3127
                                    ident_t scope, mir_type_t type,
3128
                                    mir_stamp_t stamp, const mir_value_t *args,
3129
                                    int nargs)
3130
{
3131
   mir_type_t pointer = mir_get_var_pointer(mu, type);
239✔
3132
   mir_value_t link = mir_add_linkage(mu, scope);
239✔
3133

3134
   node_data_t *n = mir_add_node(mu, MIR_OP_BIND_EXTERNAL, pointer, stamp,
478✔
3135
                                 nargs + 2);
239✔
3136
   mir_set_arg(mu, n, 0, locus);
239✔
3137
   mir_set_arg(mu, n, 1, link);
239✔
3138

3139
   for (int i = 0; i < nargs; i++)
279✔
3140
      mir_set_arg(mu, n, i + 2, args[i]);
40✔
3141

3142
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
239✔
3143
              "bind external argument must be locus");
3144

3145
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
239✔
3146
}
3147

3148
mir_value_t mir_build_context_upref(mir_unit_t *mu, int hops)
19,251✔
3149
{
3150
   mir_type_t type = MIR_NULL_TYPE;
19,251✔
3151
   if (hops == 0)
19,251✔
3152
      type = mir_self_type(mu);
8,288✔
3153
   else {
3154
      mir_shape_t *s = mu->parent;
10,963✔
3155
      for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
11,329✔
3156

3157
      if (s != NULL) type = s->type;
10,963✔
3158
   }
3159

3160
   mir_value_t result = mir_build_1(mu, MIR_OP_CONTEXT_UPREF, type,
19,251✔
3161
                                    MIR_NULL_STAMP, mir_enum(hops));
19,251✔
3162

3163
   MIR_ASSERT(hops >= 0, "invalid hop count");
19,251✔
3164
   MIR_ASSERT(!mir_is_null(type), "hop count is greater than depth");
19,251✔
3165

3166
   return result;
19,251✔
3167
}
3168

3169
mir_value_t mir_build_var_upref(mir_unit_t *mu, int hops, int nth)
98,438✔
3170
{
3171
   mir_type_t type = MIR_NULL_TYPE;
98,438✔
3172
   mir_value_t link = MIR_NULL_VALUE;
98,438✔
3173

3174
   mir_shape_t *s = mu->parent;
98,438✔
3175
   for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
112,025✔
3176

3177
   if (s != NULL && nth >= 0 && nth < s->num_slots) {
98,438✔
3178
      type = s->slots[nth].pointer;
98,438✔
3179
      link = mir_add_linkage(mu, s->name);
98,438✔
3180
   }
3181

3182
   mir_value_t result = mir_build_3(mu, MIR_OP_VAR_UPREF, type, MIR_NULL_STAMP,
98,438✔
3183
                                    mir_enum(hops), link, mir_enum(nth));
3184

3185
   MIR_ASSERT(hops > 0, "invalid hop count");
98,438✔
3186
   MIR_ASSERT(!mir_is_null(type), "invalid variable reference");
98,438✔
3187

3188
   return result;
98,438✔
3189
}
3190

3191
void mir_build_sched_event(mir_unit_t *mu, mir_value_t on, mir_value_t count)
7,632✔
3192
{
3193
   if (mir_is_null(count)) {
7,632✔
3194
      mir_build_1(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP, on);
353✔
3195

3196
      MIR_ASSERT(mir_is(mu, on, MIR_TYPE_TRIGGER), "argument must be trigger");
353✔
3197
   }
3198
   else {
3199
      mir_build_2(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,279✔
3200
                  on, count);
3201

3202
      MIR_ASSERT(mir_is_signal(mu, on), "argument must be signal");
7,279✔
3203
      MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
7,279✔
3204
   }
3205
}
7,632✔
3206

3207
void mir_build_clear_event(mir_unit_t *mu, mir_value_t on, mir_value_t count)
1,094✔
3208
{
3209
   if (mir_is_null(count)) {
1,094✔
3210
      mir_build_1(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP, on);
353✔
3211

3212
      MIR_ASSERT(mir_is(mu, on, MIR_TYPE_TRIGGER), "argument must be trigger");
353✔
3213
   }
3214
   else {
3215
      mir_build_2(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
741✔
3216
                  on, count);
3217

3218
      MIR_ASSERT(mir_is_signal(mu, on), "argument must be signal");
741✔
3219
      MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
741✔
3220
   }
3221
}
1,094✔
3222

3223
void mir_build_sched_active(mir_unit_t *mu, mir_value_t on, mir_value_t count)
533✔
3224
{
3225
   mir_build_2(mu, MIR_OP_SCHED_ACTIVE, MIR_NULL_TYPE, MIR_NULL_STAMP,
533✔
3226
               on, count);
3227

3228
   MIR_ASSERT(mir_is_signal(mu, on), "argument must be signal");
533✔
3229
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
533✔
3230
}
533✔
3231

3232
void mir_build_sched_process(mir_unit_t *mu, mir_value_t delay)
11,613✔
3233
{
3234
   mir_build_1(mu, MIR_OP_SCHED_PROCESS, MIR_NULL_TYPE, MIR_NULL_STAMP, delay);
11,613✔
3235

3236
   MIR_ASSERT(mir_is_time(mu, delay), "delay argument is not a time");
11,613✔
3237
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
11,613✔
3238
              "sched process only allowed in process or procedure");
3239
}
11,613✔
3240

3241
void mir_build_sched_inactive(mir_unit_t *mu)
92✔
3242
{
3243
   mir_build_0(mu, MIR_OP_SCHED_INACTIVE, MIR_NULL_TYPE, MIR_NULL_STAMP);
92✔
3244

3245
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
92✔
3246
              "sched inactive only allowed in process or procedure");
3247
}
92✔
3248

3249
mir_value_t mir_build_reflect_value(mir_unit_t *mu, mir_value_t value,
68✔
3250
                                    mir_value_t context, mir_value_t locus,
3251
                                    mir_value_t bounds)
3252
{
3253
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
68✔
3254

3255
   mir_value_t result;
68✔
3256
   if (mir_is_null(bounds))
68✔
3257
      result = mir_build_3(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
60✔
3258
                           value, context, locus);
3259
   else
3260
      result = mir_build_4(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
8✔
3261
                           value, context, locus, bounds);
3262

3263
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
68✔
3264
              "invalid reflect value context argument");
3265
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
68✔
3266
              "locus argument to reflect value must be a debug locus");
3267

3268
   return result;
68✔
3269
}
3270

3271
mir_value_t mir_build_reflect_subtype(mir_unit_t *mu, mir_value_t context,
68✔
3272
                                      mir_value_t locus, mir_value_t bounds)
3273
{
3274
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
68✔
3275

3276
   mir_value_t result;
68✔
3277
   if (mir_is_null(bounds))
68✔
3278
      result = mir_build_2(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
56✔
3279
                           context, locus);
3280
   else
3281
      result = mir_build_3(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
12✔
3282
                           context, locus, bounds);
3283

3284
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
68✔
3285
              "invalid reflect subtype context argument");
3286
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
68✔
3287
              "locus argument to reflect subtype must be a debug locus");
3288

3289
   return result;
68✔
3290
}
3291

3292
void mir_build_assert(mir_unit_t *mu, mir_value_t value, mir_value_t message,
19,671✔
3293
                      mir_value_t length, mir_value_t severity,
3294
                      mir_value_t locus, mir_value_t hint_left,
3295
                      mir_value_t hint_right)
3296
{
3297
   int64_t value_const;
19,671✔
3298
   if (mir_get_const(mu, value, &value_const) && value_const != 0) {
19,671✔
3299
      mir_comment(mu, "Always true assertion");
×
3300
      return;
×
3301
   }
3302

3303
   if (mir_is_null(hint_left))
19,671✔
3304
      mir_build_5(mu, MIR_OP_ASSERT, MIR_NULL_TYPE, MIR_NULL_STAMP,
11,539✔
3305
                  value, severity, message, length, locus);
3306
   else {
3307
      node_data_t *n = mir_add_node(mu, MIR_OP_ASSERT, MIR_NULL_TYPE,
16,264✔
3308
                                     MIR_NULL_STAMP, 7);
8,132✔
3309
      mir_set_arg(mu, n, 0, value);
8,132✔
3310
      mir_set_arg(mu, n, 1, severity);
8,132✔
3311
      mir_set_arg(mu, n, 2, message);
8,132✔
3312
      mir_set_arg(mu, n, 3, length);
8,132✔
3313
      mir_set_arg(mu, n, 4, locus);
8,132✔
3314
      mir_set_arg(mu, n, 5, hint_left);
8,132✔
3315
      mir_set_arg(mu, n, 6, hint_right);
8,132✔
3316

3317
      MIR_ASSERT(mir_is_scalar(mu, hint_left), "left hint must be scalar");
8,132✔
3318
      MIR_ASSERT(mir_is_scalar(mu, hint_right), "right hint must be scalar");
8,132✔
3319
   }
3320

3321
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
19,671✔
3322
   MIR_ASSERT(mir_is_null(message) || mir_is(mu, message, MIR_TYPE_POINTER),
19,671✔
3323
              "message parameter to assert is not a pointer");
3324
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
19,671✔
3325
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
19,671✔
3326
              "locus argument to report must be a debug locus");
3327
}
3328

3329
void mir_build_report(mir_unit_t *mu, mir_value_t message, mir_value_t length,
2,920✔
3330
                      mir_value_t severity, mir_value_t locus)
3331
{
3332
   mir_build_4(mu, MIR_OP_REPORT, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,920✔
3333
               severity, message, length, locus);
3334

3335
   MIR_ASSERT(mir_is(mu, message, MIR_TYPE_POINTER),
2,920✔
3336
              "message parameter to report is not a pointer");
3337
   MIR_ASSERT(mir_is_offset(mu, length), "length argument must be offset type");
2,920✔
3338
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,920✔
3339
              "locus argument to report must be a debug locus");
3340
}
2,920✔
3341

3342
mir_value_t mir_build_instance_name(mir_unit_t *mu, mir_value_t kind)
7,280✔
3343
{
3344
   mir_type_t type = mir_string_type(mu);
7,280✔
3345
   mir_value_t result = mir_build_1(mu, MIR_OP_INSTANCE_NAME, type,
7,280✔
3346
                                    MIR_NULL_STAMP, kind);
7,280✔
3347

3348
   MIR_ASSERT(mir_is_offset(mu, kind),
7,280✔
3349
              "kind argument to instance name must be offset");
3350

3351
   return result;
7,280✔
3352
}
3353

3354
void mir_build_enter_state(mir_unit_t *mu, mir_value_t state,
1,176✔
3355
                           mir_value_t strong)
3356
{
3357
   if (mir_is_null(strong))
1,176✔
3358
      mir_build_1(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP, state);
1,128✔
3359
   else
3360
      mir_build_2(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
48✔
3361
                  state, strong);
3362

3363
   MIR_ASSERT(mir_is_integral(mu, state), "state must have integer type");
1,176✔
3364
   MIR_ASSERT(mir_is_null(strong)
1,176✔
3365
              || mir_check_type(mu, strong, mir_bool_type(mu)),
3366
                "strong argument not is not boolean");
3367
}
1,176✔
3368

3369
mir_value_t mir_build_closure(mir_unit_t *mu, ident_t func, mir_type_t rtype,
17,069✔
3370
                              const mir_value_t *args, unsigned nargs)
3371
{
3372
   mir_type_t ctype = mir_closure_type(mu, rtype);
17,069✔
3373

3374
   node_data_t *n = mir_add_node(mu, MIR_OP_CLOSURE, ctype, MIR_NULL_STAMP,
17,069✔
3375
                                 nargs + 1);
3376
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
17,069✔
3377

3378
   for (int i = 0; i < nargs; i++)
35,714✔
3379
      mir_set_arg(mu, n, i + 1, args[i]);
18,645✔
3380

3381
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
17,069✔
3382
}
3383

3384
mir_value_t mir_build_resolution_wrapper(mir_unit_t *mu, mir_type_t type,
13,140✔
3385
                                         mir_value_t closure, mir_value_t nlits)
3386
{
3387
   mir_type_t rtype = mir_resolution_type(mu, type);
13,140✔
3388
   mir_value_t result = mir_build_2(mu, MIR_OP_RESOLUTION_WRAPPER, rtype,
13,140✔
3389
                                    MIR_NULL_STAMP, closure, nlits);
13,140✔
3390

3391
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
13,140✔
3392
              "first argument to resolution wrapper must be closure");
3393

3394
   return result;
13,140✔
3395
}
3396

3397
mir_value_t mir_build_debug_locus(mir_unit_t *mu, object_t *obj)
133,013✔
3398
{
3399
   node_data_t *n = mir_add_node(mu, MIR_OP_DEBUG_LOCUS, mir_locus_type(mu),
133,013✔
3400
                                 MIR_NULL_STAMP, 0);
133,013✔
3401
   n->locus = obj;
133,013✔
3402

3403
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
133,013✔
3404
}
3405

3406
mir_value_t mir_build_cast(mir_unit_t *mu, mir_type_t type, mir_value_t value)
161,805✔
3407
{
3408
   mir_type_t from = mir_get_type(mu, value);
161,805✔
3409
   if (mir_equals(from, type))
161,805✔
3410
      return value;
161,805✔
3411

3412
   const mir_class_t class = mir_get_class(mu, type);
122,094✔
3413
   const bool integral = (class == MIR_TYPE_OFFSET || class == MIR_TYPE_INT);
122,094✔
3414

3415
   int64_t cval;
122,094✔
3416
   if (integral && mir_get_const(mu, value, &cval))
122,094✔
3417
      return mir_const(mu, type, cval);
513✔
3418

3419
   if (class == MIR_TYPE_VEC2 || class == MIR_TYPE_VEC4) {
121,581✔
3420
      if (value.tag == MIR_TAG_NODE) {
39,769✔
3421
         node_data_t *n = mir_node_data(mu, value);
39,757✔
3422
         if (n->op == MIR_OP_CONST_VEC && mir_get_size(mu, type) <= 64) {
39,757✔
3423
            uint64_t abits = n->bits[0];
13,832✔
3424
            if (mir_get_signed(mu, n->type)) {
13,832✔
3425
               const int arg_size = mir_get_size(mu, n->type);
5,706✔
3426
               if (arg_size > 0 && arg_size < 64) {
5,706✔
3427
                  const int shift = 64 - arg_size;
5,706✔
3428
                  abits = ((int64_t)abits << shift) >> shift;
5,706✔
3429
               }
3430
            }
3431

3432
            const uint64_t bbits = (class == MIR_TYPE_VEC2 ? 0 : n->bits[1]);
13,832✔
3433
            return mir_const_vec(mu, type, abits, bbits);
13,832✔
3434
         }
3435
      }
3436
   }
3437
   else if (integral && mir_is_vector(mu, value)) {
81,812✔
3438
      node_data_t *n = mir_node_data(mu, value);
8,029✔
3439
      if (n->op == MIR_OP_CONST_VEC) {
8,029✔
3440
         MIR_ASSERT(n->bits[1] == 0, "X value in integral cast");
7,697✔
3441

3442
         if (mir_get_signed(mu, n->type)) {
7,697✔
3443
            const int arg_size = mir_get_size(mu, n->type);
7,444✔
3444
            if (arg_size > 0 && arg_size < 64) {
7,444✔
3445
               const int shift = 64 - arg_size;
7,444✔
3446
               const int64_t sext = ((int64_t)n->bits[0] << shift) >> shift;
7,444✔
3447
               return mir_const(mu, type, sext);
7,444✔
3448
            }
3449
         }
3450

3451
         return mir_const(mu, type, n->bits[0]);
253✔
3452
      }
3453
   }
3454

3455
   mir_stamp_t stamp = mir_stamp_cast(mu, type, mir_get_stamp(mu, value));
100,052✔
3456

3457
   mir_value_t result = mir_build_1(mu, MIR_OP_CAST, type, stamp, value);
100,052✔
3458

3459
#ifdef DEBUG
3460
   static const mir_class_t allowed[][2] = {
100,052✔
3461
      { MIR_TYPE_INT,    MIR_TYPE_OFFSET  },
3462
      { MIR_TYPE_OFFSET, MIR_TYPE_INT     },
3463
      { MIR_TYPE_INT,    MIR_TYPE_INT     },
3464
      { MIR_TYPE_INT,    MIR_TYPE_REAL    },
3465
      { MIR_TYPE_REAL,   MIR_TYPE_INT     },
3466
      { MIR_TYPE_REAL,   MIR_TYPE_OFFSET  },
3467
      { MIR_TYPE_REAL,   MIR_TYPE_REAL    },
3468
      { MIR_TYPE_ACCESS, MIR_TYPE_ACCESS  },
3469
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC2    },
3470
      { MIR_TYPE_VEC2,   MIR_TYPE_VEC4    },
3471
      { MIR_TYPE_VEC2,   MIR_TYPE_VEC2    },
3472
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC4    },
3473
      { MIR_TYPE_VEC2,   MIR_TYPE_INT     },
3474
      { MIR_TYPE_VEC2,   MIR_TYPE_OFFSET  },
3475
      { MIR_TYPE_INT,    MIR_TYPE_VEC2    },
3476
      { MIR_TYPE_INT,    MIR_TYPE_VEC4    },
3477
   };
3478

3479
   if (value.tag == MIR_TAG_CONST)
100,052✔
3480
      return result;
140✔
3481

3482
   const mir_class_t from_k = mir_get_class(mu, from);
99,912✔
3483

3484
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
441,183✔
3485
      if (from_k == allowed[i][0] && class == allowed[i][1])
441,183✔
3486
         return result;
99,912✔
3487
   }
3488

3489
   MIR_ASSERT(false, "invalid type conversion in cast");
×
3490
#else
3491
   return result;
3492
#endif
3493
}
3494

3495
void mir_build_debug_out(mir_unit_t *mu, mir_value_t value)
2✔
3496
{
3497
   mir_build_1(mu, MIR_OP_DEBUG_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
2✔
3498

3499
   MIR_ASSERT(mir_is_integral(mu, value), "argument must be integral");
2✔
3500
}
2✔
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