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

nickg / nvc / 16099227452

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

push

github

nickg
Handle underscores in Verilog decimal literals

Fixes #1230

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

598 existing lines in 16 files now uncovered.

71069 of 76969 relevant lines covered (92.33%)

564781.41 hits per line

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

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

18
#include "util.h"
19
#include "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)
9,413,077✔
35
{
36
   assert(block.tag == MIR_TAG_BLOCK);
9,413,077✔
37
   return AREF(mu->blocks, block.id);
9,413,077✔
38
}
39

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

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

50
   return b;
206,930✔
51
}
52

53
void mir_set_cursor(mir_unit_t *mu, mir_block_t block, unsigned pos)
1,959,752✔
54
{
55
   if (!mir_is_null(mu->cursor.block))
1,959,752✔
56
      mir_block_data(mu, mu->cursor.block)->last_loc = mu->cursor.loc;
1,887,313✔
57

58
   mu->cursor.block = block;
1,959,752✔
59
   mu->cursor.pos   = pos;
1,959,752✔
60

61
   if (mir_is_null(block))
1,959,752✔
62
      mu->cursor.loc = LOC_INVALID;
183✔
63
   else
64
      mu->cursor.loc = mir_block_data(mu, block)->last_loc;
1,959,569✔
65
}
1,959,752✔
66

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

72
   return mu->cursor.block;
70,609✔
73
}
74

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

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

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

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

94
void mir_compact(mir_unit_t *mu)
183✔
95
{
96
   for (int i = 0; i < mu->blocks.count; i++) {
367✔
97
      block_data_t *bd = &(mu->blocks.items[i]);
184✔
98
      if (bd->gap_pos == -1)
184✔
99
         continue;
38✔
100

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

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

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

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

123
unsigned mir_count_nodes(mir_unit_t *mu, mir_block_t block)
536,476✔
124
{
125
   if (mir_is_null(block))
536,476✔
126
      return mu->num_nodes;
71,490✔
127
   else
128
      return mir_block_data(mu, block)->num_nodes;
464,986✔
129
}
130

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

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

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

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

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

160
mir_op_t mir_get_op(mir_unit_t *mu, mir_value_t node)
3,519,475✔
161
{
162
   switch (node.tag) {
3,519,475✔
163
   case MIR_TAG_NODE:
3,492,597✔
164
      return mir_node_data(mu, node)->op;
3,492,597✔
165
   default:
166
      return _MIR_DELETED_OP;
167
   }
168
}
169

170
const loc_t *mir_get_loc(mir_unit_t *mu, mir_value_t node)
1,731,474✔
171
{
172
   switch (node.tag) {
1,731,474✔
173
   case MIR_TAG_NODE:
1,731,474✔
174
      return &(mir_node_data(mu, node)->loc);
1,731,474✔
UNCOV
175
   case MIR_TAG_NULL:
×
UNCOV
176
      return &(mu->cursor.loc);
×
177
   default:
×
178
      should_not_reach_here();
179
   }
180
}
181

182
unsigned mir_count_args(mir_unit_t *mu, mir_value_t node)
324,391✔
183
{
184
   return mir_node_data(mu, node)->nargs;
324,391✔
185
}
186

187
const mir_value_t *mir_get_args(mir_unit_t *mu, const node_data_t *nd)
5,600,071✔
188
{
189
   if (nd->nargs <= MIR_INLINE_ARGS)
5,600,071✔
190
      return nd->args;
2,933,805✔
191
   else {
192
      assert(nd->spilloff < mu->num_argspill);
2,666,266✔
193
      return mu->argspill + nd->spilloff;
2,666,266✔
194
   }
195
}
196

197
mir_value_t mir_get_arg(mir_unit_t *mu, mir_value_t node, unsigned nth)
5,592,778✔
198
{
199
   const node_data_t *nd = mir_node_data(mu, node);
5,592,778✔
200
   if (nth >= nd->nargs)
5,592,778✔
201
      return MIR_NULL_VALUE;
629✔
202
   else
203
      return mir_get_args(mu, nd)[nth];
5,592,149✔
204
}
205

206
mir_value_t mir_add_param(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
52,441✔
207
                          ident_t name)
208
{
209
   mir_value_t p = { .tag = MIR_TAG_PARAM, .id = mu->params.count };
52,441✔
210

211
   param_data_t pd = {
52,441✔
212
      .name  = name,
213
      .type  = type,
214
      .stamp = stamp,
215
   };
216
   APUSH(mu->params, pd);
52,441✔
217

218
   return p;
52,441✔
219
}
220

221
mir_value_t mir_add_var(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
92,965✔
222
                        ident_t name, mir_var_flags_t flags)
223
{
224
   mir_value_t v = { .tag = MIR_TAG_VAR, .id = mu->vars.count };
92,965✔
225

226
   mir_mem_t mem = MIR_MEM_STACK;
92,965✔
227
   if (flags & MIR_VAR_HEAP)
92,965✔
228
      mem = MIR_MEM_LOCAL;
1,476✔
229

230
   var_data_t vd = {
185,930✔
231
      .name    = name,
232
      .type    = type,
233
      .pointer = mir_get_var_pointer(mu, type),
92,965✔
234
      .stamp   = mir_pointer_stamp(mu, mem, stamp),
92,965✔
235
      .flags   = flags,
236
   };
237
   APUSH(mu->vars, vd);
92,965✔
238

239
   return v;
92,965✔
240
}
241

242
bool mir_is_terminator(mir_op_t op)
670✔
243
{
244
   switch (op) {
670✔
245
   case MIR_OP_RETURN:
246
   case MIR_OP_JUMP:
247
   case MIR_OP_COND:
248
   case MIR_OP_WAIT:
249
   case MIR_OP_CASE:
250
   case MIR_OP_PCALL:
251
   case MIR_OP_UNREACHABLE:
252
      return true;
253
   default:
472✔
254
      return false;
472✔
255
   }
256
}
257

258
bool mir_block_finished(mir_unit_t *mu, mir_block_t block)
568✔
259
{
260
   if (mir_is_null(block))
568✔
261
      block = mu->cursor.block;
456✔
262

263
   const block_data_t *bd = mir_block_data(mu, block);
568✔
264
   if (bd->num_nodes == 0)
568✔
265
      return false;
266

267
   return mir_is_terminator(mu->nodes[bd->nodes[bd->num_nodes - 1]].op);
476✔
268
}
269

270
static inline node_id_t mir_node_id(mir_unit_t *mu, node_data_t *n)
1,629,400✔
271
{
272
   assert(n >= mu->nodes && n < mu->nodes + mu->num_nodes);
1,629,400✔
273
   return n - mu->nodes;
1,629,400✔
274
}
275

276
static node_data_t *mir_alloc_node(mir_unit_t *mu)
1,689,238✔
277
{
278
   assert(!mir_is_null(mu->cursor.block));
1,689,238✔
279

280
   node_data_t *n;
1,689,238✔
281
   block_data_t *bd = mir_block_data(mu, mu->cursor.block);
1,689,238✔
282
   if (mu->cursor.pos >= bd->num_nodes) {
1,689,238✔
283
      // Append new node
284
      if (bd->num_nodes == bd->max_nodes) {
1,688,945✔
285
         bd->max_nodes = MAX(4, bd->num_nodes * 2);
393,462✔
286
         bd->nodes = xrealloc_array(bd->nodes, bd->max_nodes,
393,462✔
287
                                    sizeof(node_id_t));
288
      }
289

290
      if (mu->num_nodes == mu->max_nodes) {
1,688,945✔
291
         mu->max_nodes = MAX(8, mu->num_nodes * 2);
146,872✔
292
         mu->nodes = xrealloc_array(mu->nodes, mu->max_nodes,
146,872✔
293
                                    sizeof(node_data_t));
294
      }
295

296
      bd->nodes[bd->num_nodes++] = mu->num_nodes;
1,688,945✔
297
      n = &(mu->nodes[mu->num_nodes++]);
1,688,945✔
298
   }
299
   else {
300
      n = &(mu->nodes[bd->nodes[mu->cursor.pos]]);
293✔
301
      assert(n->op == _MIR_DELETED_OP);
293✔
302
   }
303

304
   return n;
1,689,238✔
305
}
306

307
static size_t mir_spill_args(mir_unit_t *mu, unsigned num)
119,126✔
308
{
309
   if (mu->num_argspill + num > mu->max_argspill) {
119,126✔
310
      mu->max_argspill = MAX(16, MAX(mu->num_argspill + num,
55,387✔
311
                                     mu->max_argspill * 2));
312
      mu->argspill = xrealloc_array(mu->argspill, mu->max_argspill,
55,387✔
313
                                    sizeof(mir_value_t));
314
   }
315

316
   const size_t off = mu->num_argspill;
119,126✔
317
   mu->num_argspill += num;
119,126✔
318
   return off;
119,126✔
319
}
320

321
static node_data_t *mir_add_node(mir_unit_t *mu, mir_op_t op, mir_type_t type,
1,689,238✔
322
                                 mir_stamp_t stamp, unsigned nargs)
323
{
324
   node_data_t *n = mir_alloc_node(mu);
1,689,238✔
325
   n->loc   = mu->cursor.loc;
1,689,238✔
326
   n->op    = op;
1,689,238✔
327
   n->type  = type;
1,689,238✔
328
   n->stamp = stamp;
1,689,238✔
329
   n->nargs = nargs;
1,689,238✔
330

331
   if (nargs > MIR_INLINE_ARGS)
1,689,238✔
332
      n->spilloff = mir_spill_args(mu, nargs);
119,126✔
333

334
   return n;
1,689,238✔
335
}
336

337
static mir_value_t mir_build_0(mir_unit_t *mu, mir_op_t op, mir_type_t type,
10,465✔
338
                               mir_stamp_t stamp)
339
{
340
   node_data_t *n = mir_add_node(mu, op, type, stamp, 0);
10,465✔
341
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
10,465✔
342
}
343

344
static mir_value_t mir_build_1(mir_unit_t *mu, mir_op_t op, mir_type_t type,
557,847✔
345
                               mir_stamp_t stamp, mir_value_t arg)
346
{
347
   node_data_t *n = mir_add_node(mu, op, type, stamp, 1);
557,847✔
348
   n->args[0] = arg;
557,847✔
349

350
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
557,847✔
351
}
352

353
static mir_value_t mir_build_2(mir_unit_t *mu, mir_op_t op, mir_type_t type,
445,645✔
354
                               mir_stamp_t stamp, mir_value_t arg1,
355
                               mir_value_t arg2)
356
{
357
   STATIC_ASSERT(MIR_INLINE_ARGS >= 2);
445,645✔
358

359
   node_data_t *n = mir_add_node(mu, op, type, stamp, 2);
445,645✔
360
   n->args[0] = arg1;
445,645✔
361
   n->args[1] = arg2;
445,645✔
362

363
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
445,645✔
364
}
365

366
static mir_value_t mir_build_3(mir_unit_t *mu, mir_op_t op, mir_type_t type,
264,271✔
367
                               mir_stamp_t stamp, mir_value_t arg1,
368
                               mir_value_t arg2, mir_value_t arg3)
369
{
370
   STATIC_ASSERT(MIR_INLINE_ARGS >= 3);
264,271✔
371

372
   node_data_t *n = mir_add_node(mu, op, type, stamp, 3);
264,271✔
373
   n->args[0] = arg1;
264,271✔
374
   n->args[1] = arg2;
264,271✔
375
   n->args[2] = arg3;
264,271✔
376

377
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
264,271✔
378
}
379

380
static mir_value_t mir_build_4(mir_unit_t *mu, mir_op_t op, mir_type_t type,
5,512✔
381
                               mir_stamp_t stamp, mir_value_t arg1,
382
                               mir_value_t arg2, mir_value_t arg3,
383
                               mir_value_t arg4)
384
{
385
   STATIC_ASSERT(MIR_INLINE_ARGS >= 4);
5,512✔
386

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

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

396
static mir_value_t mir_build_5(mir_unit_t *mu, mir_op_t op, mir_type_t type,
40,733✔
397
                               mir_stamp_t stamp, mir_value_t arg1,
398
                               mir_value_t arg2, mir_value_t arg3,
399
                               mir_value_t arg4, mir_value_t arg5)
400
{
401
   node_data_t *n = mir_add_node(mu, op, type, stamp, 5);
40,733✔
402
   n->nargs = 5;
40,733✔
403

404
   STATIC_ASSERT(MIR_INLINE_ARGS < 5);
40,733✔
405

406
   mu->argspill[n->spilloff + 0] = arg1;
40,733✔
407
   mu->argspill[n->spilloff + 1] = arg2;
40,733✔
408
   mu->argspill[n->spilloff + 2] = arg3;
40,733✔
409
   mu->argspill[n->spilloff + 3] = arg4;
40,733✔
410
   mu->argspill[n->spilloff + 4] = arg5;
40,733✔
411

412
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
40,733✔
413
}
414

415
static mir_value_t mir_build_6(mir_unit_t *mu, mir_op_t op, mir_type_t type,
34,341✔
416
                               mir_stamp_t stamp, mir_value_t arg1,
417
                               mir_value_t arg2, mir_value_t arg3,
418
                               mir_value_t arg4, mir_value_t arg5,
419
                               mir_value_t arg6)
420
{
421
   node_data_t *n = mir_add_node(mu, op, type, stamp, 6);
34,341✔
422

423
   STATIC_ASSERT(MIR_INLINE_ARGS < 6);
34,341✔
424

425
   mu->argspill[n->spilloff + 0] = arg1;
34,341✔
426
   mu->argspill[n->spilloff + 1] = arg2;
34,341✔
427
   mu->argspill[n->spilloff + 2] = arg3;
34,341✔
428
   mu->argspill[n->spilloff + 3] = arg4;
34,341✔
429
   mu->argspill[n->spilloff + 4] = arg5;
34,341✔
430
   mu->argspill[n->spilloff + 5] = arg6;
34,341✔
431

432
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
34,341✔
433
}
434

435
static mir_value_t mir_add_linkage(mir_unit_t *mu, ident_t ident)
174,723✔
436
{
437
   for (int i = 0; i < mu->linkage.count; i++) {
441,404✔
438
      if (mu->linkage.items[i] == ident)
339,570✔
439
         return (mir_value_t){ .tag = MIR_TAG_LINKAGE, .id = i };
72,889✔
440
   }
441

442
   mir_value_t link = { .tag = MIR_TAG_LINKAGE, .id = mu->linkage.count };
101,834✔
443

444
   APUSH(mu->linkage, ident);
101,834✔
445

446
   return link;
101,834✔
447
}
448

449
static mir_value_t mir_add_extvar(mir_unit_t *mu, ident_t ident)
5,811✔
450
{
451
   for (int i = 0; i < mu->extvars.count; i++) {
14,298✔
452
      if (mu->extvars.items[i] == ident)
10,165✔
453
         return (mir_value_t){ .tag = MIR_TAG_EXTVAR, .id = i };
1,678✔
454
   }
455

456
   mir_value_t var = { .tag = MIR_TAG_EXTVAR, .id = mu->extvars.count };
4,133✔
457

458
   APUSH(mu->extvars, ident);
4,133✔
459

460
   return var;
4,133✔
461
}
462

463
void mir_set_arg(mir_unit_t *mu, node_data_t *n, unsigned nth,
2,555,762✔
464
                 mir_value_t value)
465
{
466
   assert(nth < n->nargs);
2,555,762✔
467

468
   if (n->nargs <= MIR_INLINE_ARGS)
2,555,762✔
469
      n->args[nth] = value;
355,879✔
470
   else {
471
      assert(n->spilloff < mu->num_argspill);
2,199,883✔
472
      mu->argspill[n->spilloff + nth] = value;
2,199,883✔
473
   }
474
}
2,555,762✔
475

476
node_data_t *mir_node_data(mir_unit_t *mu, mir_value_t value)
15,377,743✔
477
{
478
   assert(value.tag == MIR_TAG_NODE);
15,377,743✔
479
   assert(value.id < mu->num_nodes);
15,377,743✔
480

481
   return &(mu->nodes[value.id]);
15,377,743✔
482
}
483

484
const param_data_t *mir_param_data(mir_unit_t *mu, mir_value_t value)
239,212✔
485
{
486
   assert(value.tag == MIR_TAG_PARAM);
239,212✔
487
   return AREF(mu->params, value.id);
239,212✔
488
}
489

490
const var_data_t *mir_var_data(mir_unit_t *mu, mir_value_t value)
515,113✔
491
{
492
   assert(value.tag == MIR_TAG_VAR);
515,113✔
493
   return AREF(mu->vars, value.id);
515,113✔
494
}
495

496
#ifdef DEBUG
497
void mir_comment(mir_unit_t *mu, const char *fmt, ...)
322✔
498
{
499
   va_list ap;
322✔
500
   va_start(ap, fmt);
322✔
501

502
   if (mu->comments == NULL)
322✔
503
      mu->comments = tb_new();
155✔
504

505
   mir_value_t value = { .tag = MIR_TAG_COMMENT, .id = tb_len(mu->comments) };
322✔
506

507
   tb_vprintf(mu->comments, fmt, ap);
322✔
508
   tb_append(mu->comments, '\0');
322✔
509

510
   va_end(ap);
322✔
511

512
   mir_build_1(mu, MIR_OP_COMMENT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
322✔
513
}
322✔
514
#endif
515

516
mir_saved_loc_t _mir_push_debug_info(mir_unit_t *mu, const loc_t *loc)
3,440✔
517
{
518
   mir_saved_loc_t result = { mu, mu->cursor.loc };
3,440✔
519
   mu->cursor.loc = *loc;
3,440✔
520
   return result;
3,440✔
521
}
522

523
bool mir_get_const(mir_unit_t *mu, mir_value_t value, int64_t *result)
5,552,997✔
524
{
525
   switch (value.tag) {
5,552,997✔
526
   case MIR_TAG_CONST:
4,894,279✔
527
      *result = (int64_t)value.id - SMALL_CONST_BIAS;
4,894,279✔
528
      return true;
4,894,279✔
529
   case MIR_TAG_ENUM:
272,637✔
530
      *result = value.id;
272,637✔
531
      return true;
272,637✔
532
   case MIR_TAG_NODE:
372,011✔
533
      {
534
         const node_data_t *n = mir_node_data(mu, value);
372,011✔
535
         if (n->op == MIR_OP_CONST) {
372,011✔
536
            *result = n->iconst;
10,724✔
537
            return true;
10,724✔
538
         }
539
         else
540
            return false;
541
      }
542
   default:
543
      return false;
544
   }
545
}
546

547
bool mir_get_const_real(mir_unit_t *mu, mir_value_t value, double *result)
167,962✔
548
{
549
   switch (value.tag) {
167,962✔
550
   case MIR_TAG_NODE:
124,978✔
551
      {
552
         const node_data_t *n = mir_node_data(mu, value);
124,978✔
553
         if (n->op == MIR_OP_CONST_REAL) {
124,978✔
554
            *result = n->dconst;
30,796✔
555
            return true;
30,796✔
556
         }
557
         else
558
            return false;
559
      }
560
   default:
561
      return false;
562
   }
563
}
564

565
mir_type_t mir_get_type(mir_unit_t *mu, mir_value_t value)
3,674,153✔
566
{
567
   switch (value.tag) {
3,674,153✔
568
   case MIR_TAG_NODE:
3,039,955✔
569
      return mir_node_data(mu, value)->type;
3,039,955✔
570
   case MIR_TAG_PARAM:
211,449✔
571
      return mir_param_data(mu, value)->type;
211,449✔
572
   case MIR_TAG_VAR:
237,922✔
573
      return mir_var_data(mu, value)->pointer;
237,922✔
574
   default:
184,827✔
575
      return MIR_NULL_TYPE;
184,827✔
576
   }
577
}
578

579
mir_stamp_t mir_get_stamp(mir_unit_t *mu, mir_value_t value)
734,320✔
580
{
581
   switch (value.tag) {
734,320✔
582
   case MIR_TAG_NODE:
565,881✔
583
      return mir_node_data(mu, value)->stamp;
565,881✔
584
   case MIR_TAG_PARAM:
27,746✔
585
      return mir_param_data(mu, value)->stamp;
27,746✔
586
   case MIR_TAG_VAR:
62,504✔
587
      return mir_var_data(mu, value)->stamp;
62,504✔
588
   case MIR_TAG_CONST:
78,189✔
589
      {
590
         const int64_t ival = (int64_t)value.id - SMALL_CONST_BIAS;
78,189✔
591
         return mir_int_stamp(mu, ival, ival);
78,189✔
592
      }
UNCOV
593
   default:
×
UNCOV
594
      return MIR_NULL_STAMP;
×
595
   }
596
}
597

598
mir_mem_t mir_get_mem(mir_unit_t *mu, mir_value_t value)
9,682✔
599
{
600
   mir_type_t type = mir_get_type(mu, value);
9,682✔
601
   if (mir_is_null(type))
9,682✔
602
      return MIR_MEM_NONE;
603

604
   switch (mir_type_data(mu, type)->class) {
7,841✔
605
   case MIR_TYPE_UARRAY:
606
   case MIR_TYPE_CARRAY:
607
   case MIR_TYPE_RECORD:
608
   case MIR_TYPE_POINTER:
609
   case MIR_TYPE_ACCESS:
610
      break;
6,123✔
611
   default:
612
      return MIR_MEM_NONE;
613
   }
614

615
   mir_stamp_t stamp = mir_get_stamp(mu, value);
6,123✔
616
   if (mir_is_null(stamp))
6,123✔
617
      return MIR_MEM_TOP;
618

619
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
732✔
620
   assert(sd->kind == MIR_STAMP_POINTER);
732✔
621

622
   return sd->u.pointer.memory;
732✔
623
}
624

625
ident_t mir_get_name(mir_unit_t *mu, mir_value_t value)
248,063✔
626
{
627
   switch (value.tag) {
248,063✔
628
   case MIR_TAG_PARAM:
17✔
629
      return mir_param_data(mu, value)->name;
17✔
630
   case MIR_TAG_VAR:
69,535✔
631
      return mir_var_data(mu, value)->name;
69,535✔
632
   case MIR_TAG_LINKAGE:
172,746✔
633
      return AGET(mu->linkage, value.id);
172,746✔
634
   case MIR_TAG_EXTVAR:
5,765✔
635
      return AGET(mu->extvars, value.id);
5,765✔
UNCOV
636
   case MIR_TAG_NULL:
×
UNCOV
637
      return mu->name;
×
638
   default:
639
      return NULL;
640
   }
641
}
642

643
void mir_set_result(mir_unit_t *mu, mir_type_t type)
32,177✔
644
{
645
   assert(mu->kind == MIR_UNIT_FUNCTION || mu->kind == MIR_UNIT_THUNK);
32,177✔
646
   mu->result = type;
32,177✔
647
}
32,177✔
648

649
mir_type_t mir_get_result(mir_unit_t *mu)
40,524✔
650
{
651
   return mu->result;
40,524✔
652
}
653

654
object_t *mir_get_locus(mir_unit_t *mu, mir_value_t value)
102,021✔
655
{
656
   switch (value.tag) {
102,021✔
657
   case MIR_TAG_NODE:
102,021✔
658
      {
659
         node_data_t *n = mir_node_data(mu, value);
102,021✔
660
         assert(n->op == MIR_OP_LOCUS);
102,021✔
661
         return n->locus;
102,021✔
662
      }
UNCOV
663
      break;
×
UNCOV
664
   default:
×
665
      should_not_reach_here();
666
   }
667
}
668

669
void mir_get_bits(mir_unit_t *mu, mir_value_t value, uint64_t *abits,
2,240✔
670
                  uint64_t *bbits)
671
{
672
   switch (value.tag) {
2,240✔
673
   case MIR_TAG_NODE:
2,240✔
674
      {
675
         node_data_t *n = mir_node_data(mu, value);
2,240✔
676
         assert(n->op == MIR_OP_CONST_VEC);
2,240✔
677

678
         *abits = n->bits[0];
2,240✔
679
         *bbits = n->bits[1];
2,240✔
680
      }
681
      break;
2,240✔
UNCOV
682
   default:
×
683
      should_not_reach_here();
684
   }
685
}
2,240✔
686

687
mir_var_flags_t mir_get_var_flags(mir_unit_t *mu, mir_value_t value)
51,713✔
688
{
689
   switch (value.tag) {
51,713✔
690
   case MIR_TAG_VAR:
51,713✔
691
      return mir_var_data(mu, value)->flags;
51,713✔
692
   default:
693
      return 0;
694
   }
695
}
696

697
mir_type_t mir_get_var_type(mir_unit_t *mu, mir_value_t value)
93,439✔
698
{
699
   switch (value.tag) {
93,439✔
700
   case MIR_TAG_VAR:
93,439✔
701
      return mir_var_data(mu, value)->type;
93,439✔
UNCOV
702
   default:
×
UNCOV
703
      return MIR_NULL_TYPE;
×
704
   }
705
}
706

707
bool mir_is_integral(mir_unit_t *mu, mir_value_t value)
186,753✔
708
{
709
   if (value.tag == MIR_TAG_CONST)
186,753✔
710
      return true;
711

712
   mir_type_t type = mir_get_type(mu, value);
117,190✔
713
   if (mir_is_null(type))
117,190✔
714
      return false;
715

716
   switch (mir_type_data(mu, type)->class) {
117,190✔
717
   case MIR_TYPE_INT:
718
   case MIR_TYPE_OFFSET:
719
      return true;
720
   default:
7,386✔
721
      return false;
7,386✔
722
   }
723
}
724

725
bool mir_is_numeric(mir_unit_t *mu, mir_value_t value)
10,862✔
726
{
727
   if (value.tag == MIR_TAG_CONST)
10,862✔
728
      return true;
729

730
   mir_type_t type = mir_get_type(mu, value);
10,798✔
731
   if (mir_is_null(type))
10,798✔
732
      return false;
733

734
   switch (mir_type_data(mu, type)->class) {
10,798✔
735
   case MIR_TYPE_INT:
736
   case MIR_TYPE_OFFSET:
737
   case MIR_TYPE_REAL:
738
   case MIR_TYPE_VEC2:
739
   case MIR_TYPE_VEC4:
740
      return true;
741
   default:
266✔
742
      return false;
266✔
743
   }
744
}
745

746
bool mir_is_scalar(mir_unit_t *mu, mir_value_t value)
200,167✔
747
{
748
   if (value.tag == MIR_TAG_CONST)
200,167✔
749
      return true;
750

751
   mir_type_t type = mir_get_type(mu, value);
186,811✔
752
   if (mir_is_null(type))
186,811✔
753
      return false;
754

755
   switch (mir_type_data(mu, type)->class) {
186,587✔
756
   case MIR_TYPE_INT:
757
   case MIR_TYPE_OFFSET:
758
   case MIR_TYPE_REAL:
759
   case MIR_TYPE_ACCESS:
760
   case MIR_TYPE_POINTER:
761
   case MIR_TYPE_UARRAY:
762
   case MIR_TYPE_SIGNAL:
763
   case MIR_TYPE_CONTEXT:
764
   case MIR_TYPE_RESOLUTION:
765
   case MIR_TYPE_FILE:
766
   case MIR_TYPE_TRIGGER:
767
   case MIR_TYPE_VEC2:
768
   case MIR_TYPE_VEC4:
769
      return true;
UNCOV
770
   default:
×
UNCOV
771
      return false;
×
772
   }
773
}
774

775
bool mir_is_vector(mir_unit_t *mu, mir_value_t value)
75,787✔
776
{
777
   mir_type_t type = mir_get_type(mu, value);
75,787✔
778
   if (mir_is_null(type))
75,787✔
779
      return false;
780

781
   switch (mir_type_data(mu, type)->class) {
75,787✔
782
   case MIR_TYPE_VEC2:
783
   case MIR_TYPE_VEC4:
784
      return true;
785
   default:
72,681✔
786
      return false;
72,681✔
787
   }
788
}
789

790
bool mir_is_bool(mir_unit_t *mu, mir_value_t value)
180,928✔
791
{
792
   if (value.tag == MIR_TAG_CONST)
180,928✔
793
      return value.id == SMALL_CONST_BIAS || value.id == SMALL_CONST_BIAS + 1;
50,161✔
794
   else
795
      return mir_equals(mir_get_type(mu, value), mir_bool_type(mu));
130,767✔
796
}
797

798
bool mir_is_time(mir_unit_t *mu, mir_value_t value)
7,380✔
799
{
800
   if (value.tag == MIR_TAG_CONST)
7,380✔
801
      return true;
802

803
   return mir_equals(mir_get_type(mu, value), mir_time_type(mu));
125✔
804
}
805

806
bool mir_is(mir_unit_t *mu, mir_value_t value, mir_class_t class)
827,579✔
807
{
808
   mir_type_t type = mir_get_type(mu, value);
827,579✔
809
   if (mir_is_null(type))
827,579✔
810
      return false;
811

812
   return mir_type_data(mu, type)->class == class;
795,021✔
813
}
814

815
bool mir_points_to(mir_unit_t *mu, mir_value_t value, mir_class_t class)
5,191✔
816
{
817
   mir_type_t type = mir_get_type(mu, value);
5,191✔
818
   if (mir_is_null(type))
5,191✔
819
      return false;
820

821
   const type_data_t *td = mir_type_data(mu, type);
5,191✔
822
   if (td->class != MIR_TYPE_POINTER)
5,191✔
823
      return false;
824

825
   return mir_type_data(mu, td->u.pointer)->class == class;
5,191✔
826
}
827

828
bool mir_is_signal(mir_unit_t *mu, mir_value_t value)
141,651✔
829
{
830
   return mir_is(mu, value, MIR_TYPE_SIGNAL);
141,651✔
831
}
832

833
bool mir_is_offset(mir_unit_t *mu, mir_value_t value)
213,384✔
834
{
835
   if (value.tag == MIR_TAG_CONST)
213,384✔
836
      return true;
837

838
   return mir_is(mu, value, MIR_TYPE_OFFSET);
56,415✔
839
}
840

841
bool mir_is_const(mir_unit_t *mu, mir_value_t value)
2,113,103✔
842
{
843
   switch (value.tag) {
2,113,103✔
844
   case MIR_TAG_CONST:
845
      return true;
846
   case MIR_TAG_NODE:
22,674✔
847
      {
848
         node_data_t *n = mir_node_data(mu, value);
22,674✔
849
         switch (n->op) {
22,674✔
850
         case MIR_OP_CONST:
851
         case MIR_OP_CONST_REAL:
852
         case MIR_OP_CONST_ARRAY:
853
         case MIR_OP_CONST_REP:
854
         case MIR_OP_CONST_RECORD:
855
         case MIR_OP_NULL:
856
            return true;
UNCOV
857
         default:
×
UNCOV
858
            return false;
×
859
         }
860
      }
861
   default:
×
UNCOV
862
      return false;
×
863
   }
864
}
865

866
bool mir_may_alias(mir_unit_t *mu, mir_value_t a, mir_value_t b)
5✔
867
{
868
   const mir_mem_t a_mem = mir_get_mem(mu, a);
5✔
869
   if (a_mem == MIR_MEM_NONE)
5✔
870
      return false;
871

872
   if (mir_equals(a, b))
5✔
873
      return true;
874

875
   const mir_mem_t b_mem = mir_get_mem(mu, b);
5✔
876
   if (b_mem == MIR_MEM_NONE)
5✔
877
      return false;
878

879
   if (a_mem == MIR_MEM_CONST || b_mem == MIR_MEM_CONST) {
5✔
880
      // Aliasing is only relevant in the presence of mutability
881
      return false;
882
   }
883

884
   return a_mem == b_mem || a_mem == MIR_MEM_TOP || b_mem == MIR_MEM_TOP;
3✔
885
}
886

887
#ifdef DEBUG
888
static bool mir_check_type(mir_unit_t *mu, mir_value_t value, mir_type_t type)
2,177,112✔
889
{
890
   if (value.tag == MIR_TAG_CONST) {
2,177,112✔
891
      const mir_class_t class = mir_type_data(mu, type)->class;
2,087,730✔
892
      return class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET;
2,087,730✔
893
   }
894
   else
895
      return mir_equals(mir_get_type(mu, value), type);
89,382✔
896
}
897
#endif
898

899
mir_value_t mir_enum(unsigned value)
311,060✔
900
{
901
   assert(value < MIR_ID_MAX);
311,060✔
902
   return (mir_value_t){ .tag = MIR_TAG_ENUM, .id = value };
311,060✔
903
}
904

905
mir_value_t mir_const(mir_unit_t *mu, mir_type_t type, int64_t value)
567,034✔
906
{
907
   mir_value_t result;
567,034✔
908
   if (value >= SMALL_CONST_MIN && value <= SMALL_CONST_MAX) {
567,034✔
909
      const unsigned biased = value + SMALL_CONST_BIAS;
556,926✔
910
      result = (mir_value_t){ .tag = MIR_TAG_CONST, .id = biased };
556,926✔
911
   }
912
   else {
913
      mir_stamp_t stamp = mir_int_stamp(mu, value, value);
10,108✔
914
      node_data_t *n = mir_add_node(mu, MIR_OP_CONST, type, stamp, 0);
10,108✔
915
      n->iconst = value;
10,108✔
916

917
      result = (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
10,108✔
918
   }
919

920
#ifdef DEBUG
921
   const mir_class_t class = mir_get_class(mu, type);
567,034✔
922
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_OFFSET,
567,034✔
923
              "constant must have integral type");
924
#endif
925

926
   return result;
567,034✔
927
}
928

929
mir_value_t mir_const_real(mir_unit_t *mu, mir_type_t type, double value)
29,805✔
930
{
931
   mir_stamp_t stamp = mir_real_stamp(mu, value, value);
29,805✔
932
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_REAL, type, stamp, 0);
29,805✔
933
   n->dconst = value;
29,805✔
934

935
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
29,805✔
936
}
937

938
mir_value_t mir_const_vec(mir_unit_t *mu, mir_type_t type, uint64_t abits,
2,251✔
939
                          uint64_t bbits)
940
{
941
   uint64_t mask = ~UINT64_C(0), size = mir_get_size(mu, type);
2,251✔
942
   if (size < 64)
2,251✔
943
      mask >>= 64 - size;
2,251✔
944

945
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_VEC, type, MIR_NULL_STAMP, 0);
2,251✔
946
   n->bits[0] = abits & mask;
2,251✔
947
   n->bits[1] = bbits & mask;
2,251✔
948

949
#ifdef DEBUG
950
   const type_data_t *td = mir_type_data(mu, type);
2,251✔
951
   MIR_ASSERT(td->class == MIR_TYPE_VEC2 || td->class == MIR_TYPE_VEC4,
2,251✔
952
              "constant vector must have vector type");
953
   MIR_ASSERT(bbits == 0 || td->class == MIR_TYPE_VEC4,
2,251✔
954
              "b-bits cannot be set for two-value vector");
955
#endif
956

957
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
2,251✔
958
}
959

960
mir_value_t mir_const_array(mir_unit_t *mu, mir_type_t type,
35,637✔
961
                            const mir_value_t *values, size_t count)
962
{
963
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
71,274✔
964
                                 MIR_NULL_STAMP, count);
35,637✔
965

966
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
35,637✔
967
              "constant array must have constrained array type");
968
   MIR_ASSERT(mir_get_size(mu, type) == count, "expected %d elements but "
35,637✔
969
              "have %zd", mir_get_size(mu, type), count);
970

971
   mir_type_t elem = mir_get_elem(mu, type);
35,637✔
972

973
   const bool integral = mir_get_class(mu, elem) == MIR_TYPE_INT;
35,637✔
974
   int64_t low = INT64_MAX, high = INT64_MIN;
35,637✔
975
   for (size_t i = 0; i < count; i++) {
2,132,152✔
976
      mir_set_arg(mu, n, i, values[i]);
2,096,515✔
977

978
      MIR_ASSERT(mir_check_type(mu, values[i], elem),
2,096,515✔
979
                 "element %zd has wrong type", i);
980
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %zd not const", i);
2,096,515✔
981

982
      int64_t cval;
2,096,515✔
983
      if (integral && mir_get_const(mu, values[i], &cval)) {
2,096,515✔
984
         low = MIN(low, cval);
2,074,624✔
985
         high = MAX(high, cval);
2,074,624✔
986
      }
987
   }
988

989
   mir_stamp_t stamp = MIR_NULL_STAMP;
35,637✔
990
   if (integral && low <= high)
35,637✔
991
      stamp = mir_int_stamp(mu, low, high);
34,752✔
992

993
   n->stamp = mir_pointer_stamp(mu, MIR_MEM_CONST, stamp);
35,637✔
994

995
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
35,637✔
996
}
997

998
mir_value_t mir_const_string(mir_unit_t *mu, const char *str)
5,822✔
999
{
1000
   int count = 0, low = UINT8_MAX, high = 0;
5,822✔
1001
   for (const char *p = str; *p; p++, count++) {
27,638✔
1002
      low = MIN(low, (unsigned char)*p);
21,816✔
1003
      high = MAX(high, (unsigned char)*p);
21,816✔
1004
   }
1005

1006
   mir_type_t t_char = mir_char_type(mu);
5,822✔
1007
   mir_type_t type = mir_carray_type(mu, count, t_char);
5,822✔
1008
   mir_stamp_t stamp = mir_int_stamp(mu, low, high);
5,822✔
1009

1010
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_ARRAY, type,
5,822✔
1011
                                 stamp, count);
1012

1013
   for (int i = 0; i < count; i++)
27,638✔
1014
      mir_set_arg(mu, n, i, mir_const(mu, t_char, (unsigned char)str[i]));
21,816✔
1015

1016
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
5,822✔
1017
}
1018

1019
mir_value_t mir_build_const_rep(mir_unit_t *mu, mir_type_t type,
423✔
1020
                                mir_value_t value, unsigned rep)
1021
{
1022
   mir_stamp_t stamp = mir_get_stamp(mu, value);
423✔
1023
   mir_value_t result = mir_build_2(mu, MIR_OP_CONST_REP, type, stamp,
423✔
1024
                                    value, mir_enum(rep));
1025

1026
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CARRAY,
423✔
1027
              "constant array must have constrained array class");
1028
   MIR_ASSERT(rep < MIR_ID_MAX, "repetitions out of range");
423✔
1029

1030
   return result;
423✔
1031
}
1032

1033
mir_value_t mir_const_record(mir_unit_t *mu, mir_type_t type,
2,667✔
1034
                             const mir_value_t *values, size_t count)
1035
{
1036
   node_data_t *n = mir_add_node(mu, MIR_OP_CONST_RECORD, type,
5,334✔
1037
                                 MIR_NULL_STAMP, count);
2,667✔
1038

1039
   DEBUG_ONLY(const type_data_t *td = mir_type_data(mu, type));
2,667✔
1040

1041
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
2,667✔
1042
              "const record must have record type");
1043
   MIR_ASSERT(td->u.record.count == count, "expected %u fields but have %zu",
2,667✔
1044
              td->u.record.count, count);
1045

1046
   for (int i = 0; i < count; i++) {
9,812✔
1047
      mir_set_arg(mu, n, i, values[i]);
7,145✔
1048

1049
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, values[i]),
7,145✔
1050
                               td->u.record.fields[i]),
1051
                 "wrong type for element %d", i);
1052
      MIR_ASSERT(mir_is_const(mu, values[i]), "element %d is not constant", i);
7,145✔
1053
   }
1054

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

1058
static mir_value_t mir_build_arith(mir_unit_t *mu, mir_op_t op, mir_type_t type,
72,842✔
1059
                                   mir_value_t left, mir_value_t right,
1060
                                   mir_value_t locus, mir_stamp_t stamp)
1061
{
1062
   mir_value_t result;
72,842✔
1063
   if (mir_is_null(locus))
72,842✔
1064
      result = mir_build_2(mu, op, type, stamp, left, right);
64,624✔
1065
   else
1066
      result = mir_build_3(mu, op, type, stamp, left, right, locus);
8,218✔
1067

1068
#ifdef DEBUG
1069
   switch (mir_get_class(mu, type)) {
72,842✔
1070
   case MIR_TYPE_INT:
72,840✔
1071
   case MIR_TYPE_REAL:
1072
   case MIR_TYPE_OFFSET:
1073
      {
1074
         mir_type_t ltype = mir_get_type(mu, left);
72,840✔
1075
         mir_type_t rtype = mir_get_type(mu, right);
72,840✔
1076

1077
         MIR_ASSERT(mir_is_null(ltype) || mir_is_null(rtype)
72,840✔
1078
                    || mir_equals(ltype, rtype),
1079
                    "arguments to %s are not the same type", mir_op_string(op));
1080
      }
1081
      break;
1082

1083
   case MIR_TYPE_VEC2:
2✔
1084
   case MIR_TYPE_VEC4:
1085
      {
1086
         const type_data_t *td = mir_type_data(mu, type);
2✔
1087
         const type_data_t *ltd = mir_type_data(mu, mir_get_type(mu, left));
2✔
1088
         const type_data_t *rtd = mir_type_data(mu, mir_get_type(mu, right));
2✔
1089

1090
         MIR_ASSERT(td->class == ltd->class && td->class == rtd->class,
2✔
1091
                    "cannot mix vector types");
1092
         MIR_ASSERT(td->u.vec.issigned == ltd->u.vec.issigned
2✔
1093
                    && td->u.vec.issigned == rtd->u.vec.issigned,
1094
                    "cannot mix vector signedness");
1095
         MIR_ASSERT(td->u.vec.size >= ltd->u.vec.size
2✔
1096
                    && td->u.vec.size >= rtd->u.vec.size,
1097
                    "implicit narrowing conversions are not allowed");
1098
      }
1099
      break;
1100

1101
   default:
UNCOV
1102
      MIR_ASSERT(false, "arithmetic is not allowed on this type");
×
1103
      break;
1104
   }
1105

1106
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
72,842✔
1107
              "locus argument to %s is not a locus", mir_op_string(op));
1108
#endif
1109

1110
   return result;
72,842✔
1111
}
1112

1113
static mir_value_t mir_build_add_op(mir_unit_t *mu, mir_op_t op,
24,869✔
1114
                                    mir_type_t type, mir_value_t left,
1115
                                    mir_value_t right, mir_value_t locus)
1116
{
1117
   int64_t lval, rval, cval;
24,869✔
1118
   const bool lconst = mir_get_const(mu, left, &lval);
24,869✔
1119
   const bool rconst = mir_get_const(mu, right, &rval);
24,869✔
1120

1121
   if (lconst && lval == 0)
24,869✔
UNCOV
1122
      return right;
×
1123
   else if (rconst && rval == 0)
24,869✔
1124
      return left;
1✔
1125
   else if (lconst && rconst && !__builtin_add_overflow(lval, rval, &cval))
24,868✔
1126
      return mir_const(mu, type, cval);
3✔
1127

1128
   double lreal, rreal;
24,865✔
1129
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
24,865✔
1130
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
24,865✔
1131

1132
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
24,865✔
1133
      return right;
1✔
1134
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
24,864✔
1135
      return left;
2✔
1136
   else if (lconst_real && rconst_real)
24,862✔
1137
      return mir_const_real(mu, type, lreal + rreal);
5✔
1138

1139
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
24,857✔
1140
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
24,857✔
1141
   mir_stamp_t stamp = mir_stamp_add(mu, lstamp, rstamp);
24,857✔
1142

1143
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
24,857✔
1144
}
1145

1146
mir_value_t mir_build_add(mir_unit_t *mu, mir_type_t type, mir_value_t left,
19,550✔
1147
                          mir_value_t right)
1148
{
1149
   return mir_build_add_op(mu, MIR_OP_ADD, type, left, right, MIR_NULL_VALUE);
19,550✔
1150
}
1151

1152
mir_value_t mir_build_trap_add(mir_unit_t *mu, mir_type_t type,
5,319✔
1153
                               mir_value_t left, mir_value_t right,
1154
                               mir_value_t locus)
1155
{
1156
   return mir_build_add_op(mu, MIR_OP_TRAP_ADD, type, left, right, locus);
5,319✔
1157
}
1158

1159
static mir_value_t mir_build_sub_op(mir_unit_t *mu, mir_op_t op,
40,303✔
1160
                                    mir_type_t type, mir_value_t left,
1161
                                    mir_value_t right, mir_value_t locus)
1162
{
1163
   int64_t lval, rval, cval;
40,303✔
1164
   const bool lconst = mir_get_const(mu, left, &lval);
40,303✔
1165
   const bool rconst = mir_get_const(mu, right, &rval);
40,303✔
1166

1167
   if (lconst && lval == 0)
40,303✔
1168
      return right;
4✔
1169
   else if (rconst && rval == 0)
40,299✔
1170
      return left;
4✔
1171
   else if (lconst && rconst && !__builtin_sub_overflow(lval, rval, &cval))
40,295✔
1172
      return mir_const(mu, type, cval);
25✔
1173
   else if (mir_equals(left, right))
40,270✔
1174
      return mir_get_class(mu, type) == MIR_TYPE_REAL
185✔
1175
         ? mir_const_real(mu, type, 0.0) : mir_const(mu, type, 0);
185✔
1176

1177
   double lreal, rreal;
40,085✔
1178
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
40,085✔
1179
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
40,085✔
1180

1181
   if (lconst_real && (lreal == 0.0 || lreal == -0.0))
40,085✔
UNCOV
1182
      return right;
×
1183
   else if (rconst_real && (rreal == 0.0 || rreal == -0.0))
40,085✔
1184
      return left;
5✔
1185
   else if (lconst_real && rconst_real)
40,080✔
UNCOV
1186
      return mir_const_real(mu, type, lreal - rreal);
×
1187

1188
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
40,080✔
1189
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
40,080✔
1190
   mir_stamp_t stamp = mir_stamp_sub(mu, lstamp, rstamp);
40,080✔
1191

1192
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
40,080✔
1193
}
1194

1195
mir_value_t mir_build_sub(mir_unit_t *mu, mir_type_t type, mir_value_t left,
38,088✔
1196
                          mir_value_t right)
1197
{
1198
   return mir_build_sub_op(mu, MIR_OP_SUB, type, left, right, MIR_NULL_VALUE);
38,088✔
1199
}
1200

1201
mir_value_t mir_build_trap_sub(mir_unit_t *mu, mir_type_t type,
1,723✔
1202
                               mir_value_t left, mir_value_t right,
1203
                               mir_value_t locus)
1204
{
1205
   return mir_build_sub_op(mu, MIR_OP_TRAP_SUB, type, left, right, locus);
1,723✔
1206
}
1207

1208
mir_value_t mir_build_neg(mir_unit_t *mu, mir_type_t type, mir_value_t value)
9,193✔
1209
{
1210
   int64_t cval;
9,193✔
1211
   if (mir_get_const(mu, value, &cval))
9,193✔
1212
      return mir_const(mu, type, -cval);
1✔
1213

1214
   mir_value_t result = mir_build_1(mu, MIR_OP_NEG, type,
9,192✔
1215
                                    MIR_NULL_STAMP, value);
9,192✔
1216

1217
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
9,192✔
1218

1219
   return result;
9,192✔
1220
}
1221

1222
mir_value_t mir_build_trap_neg(mir_unit_t *mu, mir_type_t type,
345✔
1223
                               mir_value_t value, mir_value_t locus)
1224
{
1225
   int64_t cval;
345✔
1226
   if (mir_get_const(mu, value, &cval) && cval >= 0)
345✔
UNCOV
1227
      return mir_const(mu, type, -cval);
×
1228
   // TODO: check if stamp bounds are non-negative
1229

1230
   mir_value_t result = mir_build_2(mu, MIR_OP_TRAP_NEG, type,
345✔
1231
                                    MIR_NULL_STAMP, value, locus);
345✔
1232

1233
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
345✔
1234
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
345✔
1235
              "locus argument must be debug locus");
1236

1237
   return result;
345✔
1238
}
1239

1240
mir_value_t mir_build_abs(mir_unit_t *mu, mir_type_t type, mir_value_t value)
987✔
1241
{
1242
   int64_t lconst;
987✔
1243
   if (mir_get_const(mu, value, &lconst))
987✔
UNCOV
1244
      return mir_const(mu, type, llabs(lconst));
×
1245

1246
   mir_value_t result = mir_build_1(mu, MIR_OP_ABS, type, MIR_NULL_STAMP,
987✔
1247
                                    value);
1248

1249
   MIR_ASSERT(mir_is_numeric(mu, value), "argument must be numeric");
987✔
1250

1251
   return result;
987✔
1252
}
1253

1254
static mir_value_t mir_build_mul_op(mir_unit_t *mu, mir_op_t op,
4,132✔
1255
                                    mir_type_t type, mir_value_t left,
1256
                                    mir_value_t right, mir_value_t locus)
1257
{
1258
   int64_t lval, rval, cval;
4,132✔
1259
   const bool lconst = mir_get_const(mu, left, &lval);
4,132✔
1260
   const bool rconst = mir_get_const(mu, right, &rval);
4,132✔
1261

1262
   if (lconst && lval == 0)
4,132✔
UNCOV
1263
      return left;
×
1264
   else if (rconst && rval == 0)
4,132✔
UNCOV
1265
      return right;
×
1266
   else if (lconst && rconst && !__builtin_mul_overflow(lval, rval, &cval))
4,132✔
UNCOV
1267
      return mir_const(mu, type, cval);
×
1268

1269
   double lreal, rreal;
4,132✔
1270
   const bool lconst_real = mir_get_const_real(mu, left, &lreal);
4,132✔
1271
   const bool rconst_real = mir_get_const_real(mu, right, &rreal);
4,132✔
1272

1273
   if (lconst_real && rconst_real)
4,132✔
1274
      return mir_const_real(mu, type, lreal * rreal);
192✔
1275

1276
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
3,940✔
1277
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
3,940✔
1278
   mir_stamp_t stamp = mir_stamp_mul(mu, lstamp, rstamp);
3,940✔
1279

1280
   return mir_build_arith(mu, op, type, left, right, locus, stamp);
3,940✔
1281
}
1282

1283
mir_value_t mir_build_mul(mir_unit_t *mu, mir_type_t type, mir_value_t left,
4,132✔
1284
                          mir_value_t right)
1285
{
1286
   return mir_build_mul_op(mu, MIR_OP_MUL, type, left, right, MIR_NULL_VALUE);
4,132✔
1287
}
1288

1289
mir_value_t mir_build_trap_mul(mir_unit_t *mu, mir_type_t type,
492✔
1290
                               mir_value_t left, mir_value_t right,
1291
                               mir_value_t locus)
1292
{
1293
   return mir_build_sub_op(mu, MIR_OP_TRAP_MUL, type, left, right, locus);
492✔
1294
}
1295

1296
mir_value_t mir_build_div(mir_unit_t *mu, mir_type_t type, mir_value_t left,
2,027✔
1297
                          mir_value_t right)
1298
{
1299
   int64_t lval, rval;
2,027✔
1300
   const bool lconst = mir_get_const(mu, left, &lval);
2,027✔
1301
   const bool rconst = mir_get_const(mu, right, &rval);
2,027✔
1302

1303
   if (lconst && rconst && rval != 0)
2,027✔
UNCOV
1304
      return mir_const(mu, type, lval / rval);
×
1305
   else if (rconst && rval == 1)
2,027✔
UNCOV
1306
      return left;
×
1307

1308
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
2,027✔
1309
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
2,027✔
1310
   mir_stamp_t stamp = mir_stamp_div(mu, lstamp, rstamp);
2,027✔
1311

1312
   return mir_build_arith(mu, MIR_OP_DIV, type, left, right,
2,027✔
1313
                          MIR_NULL_VALUE, stamp);
2,027✔
1314
}
1315

1316
mir_value_t mir_build_rem(mir_unit_t *mu, mir_type_t type, mir_value_t left,
887✔
1317
                          mir_value_t right)
1318
{
1319
   int64_t lval, rval;
887✔
1320
   const bool lconst = mir_get_const(mu, left, &lval);
887✔
1321
   const bool rconst = mir_get_const(mu, right, &rval);
887✔
1322

1323
   if (lconst && rconst && lval > 0 && rval > 0)
887✔
1324
      return mir_const(mu, type, lval % rval);
1✔
1325

1326
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
886✔
1327
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
886✔
1328
   mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
886✔
1329

1330
   return mir_build_arith(mu, MIR_OP_REM, type, left, right,
886✔
1331
                          MIR_NULL_VALUE, stamp);
886✔
1332
}
1333

1334
mir_value_t mir_build_mod(mir_unit_t *mu, mir_type_t type, mir_value_t left,
193✔
1335
                          mir_value_t right)
1336
{
1337
   int64_t lval, rval;
193✔
1338
   const bool lconst = mir_get_const(mu, left, &lval);
193✔
1339
   const bool rconst = mir_get_const(mu, right, &rval);
193✔
1340

1341
   if (lconst && rconst && lval > 0 && rval > 0)
193✔
UNCOV
1342
      return mir_const(mu, type, lval % rval);
×
1343

1344
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
193✔
1345
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
193✔
1346

1347
   if (!mir_is_null(lstamp) && !mir_is_null(rstamp)) {
193✔
1348
      const stamp_data_t *lsd = mir_stamp_data(mu, lstamp);
16✔
1349
      const stamp_data_t *rsd = mir_stamp_data(mu, rstamp);
16✔
1350

1351
      if (lsd->u.intg.low >= 0 && rsd->u.intg.low >= 0) {
16✔
1352
         // If both arguments are non-negative then rem is equivalent
1353
         // and cheaper to compute
1354
         mir_stamp_t stamp = mir_stamp_rem(mu, lstamp, rstamp);
1✔
1355
         return mir_build_arith(mu, MIR_OP_REM, type, left, right,
1✔
1356
                                MIR_NULL_VALUE, stamp);
1✔
1357
      }
1358
   }
1359

1360
   return mir_build_arith(mu, MIR_OP_MOD, type, left, right,
192✔
1361
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
192✔
1362
}
1363

1364
mir_value_t mir_build_exp(mir_unit_t *mu, mir_type_t type, mir_value_t left,
175✔
1365
                          mir_value_t right)
1366
{
1367
   return mir_build_arith(mu, MIR_OP_EXP, type, left, right,
350✔
1368
                          MIR_NULL_VALUE, MIR_NULL_STAMP);
175✔
1369
}
1370

1371
mir_value_t mir_build_trap_exp(mir_unit_t *mu, mir_type_t type,
684✔
1372
                               mir_value_t left, mir_value_t right,
1373
                               mir_value_t locus)
1374
{
1375
   int64_t rconst;
684✔
1376
   if (mir_get_const(mu, right, &rconst)) {
684✔
1377
      if (rconst == 0)
580✔
UNCOV
1378
         return mir_const(mu, type, 1);
×
1379
      else if (rconst == 1)
580✔
UNCOV
1380
         return left;
×
1381
   }
1382

1383
   mir_value_t result = mir_build_arith(mu, MIR_OP_TRAP_EXP, type, left, right,
684✔
1384
                                        locus, MIR_NULL_STAMP);
684✔
1385

1386
   MIR_ASSERT(mir_is_integral(mu, result),
684✔
1387
              "trapping exp may only be used with integer types");
1388

1389
   return result;
684✔
1390
}
1391

1392
static mir_value_t mir_build_logical(mir_unit_t *mu, mir_op_t op,
8,972✔
1393
                                     mir_type_t type, mir_value_t left,
1394
                                     mir_value_t right)
1395
{
1396
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP, left, right);
8,972✔
1397

1398
   MIR_ASSERT(mir_is_bool(mu, left), "left argument to %s is not bool",
8,972✔
1399
              mir_op_string(op));
1400
   MIR_ASSERT(mir_is_bool(mu, right), "right argument to %s is not bool",
8,972✔
1401
              mir_op_string(op));
1402

1403
   return result;
8,972✔
1404
}
1405

1406
mir_value_t mir_build_and(mir_unit_t *mu, mir_value_t left, mir_value_t right)
6,062✔
1407
{
1408
   int64_t lval, rval;
6,062✔
1409
   const bool lconst = mir_get_const(mu, left, &lval);
6,062✔
1410
   const bool rconst = mir_get_const(mu, right, &rval);
6,062✔
1411

1412
   mir_type_t t_bool = mir_bool_type(mu);
6,062✔
1413

1414
   if (lconst && rconst)
6,062✔
1415
      return mir_const(mu, t_bool, lval && rval);
23✔
1416
   else if (lconst)
6,048✔
UNCOV
1417
      return lval ? right : mir_const(mu, t_bool, 0);
×
1418
   else if (rconst)
6,048✔
1419
      return rval ? left : mir_const(mu, t_bool, 0);
2✔
1420

1421
   return mir_build_logical(mu, MIR_OP_AND, t_bool, left, right);
6,046✔
1422
}
1423

1424
mir_value_t mir_build_or(mir_unit_t *mu, mir_value_t left, mir_value_t right)
2,781✔
1425
{
1426
   int64_t lval, rval;
2,781✔
1427
   const bool lconst = mir_get_const(mu, left, &lval);
2,781✔
1428
   const bool rconst = mir_get_const(mu, right, &rval);
2,781✔
1429

1430
   mir_type_t t_bool = mir_bool_type(mu);
2,781✔
1431

1432
   if (lconst && rconst)
2,781✔
1433
      return mir_const(mu, t_bool, lval || rval);
3✔
1434
   else if (lconst)
2,779✔
1435
      return lval ? mir_const(mu, t_bool, 1) : right;
1✔
1436
   else if (rconst)
2,778✔
1437
      return rval ? mir_const(mu, t_bool, 1) : left;
1✔
1438

1439
   return mir_build_logical(mu, MIR_OP_OR, t_bool, left, right);
2,777✔
1440
}
1441

1442
mir_value_t mir_build_xor(mir_unit_t *mu, mir_value_t left, mir_value_t right)
151✔
1443
{
1444
   int64_t lval, rval;
151✔
1445
   const bool lconst = mir_get_const(mu, left, &lval);
151✔
1446
   const bool rconst = mir_get_const(mu, right, &rval);
151✔
1447

1448
   mir_type_t t_bool = mir_bool_type(mu);
151✔
1449
   if (lconst && rconst)
151✔
1450
      return mir_const(mu, t_bool, lval ^ rval);
1✔
1451
   else if (mir_equals(left, right))
150✔
1452
      return mir_const(mu, t_bool, 0);
1✔
1453

1454
   return mir_build_logical(mu, MIR_OP_XOR, t_bool, left, right);
149✔
1455
}
1456

1457
mir_value_t mir_build_not(mir_unit_t *mu, mir_value_t value)
3,601✔
1458
{
1459
   mir_type_t t_bool = mir_bool_type(mu);
3,601✔
1460

1461
   int64_t cval;
3,601✔
1462
   if (mir_get_const(mu, value, &cval))
3,601✔
1463
      return mir_const(mu, t_bool, !cval);
2✔
1464

1465
   if (mir_get_op(mu, value) == MIR_OP_NOT)
3,599✔
1466
      return mir_get_arg(mu, value, 0);
41✔
1467

1468
   mir_value_t result = mir_build_1(mu, MIR_OP_NOT, t_bool,
3,558✔
1469
                                    MIR_NULL_STAMP, value);
3,558✔
1470

1471
   MIR_ASSERT(mir_is_bool(mu, value), "argument to not is not bool");
3,558✔
1472

1473
   return result;
3,558✔
1474
}
1475

1476
mir_value_t mir_build_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_value_t left,
51,634✔
1477
                          mir_value_t right)
1478
{
1479
   int64_t lval, rval;
51,634✔
1480
   const bool lconst = mir_get_const(mu, left, &lval);
51,634✔
1481
   const bool rconst = mir_get_const(mu, right, &rval);
51,634✔
1482

1483
   mir_type_t t_bool = mir_bool_type(mu);
51,634✔
1484

1485
   if (lconst && rconst) {
51,634✔
1486
      switch (cmp) {
37✔
1487
      case MIR_CMP_EQ:  return mir_const(mu, t_bool, lval == rval);
3✔
1488
      case MIR_CMP_NEQ: return mir_const(mu, t_bool, lval != rval);
2✔
1489
      case MIR_CMP_LT:  return mir_const(mu, t_bool, lval < rval);
14✔
1490
      case MIR_CMP_GT:  return mir_const(mu, t_bool, lval > rval);
2✔
1491
      case MIR_CMP_GEQ: return mir_const(mu, t_bool, lval >= rval);
14✔
1492
      case MIR_CMP_LEQ: return mir_const(mu, t_bool, lval <= rval);
2✔
1493
      default: should_not_reach_here();
1494
      }
1495
   }
1496

1497
   mir_stamp_t lstamp = mir_get_stamp(mu, left);
51,597✔
1498
   mir_stamp_t rstamp = mir_get_stamp(mu, right);
51,597✔
1499
   mir_stamp_t stamp = mir_stamp_cmp(mu, cmp, lstamp, rstamp);
51,597✔
1500

1501
   int64_t sconst;
51,597✔
1502
   if (mir_stamp_const(mu, stamp, &sconst))
51,597✔
1503
      return mir_const(mu, t_bool, sconst);
3✔
1504

1505
   mir_value_t result = mir_build_3(mu, MIR_OP_CMP, t_bool,
51,594✔
1506
                                    stamp, mir_enum(cmp), left, right);
1507

1508
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
51,594✔
1509
                            mir_get_type(mu, right)),
1510
              "arguments to cmp are not the same type");
1511

1512
   return result;
51,594✔
1513
}
1514

1515
mir_value_t mir_build_pack(mir_unit_t *mu, mir_type_t type, mir_value_t arg)
713✔
1516
{
1517
   mir_value_t result = mir_build_1(mu, MIR_OP_PACK, type, MIR_NULL_STAMP, arg);
713✔
1518

1519
#ifdef DEBUG
1520
   const mir_class_t class = mir_get_class(mu, type);
713✔
1521
   MIR_ASSERT(class == MIR_TYPE_VEC2 || class == MIR_TYPE_VEC4,
713✔
1522
              "pack type must be vector");
1523
   MIR_ASSERT(mir_is(mu, arg, MIR_TYPE_POINTER)
713✔
1524
              || (mir_get_size(mu, type) == 1 && mir_is_integral(mu, arg)),
1525
              "pack argument must be pointer if size != 1");
1526
#endif
1527

1528
   return result;
713✔
1529
}
1530

1531
mir_value_t mir_build_unpack(mir_unit_t *mu, mir_value_t vec, uint8_t strength,
629✔
1532
                             mir_value_t dest)
1533
{
1534
   mir_value_t result = dest;
629✔
1535
   if (mir_is_null(dest))
629✔
1536
      result = mir_build_2(mu, MIR_OP_UNPACK, mir_logic_type(mu),
808✔
1537
                           MIR_NULL_STAMP, vec, mir_enum(strength));
404✔
1538
   else
1539
      mir_build_3(mu, MIR_OP_UNPACK, MIR_NULL_TYPE, MIR_NULL_STAMP,
225✔
1540
                  vec, mir_enum(strength), dest);
1541

1542
   MIR_ASSERT(mir_is_vector(mu, vec), "unpack argument must be vector");
629✔
1543
   MIR_ASSERT(mir_is_null(dest) || mir_points_to(mu, dest, MIR_TYPE_INT),
629✔
1544
              "unpack dest must be pointer to logic or null");
1545
   MIR_ASSERT(mir_get_size(mu, mir_get_type(mu, vec)) == 1
629✔
1546
              || !mir_is_null(dest),
1547
              "unpack dest must be non-null if wide vector");
1548
   MIR_ASSERT((strength & 3) == 0, "strength lower bits must be zero");
629✔
1549

1550
   return result;
629✔
1551
}
1552

1553
mir_value_t mir_build_binary(mir_unit_t *mu, mir_vec_op_t op, mir_type_t type,
528✔
1554
                             mir_value_t left, mir_value_t right)
1555
{
1556
   mir_type_t otype;
528✔
1557
   switch (op) {
528✔
1558
   case MIR_VEC_CASE_EQ:
344✔
1559
   case MIR_VEC_CASE_NEQ:
1560
   case MIR_VEC_LOG_AND:
1561
   case MIR_VEC_LOG_OR:
1562
      // XXX: these should be vec2
1563
   case MIR_VEC_LT:
1564
   case MIR_VEC_LEQ:
1565
   case MIR_VEC_GT:
1566
   case MIR_VEC_GEQ:
1567
   case MIR_VEC_LOG_EQ:
1568
   case MIR_VEC_LOG_NEQ:
1569
      otype = mir_vec4_type(mu, 1, false);
344✔
1570
      break;
344✔
1571
   default:
184✔
1572
      otype = type;
184✔
1573
   }
1574

1575
   mir_value_t result = mir_build_3(mu, MIR_OP_BINARY, otype, MIR_NULL_STAMP,
528✔
1576
                                    mir_enum(op), left, right);
1577

1578
   MIR_ASSERT(mir_is_vector(mu, result), "binary operation must be vector");
528✔
1579
   MIR_ASSERT(mir_check_type(mu, left, type), "left type does not match");
528✔
1580
   MIR_ASSERT(mir_check_type(mu, right, type), "right type does not match");
528✔
1581

1582
   return result;
528✔
1583
}
1584

1585
mir_value_t mir_build_unary(mir_unit_t *mu, mir_vec_op_t op, mir_type_t type,
56✔
1586
                            mir_value_t arg)
1587
{
1588
   mir_type_t otype;
56✔
1589
   switch (op) {
56✔
1590
   case MIR_VEC_LOG_NOT:
20✔
1591
      otype = mir_vec2_type(mu, 1, false);
20✔
1592
      break;
20✔
1593
   default:
36✔
1594
      otype = type;
36✔
1595
   }
1596

1597
   mir_value_t result = mir_build_2(mu, MIR_OP_UNARY, otype, MIR_NULL_STAMP,
56✔
1598
                                    mir_enum(op), arg);
1599

1600
   MIR_ASSERT(mir_is_vector(mu, result), "unary operation must be vector");
56✔
1601
   MIR_ASSERT(mir_check_type(mu, arg, type), "arg type does not match");
56✔
1602

1603
   return result;
56✔
1604
}
1605

1606
void mir_build_store(mir_unit_t *mu, mir_value_t dest, mir_value_t src)
121,119✔
1607
{
1608
   mir_type_t type = mir_get_type(mu, dest);
121,119✔
1609
   mir_type_t pointed = mir_get_pointer(mu, type);
121,119✔
1610

1611
   mir_build_2(mu, MIR_OP_STORE, pointed, MIR_NULL_STAMP, dest, src);
121,119✔
1612

1613
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
121,119✔
1614
              "store destination is not a pointer or variable");
1615
   MIR_ASSERT(mir_same_type(mu, pointed, mir_get_type(mu, src)),
121,119✔
1616
              "source and destination have different types");
1617
}
121,119✔
1618

1619
mir_value_t mir_build_load(mir_unit_t *mu, mir_value_t value)
176,114✔
1620
{
1621
   mir_type_t type = mir_get_type(mu, value);
176,114✔
1622
   mir_stamp_t stamp = mir_stamp_elem(mu, mir_get_stamp(mu, value));
176,114✔
1623
   mir_type_t pointed = mir_get_pointer(mu, type);
176,114✔
1624

1625
   mir_value_t result = mir_build_1(mu, MIR_OP_LOAD, pointed, stamp, value);
176,114✔
1626

1627
   MIR_ASSERT(!mir_is_null(type), "cannot load this value");
176,114✔
1628
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_POINTER,
176,114✔
1629
              "argument to load is not a pointer or variable");
1630
   MIR_ASSERT(mir_is_scalar(mu, result), "cannot load non-scalar type");
176,114✔
1631

1632
   return result;
176,114✔
1633
}
1634

1635
void mir_build_copy(mir_unit_t *mu, mir_value_t dest, mir_value_t src,
30,782✔
1636
                    mir_value_t count)
1637
{
1638
   int64_t cval;
30,782✔
1639
   if (!mir_is_null(count) && mir_get_const(mu, count, &cval) && cval == 0)
30,782✔
1640
      return;
293✔
1641
   else if (mir_equals(dest, src))
30,782✔
1642
      return;
1643

1644
   mir_type_t dtype = mir_get_type(mu, dest);
30,489✔
1645
   mir_type_t elem = mir_get_pointer(mu, dtype);
30,489✔
1646

1647
   if (mir_is_null(count))
30,489✔
1648
      mir_build_2(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src);
2,053✔
1649
   else
1650
      mir_build_3(mu, MIR_OP_COPY, elem, MIR_NULL_STAMP, dest, src, count);
28,436✔
1651

1652
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
30,489✔
1653
              "destination type is not a pointer");
1654
   MIR_ASSERT(mir_is(mu, src, MIR_TYPE_POINTER),
30,489✔
1655
              "source type is not a pointer");
1656
   MIR_ASSERT(mir_equals(mir_get_type(mu, src), dtype),
30,489✔
1657
              "source and destination types do not match");
1658
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
30,489✔
1659
              "count is not offset type");
1660
}
1661

1662
void mir_build_set(mir_unit_t *mu, mir_value_t dest, mir_value_t value,
7,597✔
1663
                   mir_value_t count)
1664
{
1665
   int64_t cval;
7,597✔
1666
   if (mir_get_const(mu, count, &cval) && cval == 0)
7,597✔
UNCOV
1667
      return;
×
1668

1669
   mir_type_t dtype = mir_get_type(mu, dest);
7,597✔
1670
   mir_type_t elem = mir_get_pointer(mu, dtype);
7,597✔
1671

1672
   mir_build_3(mu, MIR_OP_SET, elem, MIR_NULL_STAMP, dest, value, count);
7,597✔
1673

1674
   MIR_ASSERT(mir_is(mu, dest, MIR_TYPE_POINTER),
7,597✔
1675
              "destination type is not a pointer");
1676
   MIR_ASSERT(mir_is_scalar(mu, value), "memset value must have scalar type");
7,597✔
1677
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
7,597✔
1678
}
1679

1680
mir_value_t mir_build_alloc(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
9,472✔
1681
                            mir_value_t count)
1682
{
1683
   mir_type_t ptr = mir_pointer_type(mu, type);
9,472✔
1684
   mir_value_t result = mir_build_1(mu, MIR_OP_ALLOC, ptr, stamp, count);
9,472✔
1685

1686
   MIR_ASSERT(mir_get_class(mu, type) != MIR_TYPE_CARRAY,
9,472✔
1687
              "alloc element type cannot be array");
1688
   MIR_ASSERT(mir_is_offset(mu, count), "count must be offset type");
9,472✔
1689

1690
   return result;
9,472✔
1691
}
1692

1693
mir_value_t mir_build_null(mir_unit_t *mu, mir_type_t type)
5,714✔
1694
{
1695
   mir_value_t result = mir_build_0(mu, MIR_OP_NULL, type, MIR_NULL_STAMP);
5,714✔
1696

1697
#ifdef DEBUG
1698
   const mir_class_t class = mir_get_class(mu, type);
5,714✔
1699
   MIR_ASSERT(class == MIR_TYPE_POINTER || class == MIR_TYPE_FILE
5,714✔
1700
              || class == MIR_TYPE_ACCESS || class == MIR_TYPE_CONTEXT,
1701
              "null type must be file, access, context, or pointer");
1702
#endif
1703

1704
   return result;
5,714✔
1705
}
1706

1707
mir_value_t mir_build_new(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp,
854✔
1708
                          mir_value_t count)
1709
{
1710
   mir_type_t access = mir_access_type(mu, type);
854✔
1711

1712
   mir_value_t result;
854✔
1713
   if (mir_is_null(count))
854✔
1714
      result = mir_build_0(mu, MIR_OP_NEW, access, stamp);
118✔
1715
   else
1716
      result = mir_build_1(mu, MIR_OP_NEW, access, stamp, count);
736✔
1717

1718
#ifdef DEBUG
1719
   const mir_class_t class = mir_get_class(mu, type);
854✔
1720
   MIR_ASSERT(class == MIR_TYPE_INT || class == MIR_TYPE_RECORD
854✔
1721
              || class == MIR_TYPE_UARRAY || class == MIR_TYPE_ACCESS
1722
              || class == MIR_TYPE_REAL || class == MIR_TYPE_CONTEXT,
1723
              "new type must be int, real, record, access, or uarray");
1724
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
854✔
1725
              "new count must have offset type");
1726
#endif
1727

1728
   return result;
854✔
1729
}
1730

1731
mir_value_t mir_build_all(mir_unit_t *mu, mir_value_t access)
3,755✔
1732
{
1733
   mir_type_t type = mir_get_type(mu, access);
3,755✔
1734
   mir_stamp_t stamp = mir_get_stamp(mu, access);
3,755✔
1735
   mir_type_t pointed = mir_get_pointer(mu, type);
3,755✔
1736
   mir_value_t result = mir_build_1(mu, MIR_OP_ALL, pointed, stamp, access);
3,755✔
1737

1738
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_ACCESS,
3,755✔
1739
              "argument to all must be access type");
1740

1741
   return result;
3,755✔
1742
}
1743

1744
mir_value_t mir_build_address_of(mir_unit_t *mu, mir_value_t array)
43,096✔
1745
{
1746
   mir_type_t type = mir_get_type(mu, array);
43,096✔
1747
   mir_type_t pointer = mir_get_pointer(mu, type);
43,096✔
1748
   mir_stamp_t stamp = mir_get_stamp(mu, array);
43,096✔
1749

1750
   if (mir_is_null(pointer))
43,096✔
1751
      pointer = mir_pointer_type(mu, type);
1,946✔
1752

1753
   mir_value_t result = mir_build_1(mu, MIR_OP_ADDRESS_OF,
43,096✔
1754
                                    pointer, stamp, array);
1755

1756
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_CARRAY)
43,096✔
1757
              || mir_is(mu, array, MIR_TYPE_RECORD),
1758
              "argument to address of must be array or record");
1759

1760
   return result;
43,096✔
1761
}
1762

1763
mir_value_t mir_build_array_ref(mir_unit_t *mu, mir_value_t array,
49,700✔
1764
                                mir_value_t offset)
1765
{
1766
   mir_type_t type = mir_get_type(mu, array);
49,700✔
1767
   mir_stamp_t stamp = mir_get_stamp(mu, array);
49,700✔
1768

1769
   mir_value_t result = mir_build_2(mu, MIR_OP_ARRAY_REF, type, stamp,
49,700✔
1770
                                    array, offset);
1771

1772
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_POINTER) || mir_is_signal(mu, array),
49,700✔
1773
              "argument to array ref must be pointer or signal");
1774
   MIR_ASSERT(mir_is_offset(mu, offset),
49,700✔
1775
              "offset argument to array ref must be offset");
1776

1777
   return result;
49,700✔
1778
}
1779

1780
mir_value_t mir_build_record_ref(mir_unit_t *mu, mir_value_t record,
48,458✔
1781
                                 unsigned field)
1782
{
1783
   mir_type_t pointer = mir_get_type(mu, record);
48,458✔
1784

1785
   const type_data_t *td = mir_type_data(mu, mir_get_elem(mu, pointer));
48,458✔
1786

1787
   mir_type_t type = MIR_NULL_TYPE;
48,458✔
1788
   if (td->class == MIR_TYPE_RECORD && field < td->u.record.count)
48,458✔
1789
      type = td->u.record.fields[field + td->u.record.count];
48,458✔
1790

1791
   mir_value_t result = mir_build_2(mu, MIR_OP_RECORD_REF, type, MIR_NULL_STAMP,
48,458✔
1792
                                    record, mir_enum(field));
1793

1794
   MIR_ASSERT(mir_get_class(mu, pointer) == MIR_TYPE_POINTER,
48,458✔
1795
              "record ref argument must be pointer to record");
1796
   MIR_ASSERT(td->class == MIR_TYPE_RECORD,
48,458✔
1797
              "record ref argument must be pointer to record");
1798
   MIR_ASSERT(field < td->u.record.count, "field index %d out of range", field);
48,458✔
1799

1800
   return result;
48,458✔
1801
}
1802

1803
mir_value_t mir_build_wrap(mir_unit_t *mu, mir_value_t data,
42,975✔
1804
                           const mir_dim_t *dims, int ndims)
1805
{
1806
   mir_type_t type = mir_get_type(mu, data);
42,975✔
1807
   mir_stamp_t stamp = mir_get_stamp(mu, data);
42,975✔
1808

1809
   const type_data_t *td = mir_type_data(mu, type);
42,975✔
1810
   mir_type_t elem = td->class == MIR_TYPE_POINTER ? td->u.pointer : type;
42,975✔
1811

1812
   mir_type_t uarray = mir_uarray_type(mu, ndims, elem);
42,975✔
1813

1814
   node_data_t *n = mir_add_node(mu, MIR_OP_WRAP, uarray, stamp,
85,950✔
1815
                                  ndims * 3 + 1);
42,975✔
1816

1817
   mir_set_arg(mu, n, 0, data);
42,975✔
1818

1819
   for (int i = 0; i < ndims; i++) {
86,520✔
1820
      mir_set_arg(mu, n, i*3 + 1, dims[i].left);
43,545✔
1821
      mir_set_arg(mu, n, i*3 + 2, dims[i].right);
43,545✔
1822
      mir_set_arg(mu, n, i*3 + 3, dims[i].dir);
43,545✔
1823
   }
1824

1825
   MIR_ASSERT(td->class == MIR_TYPE_POINTER || td->class == MIR_TYPE_SIGNAL,
42,975✔
1826
              "wrapped data is not pointer or signal");
1827

1828
   for (int i = 0; i < ndims; i++) {
86,520✔
1829
      MIR_ASSERT(mir_is_integral(mu, dims[i].left),
43,545✔
1830
                 "dimension %d left bound must be integral", i + 1);
1831
      MIR_ASSERT(mir_is_integral(mu, dims[i].right),
43,545✔
1832
                 "dimension %d right bound must be integral", i + 1);
1833
      MIR_ASSERT(mir_is_bool(mu, dims[i].dir),
43,545✔
1834
                 "dimension %d direction must be bool", i + 1);
1835
   }
1836

1837
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
42,975✔
1838
}
1839

1840
mir_value_t mir_build_unwrap(mir_unit_t *mu, mir_value_t array)
37,452✔
1841
{
1842
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
37,452✔
1843
      return mir_get_arg(mu, array, 0);
2,362✔
1844

1845
   mir_type_t type = mir_get_type(mu, array);
35,090✔
1846
   mir_type_t pointer = mir_get_pointer(mu, type);
35,090✔
1847
   mir_stamp_t stamp = mir_get_stamp(mu, array);
35,090✔
1848

1849
   mir_value_t result = mir_build_1(mu, MIR_OP_UNWRAP, pointer, stamp, array);
35,090✔
1850

1851
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_UARRAY,
35,090✔
1852
              "unwrap argument must be uarray");
1853

1854
   return result;
35,090✔
1855
}
1856

1857
mir_value_t mir_build_uarray_len(mir_unit_t *mu, mir_value_t array, int dim)
29,022✔
1858
{
1859
   mir_type_t t_offset = mir_offset_type(mu);
29,022✔
1860
   mir_value_t result = mir_build_2(mu, MIR_OP_UARRAY_LEN, t_offset,
29,022✔
1861
                                    MIR_NULL_STAMP, array,
29,022✔
1862
                                    mir_const(mu, t_offset, dim));
1863

1864
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
29,022✔
1865
              "uarray len argument must be uarrray");
1866

1867
#ifdef DEBUG
1868
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
29,022✔
1869
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
29,022✔
1870
#endif
1871

1872
   return result;
29,022✔
1873
}
1874

1875
static mir_value_t mir_build_uarray_op(mir_unit_t *mu, mir_op_t op,
64,469✔
1876
                                       mir_type_t type, int arg_index,
1877
                                       mir_value_t array, int dim)
1878
{
1879
   if (mir_get_op(mu, array) == MIR_OP_WRAP)
64,469✔
1880
      return mir_get_arg(mu, array, 1 + (dim * 3) + arg_index);
1,855✔
1881

1882
   mir_value_t result = mir_build_2(mu, op, type, MIR_NULL_STAMP,
62,614✔
1883
                                    array, mir_enum(dim));
1884

1885
   MIR_ASSERT(mir_is(mu, array, MIR_TYPE_UARRAY),
62,614✔
1886
              "cannot use %s with non-uarray type", mir_op_string(op));
1887

1888
#ifdef DEBUG
1889
   const type_data_t *td = mir_type_data(mu, mir_get_type(mu, array));
62,614✔
1890
   MIR_ASSERT(dim >= 0 && dim < td->u.uarray.dims, "invalid dimension %d", dim);
62,614✔
1891
#endif
1892

1893
   return result;
62,614✔
1894
}
1895

1896
mir_value_t mir_build_uarray_left(mir_unit_t *mu, mir_value_t array, int dim)
22,885✔
1897
{
1898
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_LEFT, mir_offset_type(mu),
22,885✔
1899
                              0, array, dim);
1900
}
1901

1902
mir_value_t mir_build_uarray_right(mir_unit_t *mu, mir_value_t array, int dim)
18,785✔
1903
{
1904
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_RIGHT, mir_offset_type(mu),
18,785✔
1905
                              1, array, dim);
1906
}
1907

1908
mir_value_t mir_build_uarray_dir(mir_unit_t *mu, mir_value_t array, int dim)
22,799✔
1909
{
1910
   return mir_build_uarray_op(mu, MIR_OP_UARRAY_DIR, mir_bool_type(mu),
22,799✔
1911
                              2, array, dim);
1912
}
1913

1914
mir_value_t mir_build_range_length(mir_unit_t *mu, mir_value_t left,
9,038✔
1915
                                   mir_value_t right, mir_value_t dir)
1916
{
1917
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_LENGTH,
9,038✔
1918
                                    mir_offset_type(mu), MIR_NULL_STAMP,
9,038✔
1919
                                    left, right, dir);
1920

1921
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
9,038✔
1922
                            mir_get_type(mu, right)),
1923
              "left and right are not the same type");
1924
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
9,038✔
1925
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
9,038✔
1926

1927
   return result;
9,038✔
1928
}
1929

1930
mir_value_t mir_build_range_null(mir_unit_t *mu, mir_value_t left,
4,321✔
1931
                                 mir_value_t right, mir_value_t dir)
1932
{
1933
   mir_value_t result = mir_build_3(mu, MIR_OP_RANGE_NULL,
4,321✔
1934
                                    mir_bool_type(mu), MIR_NULL_STAMP,
4,321✔
1935
                                    left, right, dir);
1936

1937
   MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, left),
4,321✔
1938
                            mir_get_type(mu, right)),
1939
              "left and right are not the same type");
1940
   MIR_ASSERT(mir_is_integral(mu, left), "left/right type is not integeral");
4,321✔
1941
   MIR_ASSERT(mir_is_bool(mu, dir), "dir type is not bool");
4,321✔
1942

1943
   return result;
4,321✔
1944
}
1945

1946
void mir_build_jump(mir_unit_t *mu, mir_block_t target)
51,214✔
1947
{
1948
   mir_build_1(mu, MIR_OP_JUMP, MIR_NULL_TYPE, MIR_NULL_STAMP,
51,214✔
1949
               mir_cast_value(target));
51,214✔
1950

1951
   MIR_ASSERT(!mir_is_null(target), "invalid jump target");
51,214✔
1952
}
51,214✔
1953

1954
void mir_build_cond(mir_unit_t *mu, mir_value_t test, mir_block_t btrue,
47,090✔
1955
                    mir_block_t bfalse)
1956
{
1957
   int64_t tconst;
47,090✔
1958
   if (mir_get_const(mu, test, &tconst)) {
47,090✔
1959
      mir_build_jump(mu, !!tconst ? btrue : bfalse);
23✔
1960
      return;
23✔
1961
   }
1962

1963
   mir_build_3(mu, MIR_OP_COND, MIR_NULL_TYPE, MIR_NULL_STAMP,
47,067✔
1964
               test, mir_cast_value(btrue), mir_cast_value(bfalse));
47,067✔
1965

1966
   MIR_ASSERT(mir_is_bool(mu, test), "cond test is not a bool");
47,067✔
1967
   MIR_ASSERT(!mir_is_null(btrue) && !mir_is_null(bfalse),
47,067✔
1968
              "invalid cond targets");
1969
}
1970

1971
mir_value_t mir_build_select(mir_unit_t *mu, mir_type_t type, mir_value_t test,
18,175✔
1972
                             mir_value_t vtrue, mir_value_t vfalse)
1973
{
1974
   int64_t tconst;
18,175✔
1975
   if (mir_get_const(mu, test, &tconst))
18,175✔
1976
      return tconst ? vtrue : vfalse;
151✔
1977
   else if (mir_equals(vtrue, vfalse))
18,024✔
1978
      return vtrue;
1✔
1979

1980
   mir_stamp_t s_true = mir_get_stamp(mu, vtrue);
18,023✔
1981
   mir_stamp_t s_false = mir_get_stamp(mu, vfalse);
18,023✔
1982
   mir_stamp_t stamp = mir_stamp_union(mu, s_true, s_false);
18,023✔
1983

1984
   mir_value_t result = mir_build_3(mu, MIR_OP_SELECT, type, stamp, test,
18,023✔
1985
                                    vtrue, vfalse);
1986

1987
   MIR_ASSERT(mir_is_bool(mu, test), "select test is not a bool");
18,023✔
1988
   MIR_ASSERT(mir_check_type(mu, vtrue, type),
18,023✔
1989
              "true argument to select is not expected type");
1990
   MIR_ASSERT(mir_check_type(mu, vfalse, type),
18,023✔
1991
              "false argument to select is not expected type");
1992

1993
   return result;
18,023✔
1994
}
1995

1996
mir_value_t mir_build_phi(mir_unit_t *mu, mir_type_t type, unsigned ninputs)
1✔
1997
{
1998
   node_data_t *n = mir_add_node(mu, MIR_OP_PHI, type, MIR_NULL_STAMP,
1✔
1999
                                 ninputs * 2);
2000

2001
   for (int i = 0; i < ninputs; i++)
3✔
2002
      mir_set_arg(mu, n, i, MIR_NULL_VALUE);
2✔
2003

2004
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
1✔
2005
}
2006

2007
void mir_set_input(mir_unit_t *mu, mir_value_t phi, unsigned nth,
2✔
2008
                   mir_block_t block, mir_value_t value)
2009
{
2010
   node_data_t *n = mir_node_data(mu, phi);
2✔
2011
   assert(n->op == MIR_OP_PHI);
2✔
2012
   assert(nth * 2 < n->nargs);
2✔
2013

2014
   mir_set_arg(mu, n, nth * 2,  mir_cast_value(block));
2✔
2015
   mir_set_arg(mu, n, nth * 2 + 1, value);
2✔
2016

2017
   n->stamp = mir_stamp_union(mu, n->stamp, mir_get_stamp(mu, value));
2✔
2018

2019
   MIR_ASSERT(mir_equals(n->type, mir_get_type(mu, value)),
2✔
2020
              "phi input %d has wrong type", nth);
2021

2022
#ifdef DEBUG
2023
   if (value.tag != MIR_TAG_CONST) {
2✔
2024
      const block_data_t *bd = mir_block_data(mu, block);
2✔
2025
      for (int i = 0; i < bd->num_nodes; i++) {
2✔
2026
         if (bd->nodes[i] == value.id)
2✔
2027
         return;
2028
      }
2029

UNCOV
2030
      MIR_ASSERT(false, "phi input %d not in block %d", nth, block.id);
×
2031
   }
2032
#endif
2033
}
2034

2035
void mir_build_case(mir_unit_t *mu, mir_value_t value, mir_block_t def,
968✔
2036
                    const mir_value_t *cases, const mir_block_t *blocks,
2037
                    int ncases)
2038
{
2039
   int64_t cval;
968✔
2040
   if (mir_get_const(mu, value, &cval)) {
968✔
2041
      for (int i = 0; i < ncases; i++) {
3✔
2042
         int64_t cmp;
2✔
2043
         if (mir_get_const(mu, cases[i], &cmp) && cmp == cval) {
2✔
2044
            mir_build_jump(mu, blocks[i]);
1✔
2045
            return;
1✔
2046
         }
2047
      }
2048

2049
      mir_build_jump(mu, def);
1✔
2050
      return;
1✔
2051
   }
2052

2053
   node_data_t *n = mir_add_node(mu, MIR_OP_CASE, MIR_NULL_TYPE,
1,932✔
2054
                                 MIR_NULL_STAMP, (ncases + 1) * 2);
966✔
2055

2056
   mir_set_arg(mu, n, 0, value);
966✔
2057
   mir_set_arg(mu, n, 1, mir_cast_value(def));
966✔
2058

2059
   for (int i = 0; i < ncases; i++) {
10,409✔
2060
      mir_set_arg(mu, n, (i + 1) * 2, cases[i]);
9,443✔
2061
      mir_set_arg(mu, n, (i + 1) * 2 + 1, mir_cast_value(blocks[i]));
9,443✔
2062
   }
2063

2064
   MIR_ASSERT(mir_is_integral(mu, value), "case choice must be integral");
966✔
2065

2066
#ifdef DEBUG
2067
   mir_type_t type = mir_get_type(mu, value);
966✔
2068
   for (int i = 0; i < ncases; i++) {
10,409✔
2069
      MIR_ASSERT(mir_is_const(mu, cases[i]), "case choice is not constant");
9,443✔
2070
      MIR_ASSERT(mir_same_type(mu, mir_get_type(mu, cases[i]), type),
9,443✔
2071
                 "choice and value types do not match");
2072

2073
      for (int j = 0; j < i; j++)
679,385✔
2074
         MIR_ASSERT(!mir_equals(cases[i], cases[j]), "duplicate case choice");
669,942✔
2075
   }
2076
#endif
2077
}
2078

2079
void mir_build_return(mir_unit_t *mu, mir_value_t value)
86,164✔
2080
{
2081
   if (mir_is_null(value))
86,164✔
2082
      mir_add_node(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, 0);
42,453✔
2083
   else
2084
      mir_build_1(mu, MIR_OP_RETURN, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
43,711✔
2085

2086
   MIR_ASSERT(mir_is_null(mu->result) || mir_check_type(mu, value, mu->result),
86,164✔
2087
              "wrong result type");
2088
   MIR_ASSERT(!mir_is_null(mu->result) || mu->kind == MIR_UNIT_PROPERTY
86,164✔
2089
              || mir_is_null(value), "cannot return a result");
2090
}
86,164✔
2091

2092
void mir_build_wait(mir_unit_t *mu, mir_block_t target, mir_value_t time)
18,714✔
2093
{
2094
   if (mir_is_null(time))
18,714✔
2095
      mir_build_1(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
11,334✔
2096
                  mir_cast_value(target));
11,334✔
2097
   else
2098
      mir_build_2(mu, MIR_OP_WAIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,380✔
2099
                  mir_cast_value(target), time);
7,380✔
2100

2101
   MIR_ASSERT(mir_is_null(time) || mir_is_time(mu, time),
18,714✔
2102
              "time argument to wait is not a time");
2103
   MIR_ASSERT(mu->kind == MIR_UNIT_PROCEDURE || mu->kind == MIR_UNIT_PROCESS,
18,714✔
2104
              "wait only allowed in process or procedure");
2105
}
18,714✔
2106

2107
void mir_build_consume(mir_unit_t *mu, mir_value_t value)
1✔
2108
{
2109
   if (value.tag != MIR_TAG_NODE)
1✔
2110
      return;   // Only useful for keeping nodes alive
2111

UNCOV
2112
   mir_build_1(mu, MIR_OP_CONSUME, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
2113
}
2114

2115
mir_value_t mir_build_fcall(mir_unit_t *mu, ident_t name, mir_type_t type,
45,908✔
2116
                            mir_stamp_t stamp, const mir_value_t *args,
2117
                            unsigned nargs)
2118
{
2119
   node_data_t *n = mir_add_node(mu, MIR_OP_FCALL, type, stamp, nargs + 1);
45,908✔
2120

2121
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
45,908✔
2122

2123
   for (int i = 0; i < nargs; i++)
173,183✔
2124
      mir_set_arg(mu, n, i + 1, args[i]);
127,275✔
2125

2126
   if (mir_is_null(type))
45,908✔
2127
      return MIR_NULL_VALUE;
6,712✔
2128
   else
2129
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
39,196✔
2130
}
2131

2132
void mir_build_pcall(mir_unit_t *mu, ident_t name, mir_block_t resume,
1,089✔
2133
                     const mir_value_t *args, unsigned nargs)
2134
{
2135
   node_data_t *n = mir_add_node(mu, MIR_OP_PCALL, MIR_NULL_TYPE,
2,178✔
2136
                                 MIR_NULL_STAMP, nargs + 2);
1,089✔
2137
   mir_set_arg(mu, n, 0, mir_cast_value(resume));
1,089✔
2138
   mir_set_arg(mu, n, 1, mir_add_linkage(mu, name));
1,089✔
2139

2140
   for (int i = 0; i < nargs; i++)
3,694✔
2141
      mir_set_arg(mu, n, i + 2, args[i]);
2,605✔
2142

2143
   MIR_ASSERT(nargs > 0 && mir_is(mu, args[0], MIR_TYPE_CONTEXT),
1,089✔
2144
              "first argument to VHDL procedure must be context pointer");
2145
}
1,089✔
2146

2147
void mir_build_resume(mir_unit_t *mu, ident_t name)
1,089✔
2148
{
2149
   mir_value_t link = mir_add_linkage(mu, name);
1,089✔
2150
   mir_build_1(mu, MIR_OP_RESUME, MIR_NULL_TYPE, MIR_NULL_STAMP, link);
1,089✔
2151

2152
   MIR_ASSERT(mir_count_nodes(mu, mu->cursor.block) == 1,
1,089✔
2153
              "resume must be first op in a block");
2154
}
1,089✔
2155

2156
mir_value_t mir_build_syscall(mir_unit_t *mu, ident_t func, mir_type_t type,
756✔
2157
                              mir_stamp_t stamp, mir_value_t locus,
2158
                              const mir_value_t *args, int nargs)
2159
{
2160
   node_data_t *n = mir_add_node(mu, MIR_OP_SYSCALL, type, stamp, nargs + 2);
756✔
2161

2162
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, func));
756✔
2163
   mir_set_arg(mu, n, 1, locus);
756✔
2164

2165
   for (int i = 0; i < nargs; i++)
964✔
2166
      mir_set_arg(mu, n, i + 2, args[i]);
208✔
2167

2168
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
756✔
2169
              "locus argument to syscall must be a debug locus");
2170

2171
   for (int i = 0; i < nargs; i++)
964✔
2172
      MIR_ASSERT(!mir_is_null(args[i]), "invalid argument to syscall");
208✔
2173

2174
   if (mir_is_null(type))
756✔
2175
      return MIR_NULL_VALUE;
704✔
2176
   else
2177
      return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
52✔
2178
}
2179

2180
void mir_build_unreachable(mir_unit_t *mu, mir_value_t locus)
1,707✔
2181
{
2182
   if (mir_is_null(locus))
1,707✔
2183
      mir_build_0(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP);
1,582✔
2184
   else
2185
      mir_build_1(mu, MIR_OP_UNREACHABLE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
125✔
2186

2187
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
1,707✔
2188
              "locus argument to unreachable must be debug locus");
2189
}
1,707✔
2190
static void mir_build_bounds_op(mir_unit_t *mu, mir_op_t op, mir_value_t value,
26,738✔
2191
                                mir_value_t left, mir_value_t right,
2192
                                mir_value_t dir, mir_value_t locus,
2193
                                mir_value_t hint)
2194
{
2195
   // TODO: check if can elide bounds
2196

2197
   mir_build_6(mu, op, MIR_NULL_TYPE, MIR_NULL_STAMP, value, left, right,
26,738✔
2198
               dir, locus, hint);
2199
}
26,738✔
2200

2201
void mir_build_range_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
5,695✔
2202
                           mir_value_t right, mir_value_t dir,
2203
                           mir_value_t locus, mir_value_t hint)
2204
{
2205
   mir_build_bounds_op(mu, MIR_OP_RANGE_CHECK, value, left, right, dir,
5,695✔
2206
                       locus, hint);
2207
}
5,695✔
2208

2209
void mir_build_index_check(mir_unit_t *mu, mir_value_t value, mir_value_t left,
21,043✔
2210
                           mir_value_t right, mir_value_t dir,
2211
                           mir_value_t locus, mir_value_t hint)
2212
{
2213
   mir_build_bounds_op(mu, MIR_OP_INDEX_CHECK, value, left, right, dir,
21,043✔
2214
                       locus, hint);
2215
}
21,043✔
2216

2217
void mir_build_null_check(mir_unit_t *mu, mir_value_t ptr, mir_value_t locus)
2,901✔
2218
{
2219
   mir_build_2(mu, MIR_OP_NULL_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,901✔
2220
               ptr, locus);
2221

2222
   MIR_ASSERT(mir_is(mu, ptr, MIR_TYPE_ACCESS),
2,901✔
2223
              "null check argument must be an access");
2224
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,901✔
2225
              "locus argument to null check must be a debug locus");
2226
}
2,901✔
2227

2228
void mir_build_zero_check(mir_unit_t *mu, mir_value_t value, mir_value_t locus)
119✔
2229
{
2230
   int64_t cval;
119✔
2231
   if (mir_get_const(mu, value, &cval) && cval != 0)
119✔
UNCOV
2232
      return;
×
2233

2234
   mir_build_2(mu, MIR_OP_ZERO_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
119✔
2235
               value, locus);
2236

2237
   MIR_ASSERT(mir_is_integral(mu, value),
119✔
2238
              "argument to zero check must be integral");
2239
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
119✔
2240
              "locus argument to zero check must be a debug locus");
2241
}
2242

2243
void mir_build_length_check(mir_unit_t *mu, mir_value_t llen, mir_value_t rlen,
9,538✔
2244
                            mir_value_t locus, mir_value_t dim)
2245
{
2246
   if (mir_equals(llen, rlen))
9,538✔
2247
      return;
2248

2249
   if (mir_is_null(dim))
9,538✔
2250
      mir_build_3(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
9,502✔
2251
                  llen, rlen, locus);
2252
   else
2253
      mir_build_4(mu, MIR_OP_LENGTH_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
36✔
2254
                  llen, rlen, locus, dim);
2255

2256
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
9,538✔
2257
              "locus argument to length check must be a debug locus");
2258
}
2259

2260
void mir_build_exponent_check(mir_unit_t *mu, mir_value_t exp,
660✔
2261
                              mir_value_t locus)
2262
{
2263
   int64_t cval;
660✔
2264
   if (mir_get_const(mu, exp, &cval) && cval >= 0)
660✔
UNCOV
2265
      return;
×
2266

2267
   mir_build_2(mu, MIR_OP_EXPONENT_CHECK, MIR_NULL_TYPE, MIR_NULL_STAMP,
660✔
2268
               exp, locus);
2269

2270
   MIR_ASSERT(mir_is_integral(mu, exp),
660✔
2271
              "exp argument to exponent check must be a integer");
2272
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
660✔
2273
              "locus argument to exponent check must be a debug locus");
2274
}
2275

2276
void mir_build_file_open(mir_unit_t *mu, mir_value_t file, mir_value_t name,
1,550✔
2277
                         mir_value_t length, mir_value_t kind,
2278
                         mir_value_t status)
2279
{
2280
   if (mir_is_null(status))
1,550✔
2281
      mir_build_4(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,517✔
2282
                  file, name, length, kind);
2283
   else
2284
      mir_build_5(mu, MIR_OP_FILE_OPEN, MIR_NULL_TYPE, MIR_NULL_STAMP,
33✔
2285
                  file, name, length, kind, status);
2286

2287
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
1,550✔
2288
              "file open first argument must be pointer to file");
2289
}
1,550✔
2290

2291
void mir_build_file_read(mir_unit_t *mu, mir_value_t file, mir_value_t ptr,
120✔
2292
                         mir_value_t inlen, mir_value_t outlen)
2293
{
2294
   if (mir_is_null(inlen))
120✔
2295
      mir_build_2(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
64✔
2296
                  file, ptr);
2297
   else if (mir_is_null(outlen))
56✔
2298
      mir_build_3(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
12✔
2299
                  file, ptr, inlen);
2300
   else
2301
      mir_build_4(mu, MIR_OP_FILE_READ, MIR_NULL_TYPE, MIR_NULL_STAMP,
44✔
2302
                  file, ptr, inlen, outlen);
2303

2304
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
120✔
2305
              "file read first argument must have file pointer type");
2306
   MIR_ASSERT(mir_is(mu, file, MIR_TYPE_POINTER),
120✔
2307
              "file read pointer argument must have pointer type");
2308
   MIR_ASSERT(mir_is_null(inlen) || mir_is_integral(mu, inlen),
120✔
2309
              "file read inlen argument must be integral");
2310
   MIR_ASSERT(mir_is_null(outlen) || mir_is(mu, outlen, MIR_TYPE_POINTER),
120✔
2311
              "file read outlen argument must have pointer type");
2312
}
120✔
2313

2314
void mir_build_file_write(mir_unit_t *mu, mir_value_t file, mir_value_t value,
339✔
2315
                          mir_value_t length)
2316
{
2317
   if (mir_is_null(length))
339✔
2318
      mir_build_2(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
76✔
2319
                  file, value);
2320
   else
2321
      mir_build_3(mu, MIR_OP_FILE_WRITE, MIR_NULL_TYPE, MIR_NULL_STAMP,
263✔
2322
                  file, value, length);
2323

2324
   MIR_ASSERT(mir_points_to(mu, file, MIR_TYPE_FILE),
339✔
2325
              "file write first argument must have file pointer type");
2326
}
339✔
2327

2328
mir_value_t mir_build_port_conversion(mir_unit_t *mu, mir_value_t driving,
375✔
2329
                                      mir_value_t effective)
2330
{
2331
   mir_type_t type = mir_conversion_type(mu);
375✔
2332

2333
   mir_value_t result;
375✔
2334
   if (mir_is_null(effective) || mir_equals(effective, driving))
375✔
2335
      result = mir_build_1(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
351✔
2336
                           driving);
2337
   else
2338
      result = mir_build_2(mu, MIR_OP_PORT_CONVERSION, type, MIR_NULL_STAMP,
24✔
2339
                           driving, effective);
2340

2341
   MIR_ASSERT(mir_is(mu, driving, MIR_TYPE_CLOSURE),
375✔
2342
              "port conversion argument must be a closure");
2343
   MIR_ASSERT(mir_is_null(effective) || mir_is(mu, effective, MIR_TYPE_CLOSURE),
375✔
2344
              "port conversion argument must be a closure");
2345

2346
   return result;
375✔
2347
}
2348

2349
void mir_build_convert_in(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
479✔
2350
                          mir_value_t count)
2351
{
2352
   mir_build_3(mu, MIR_OP_CONVERT_IN, MIR_NULL_TYPE, MIR_NULL_STAMP,
479✔
2353
               conv, nets, count);
2354

2355
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
479✔
2356
              "conv argument to convert must be a port conversion");
2357
   MIR_ASSERT(mir_is_signal(mu, nets),
479✔
2358
              "nets argument to convert must be a signal");
2359
   MIR_ASSERT(mir_is_offset(mu, count),
479✔
2360
              "count argument to convert must be offset");
2361
}
479✔
2362

2363
void mir_build_convert_out(mir_unit_t *mu, mir_value_t conv, mir_value_t nets,
535✔
2364
                           mir_value_t count)
2365
{
2366
   mir_build_3(mu, MIR_OP_CONVERT_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP,
535✔
2367
               conv, nets, count);
2368

2369
   MIR_ASSERT(mir_is(mu, conv, MIR_TYPE_CONVERSION),
535✔
2370
              "conv argument to convert must be a port conversion");
2371
   MIR_ASSERT(mir_is_signal(mu, nets),
535✔
2372
              "nets argument to convert must be a signal");
2373
   MIR_ASSERT(mir_is_offset(mu, count),
535✔
2374
              "count argument to convert must be offset");
2375
}
535✔
2376

2377
void mir_build_put_conversion(mir_unit_t *mu, mir_value_t cf,
556✔
2378
                              mir_value_t target, mir_value_t count,
2379
                              mir_value_t values)
2380
{
2381
   mir_build_4(mu, MIR_OP_PUT_CONVERSION, MIR_NULL_TYPE, MIR_NULL_STAMP,
556✔
2382
               cf, target, count, values);
2383

2384
   MIR_ASSERT(mir_is_signal(mu, target),
556✔
2385
              "put conversion target is not signal");
2386
   MIR_ASSERT(mir_is_offset(mu, count),
556✔
2387
              "put conversion net count is not offset type");
2388
   MIR_ASSERT(!mir_is_signal(mu, values),
556✔
2389
              "signal cannot be values argument for put conversion");
2390
   MIR_ASSERT(mir_is(mu, cf, MIR_TYPE_CONVERSION),
556✔
2391
              "cf argument to put conversion must be conversion function");
2392
}
556✔
2393

2394
mir_value_t mir_build_init_signal(mir_unit_t *mu, mir_type_t type,
21,337✔
2395
                                  mir_value_t count, mir_value_t size,
2396
                                  mir_value_t value, mir_value_t flags,
2397
                                  mir_value_t locus, mir_value_t offset)
2398
{
2399
   mir_type_t stype = mir_signal_type(mu, type);
21,337✔
2400

2401
   mir_value_t result;
21,337✔
2402
   if (mir_is_null(offset))
21,337✔
2403
      result = mir_build_5(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
13,842✔
2404
                           count, size, value, flags, locus);
2405
   else
2406
      result = mir_build_6(mu, MIR_OP_INIT_SIGNAL, stype, MIR_NULL_STAMP,
7,495✔
2407
                           count, size, value, flags, locus, offset);
2408

2409
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_INT
21,337✔
2410
              || mir_get_class(mu, type) == MIR_TYPE_REAL,
2411
              "signal must have integer or real type");
2412
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
21,337✔
2413
   MIR_ASSERT(mir_is_offset(mu, size), "size argument must be offset");
21,337✔
2414
   MIR_ASSERT(mir_is_offset(mu, flags), "flags argument must be offset");
21,337✔
2415
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
21,337✔
2416
              "locus argument to init signal is not debug locus");
2417
   MIR_ASSERT(mir_is_null(offset) || mir_is(mu, offset, MIR_TYPE_POINTER),
21,337✔
2418
              "offset argument must be pointer or null");
2419

2420
   return result;
21,337✔
2421
}
2422

2423
mir_value_t mir_build_implicit_signal(mir_unit_t *mu, mir_type_t type,
108✔
2424
                                      mir_value_t count, mir_value_t size,
2425
                                      mir_value_t locus, mir_value_t kind,
2426
                                      mir_value_t closure, mir_value_t delay)
2427
{
2428
   mir_type_t stype = mir_signal_type(mu, type);
108✔
2429

2430
   mir_value_t result = mir_build_6(mu, MIR_OP_IMPLICIT_SIGNAL, stype,
108✔
2431
                                    MIR_NULL_STAMP, count, size, locus,
108✔
2432
                                    kind, closure, delay);
2433

2434
   MIR_ASSERT(mir_is_offset(mu, count),
108✔
2435
              "count argument to implicit signal is not offset");
2436
   MIR_ASSERT(mir_is_offset(mu, kind),  // XXX: should be enum
108✔
2437
              "kind argument to implicit signal is not offset");
2438
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
108✔
2439
              "closure argument to implicit signal is not a closure");
2440
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
108✔
2441
              "locus argument to implicit signal must be a debug locus");
2442
   MIR_ASSERT(mir_is_integral(mu, delay),
108✔
2443
              "delay argument to implicit signal must be time");
2444

2445
   return result;
108✔
2446
}
2447

2448
void mir_build_drive_signal(mir_unit_t *mu, mir_value_t target,
12,602✔
2449
                            mir_value_t count)
2450
{
2451
   mir_build_2(mu, MIR_OP_DRIVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
12,602✔
2452
               target, count);
2453

2454
   MIR_ASSERT(mir_is_signal(mu, target), "target must be signal");
12,602✔
2455
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
12,602✔
2456
}
12,602✔
2457

2458
void mir_build_sched_waveform(mir_unit_t *mu, mir_value_t target,
14,450✔
2459
                              mir_value_t count, mir_value_t values,
2460
                              mir_value_t reject, mir_value_t after)
2461
{
2462
   int64_t nconst;
14,450✔
2463
   if (mir_get_const(mu, count, &nconst) && nconst == 0) {
14,450✔
UNCOV
2464
      mir_comment(mu, "Skip empty waveform");
×
UNCOV
2465
      return;
×
2466
   }
2467

2468
   mir_build_5(mu, MIR_OP_SCHED_WAVEFORM, MIR_NULL_TYPE, MIR_NULL_STAMP,
14,450✔
2469
               target, count, values, reject, after);
2470

2471
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
14,450✔
2472
   MIR_ASSERT(mir_is_offset(mu, count), "count is not offset type");
14,450✔
2473
   MIR_ASSERT(!mir_is_signal(mu, values), "values cannot be signal");
14,450✔
2474
}
2475

2476
void mir_build_deposit_signal(mir_unit_t *mu, mir_value_t target,
368✔
2477
                              mir_value_t count, mir_value_t values)
2478
{
2479
   mir_build_3(mu, MIR_OP_DEPOSIT_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
368✔
2480
               target, count, values);
2481

2482
   MIR_ASSERT(mir_is_signal(mu, target),
368✔
2483
              "deposit signal target is not signal");
2484
   MIR_ASSERT(mir_is_offset(mu, count),
368✔
2485
              "deposit signal count is not offset type");
2486
   MIR_ASSERT(!mir_is_signal(mu, values),
368✔
2487
              "signal cannot be values argument for deposit signal");
2488
}
368✔
2489

2490
mir_value_t mir_build_resolved(mir_unit_t *mu, mir_value_t signal)
19,464✔
2491
{
2492
   mir_type_t type = mir_get_type(mu, signal);
19,464✔
2493
   mir_type_t pointer = mir_get_pointer(mu, type);
19,464✔
2494
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
19,464✔
2495

2496
   mir_value_t result = mir_build_1(mu, MIR_OP_RESOLVED, pointer,
19,464✔
2497
                                    stamp, signal);
2498

2499
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
19,464✔
2500
              "argument to resolved must be signal");
2501

2502
   return result;
19,464✔
2503
}
2504

2505
mir_value_t mir_build_last_value(mir_unit_t *mu, mir_value_t signal)
277✔
2506
{
2507
   mir_type_t type = mir_get_type(mu, signal);
277✔
2508
   mir_type_t pointer = mir_get_pointer(mu, type);
277✔
2509
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
277✔
2510

2511
   mir_value_t result = mir_build_1(mu, MIR_OP_LAST_VALUE, pointer,
277✔
2512
                                    stamp, signal);
2513

2514
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_SIGNAL,
277✔
2515
              "argument to resolved must be signal");
2516

2517
   return result;
277✔
2518
}
2519

2520
mir_value_t mir_build_driving_value(mir_unit_t *mu, mir_value_t signal,
152✔
2521
                                    mir_value_t count)
2522
{
2523
   mir_type_t type = mir_get_pointer(mu, mir_get_type(mu, signal));
152✔
2524
   mir_stamp_t stamp = mir_get_stamp(mu, signal);
152✔
2525

2526
   mir_value_t result;
152✔
2527
   if (mir_is_null(count))
152✔
2528
      result = mir_build_1(mu, MIR_OP_DRIVING_VALUE, type, stamp, signal);
112✔
2529
   else
2530
      result = mir_build_2(mu, MIR_OP_DRIVING_VALUE, type, stamp,
40✔
2531
                           signal, count);
2532

2533
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
152✔
2534
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
152✔
2535
              "count argument must have offset type");
2536

2537
   return result;
152✔
2538
}
2539

2540
void mir_build_force(mir_unit_t *mu, mir_value_t target, mir_value_t count,
84✔
2541
                     mir_value_t values)
2542
{
2543
   mir_build_3(mu, MIR_OP_FORCE, MIR_NULL_TYPE, MIR_NULL_STAMP,
84✔
2544
               target, count, values);
2545

2546
   MIR_ASSERT(mir_is_signal(mu, target), "force target is not signal");
84✔
2547
   MIR_ASSERT(mir_is_offset(mu, count), "force count is not offset type");
84✔
2548
}
84✔
2549

2550
void mir_build_release(mir_unit_t *mu, mir_value_t target, mir_value_t count)
40✔
2551
{
2552
   mir_build_2(mu, MIR_OP_RELEASE, MIR_NULL_TYPE, MIR_NULL_STAMP,
40✔
2553
               target, count);
2554

2555
   MIR_ASSERT(mir_is_signal(mu, target), "release target is not signal");
40✔
2556
   MIR_ASSERT(mir_is_offset(mu, count), "release net count is not offset type");
40✔
2557
}
40✔
2558

2559
void mir_build_disconnect(mir_unit_t *mu, mir_value_t target, mir_value_t count,
32✔
2560
                          mir_value_t reject, mir_value_t after)
2561
{
2562
   mir_build_4(mu, MIR_OP_DISCONNECT, MIR_NULL_TYPE, MIR_NULL_STAMP,
32✔
2563
               target, count, reject, after);
2564

2565
   MIR_ASSERT(mir_is_signal(mu, target), "disconnect target is not signal");
32✔
2566
   MIR_ASSERT(mir_is_offset(mu, count), "disconnect count is not offset type");
32✔
2567
}
32✔
2568

2569

2570
mir_value_t mir_build_last_event(mir_unit_t *mu, mir_value_t signal,
44✔
2571
                                 mir_value_t count)
2572
{
2573
   mir_type_t type = mir_time_type(mu);
44✔
2574

2575
   mir_value_t result;
44✔
2576
   if (mir_is_null(count))
44✔
2577
      result = mir_build_1(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP, signal);
32✔
2578
   else
2579
      result = mir_build_2(mu, MIR_OP_LAST_EVENT, type, MIR_NULL_STAMP,
12✔
2580
                           signal, count);
2581

2582
   MIR_ASSERT(mir_is_signal(mu, signal),
44✔
2583
              "signal argument to last event must have signal type");
2584
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
44✔
2585
              "length argument to last event must have offset type");
2586

2587
   return result;
44✔
2588
}
2589

2590
mir_value_t mir_build_last_active(mir_unit_t *mu, mir_value_t signal,
48✔
2591
                                  mir_value_t count)
2592
{
2593
   mir_type_t type = mir_time_type(mu);
48✔
2594

2595
   mir_value_t result;
48✔
2596
   if (mir_is_null(count))
48✔
2597
      result = mir_build_1(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
40✔
2598
                           signal);
2599
   else
2600
      result = mir_build_2(mu, MIR_OP_LAST_ACTIVE, type, MIR_NULL_STAMP,
8✔
2601
                           signal, count);
2602

2603
   MIR_ASSERT(mir_is_signal(mu, signal),
48✔
2604
              "signal argument to last event must have signal type");
2605
   MIR_ASSERT(mir_is_null(count) || mir_is_offset(mu, count),
48✔
2606
              "length argument to last event must have offset type");
2607

2608
   return result;
48✔
2609
}
2610

2611

2612
static mir_value_t mir_build_signal_flag(mir_unit_t *mu, mir_op_t op,
1,095✔
2613
                                         mir_value_t signal, mir_value_t count)
2614
{
2615
   mir_type_t t_bool = mir_bool_type(mu);
1,095✔
2616
   mir_value_t result = mir_build_2(mu, op, t_bool, MIR_NULL_STAMP,
1,095✔
2617
                                    signal, count);
2618

2619
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument must be signal");
1,095✔
2620
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
1,095✔
2621

2622
   return result;
1,095✔
2623
}
2624

2625
mir_value_t mir_build_event_flag(mir_unit_t *mu, mir_value_t signal,
754✔
2626
                                 mir_value_t count)
2627
{
2628
   return mir_build_signal_flag(mu, MIR_OP_EVENT, signal, count);
754✔
2629
}
2630

2631
mir_value_t mir_build_active_flag(mir_unit_t *mu, mir_value_t signal,
293✔
2632
                                  mir_value_t count)
2633
{
2634
   return mir_build_signal_flag(mu, MIR_OP_ACTIVE, signal, count);
293✔
2635
}
2636

2637
mir_value_t mir_build_driving_flag(mir_unit_t *mu, mir_value_t signal,
48✔
2638
                                   mir_value_t count)
2639
{
2640
   return mir_build_signal_flag(mu, MIR_OP_DRIVING, signal, count);
48✔
2641
}
2642

2643
void mir_build_resolve_signal(mir_unit_t *mu, mir_value_t signal,
4,503✔
2644
                              mir_value_t resolution)
2645
{
2646
   mir_build_2(mu, MIR_OP_RESOLVE_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
4,503✔
2647
               signal, resolution);
2648

2649
   MIR_ASSERT(mir_is_signal(mu, signal), "signal argument has wrong type");
4,503✔
2650
   MIR_ASSERT(mir_points_to(mu, resolution, MIR_TYPE_RESOLUTION),
4,503✔
2651
              "resolution wrapper argument has wrong type");
2652
}
4,503✔
2653

2654
void mir_build_transfer_signal(mir_unit_t *mu, mir_value_t target,
1,606✔
2655
                               mir_value_t source, mir_value_t count,
2656
                               mir_value_t reject, mir_value_t after)
2657
{
2658
   mir_build_5(mu, MIR_OP_TRANSFER_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,606✔
2659
               target, source, count, reject, after);
2660

2661
   MIR_ASSERT(mir_is_signal(mu, target), "target is not a signal");
1,606✔
2662
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
1,606✔
2663
   MIR_ASSERT(mir_is_signal(mu, source), "source is not a signal");
1,606✔
2664
}
1,606✔
2665

2666
void mir_build_cover_stmt(mir_unit_t *mu, uint32_t tag)
1,374✔
2667
{
2668
   mir_build_1(mu, MIR_OP_COVER_STMT, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,374✔
2669
               mir_enum(tag));
2670
}
1,374✔
2671

2672
void mir_build_cover_branch(mir_unit_t *mu, uint32_t tag)
657✔
2673
{
2674
   mir_build_1(mu, MIR_OP_COVER_BRANCH, MIR_NULL_TYPE, MIR_NULL_STAMP,
657✔
2675
               mir_enum(tag));
2676
}
657✔
2677

2678
void mir_build_cover_expr(mir_unit_t *mu, uint32_t tag)
1,142✔
2679
{
2680
   mir_build_1(mu, MIR_OP_COVER_EXPR, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,142✔
2681
               mir_enum(tag));
2682
}
1,142✔
2683

2684
void mir_build_cover_toggle(mir_unit_t *mu, mir_value_t signal, uint32_t tag)
416✔
2685
{
2686
   mir_build_2(mu, MIR_OP_COVER_TOGGLE, MIR_NULL_TYPE, MIR_NULL_STAMP,
416✔
2687
               signal, mir_enum(tag));
2688

2689
   MIR_ASSERT(mir_is_signal(mu, signal),
416✔
2690
              "argument to cover toggle must be signal");
2691
}
416✔
2692

2693
void mir_build_cover_state(mir_unit_t *mu, mir_value_t signal, mir_value_t low,
16✔
2694
                           uint32_t tag)
2695
{
2696
   mir_build_3(mu, MIR_OP_COVER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
16✔
2697
               signal, low, mir_enum(tag));
2698

2699
   MIR_ASSERT(mir_is_signal(mu, signal),
16✔
2700
              "argument to cover state must be signal");
2701
}
16✔
2702
mir_value_t mir_build_package_init(mir_unit_t *mu, ident_t name,
34,314✔
2703
                                   mir_value_t context)
2704
{
2705
   mir_value_t link = mir_add_linkage(mu, name);
34,314✔
2706
   mir_type_t type = mir_context_type(mu, name);
34,314✔
2707

2708
   mir_value_t result;
34,314✔
2709
   if (mir_is_null(context))
34,314✔
2710
      result = mir_build_1(mu, MIR_OP_PACKAGE_INIT, type,
34,071✔
2711
                           MIR_NULL_STAMP, link);
34,071✔
2712
   else
2713
      result = mir_build_2(mu, MIR_OP_PACKAGE_INIT, type,
243✔
2714
                           MIR_NULL_STAMP, link, context);
243✔
2715

2716
   MIR_ASSERT(mir_is_null(context) || mir_is(mu, context, MIR_TYPE_CONTEXT),
34,314✔
2717
              "invalid package init context argument");
2718
   MIR_ASSERT(mu->kind == MIR_UNIT_INSTANCE
34,314✔
2719
              || mu->kind == MIR_UNIT_PACKAGE
2720
              || mu->kind == MIR_UNIT_THUNK,
2721
              "cannot use package init here");
2722
   MIR_ASSERT(name != mu->name, "cyclic package init");
34,314✔
2723

2724
   return result;
34,314✔
2725
}
2726

2727
void mir_build_process_init(mir_unit_t *mu, ident_t name, mir_value_t locus)
154✔
2728
{
2729
   mir_value_t link = mir_add_linkage(mu, name);
154✔
2730
   mir_build_2(mu, MIR_OP_PROCESS_INIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
154✔
2731
               link, locus);
2732

2733
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
154✔
2734
              "locus argument to process init must be a debug locus");
2735
}
154✔
2736

2737
mir_value_t mir_build_protected_init(mir_unit_t *mu, mir_type_t type,
719✔
2738
                                     mir_value_t context, mir_value_t path_name,
2739
                                     mir_value_t inst_name)
2740
{
2741
   mir_value_t link = mir_add_linkage(mu, mir_type_data(mu, type)->u.context);
719✔
2742

2743
   mir_value_t result;
719✔
2744
   if (mir_is_null(path_name) && mir_is_null(inst_name))
719✔
2745
      result = mir_build_2(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
171✔
2746
                           link, context);
2747
   else {
2748
      result = mir_build_4(mu, MIR_OP_PROTECTED_INIT, type, MIR_NULL_STAMP,
548✔
2749
                           link, context, path_name, inst_name);
2750

2751
      MIR_ASSERT(mir_is(mu, path_name, MIR_TYPE_UARRAY),
548✔
2752
                 "path name argument must be array");
2753
      MIR_ASSERT(mir_is(mu, inst_name, MIR_TYPE_UARRAY),
548✔
2754
                 "inst name argument must be array");
2755
   }
2756

2757
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_CONTEXT,
719✔
2758
                "protected init type must be context");
2759
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
719✔
2760
              "invalid protected init context argument");
2761

2762
   return result;
719✔
2763
}
2764

2765
void mir_build_record_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
2,153✔
2766
{
2767
   mir_build_1(mu, MIR_OP_RECORD_SCOPE, type, MIR_NULL_STAMP, locus);
2,153✔
2768

2769
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,153✔
2770
              "locus argument to record scope must be a debug locus");
2771
   MIR_ASSERT(mir_get_class(mu, type) == MIR_TYPE_RECORD,
2,153✔
2772
              "record scope type must be record");
2773
}
2,153✔
2774

2775
void mir_build_array_scope(mir_unit_t *mu, mir_value_t locus, mir_type_t type)
839✔
2776
{
2777
   mir_build_1(mu, MIR_OP_ARRAY_SCOPE, type, MIR_NULL_STAMP, locus);
839✔
2778

2779
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
839✔
2780
              "locus argument to array scope must be a debug locus");
2781
}
839✔
2782

2783
void mir_build_package_scope(mir_unit_t *mu, mir_value_t locus)
59✔
2784
{
2785
   mir_build_1(mu, MIR_OP_PACKAGE_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP, locus);
59✔
2786

2787
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
59✔
2788
              "locus argument to package scope must be a debug locus");
2789
}
59✔
2790

2791
void mir_build_pop_scope(mir_unit_t *mu)
3,051✔
2792
{
2793
   mir_build_0(mu, MIR_OP_POP_SCOPE, MIR_NULL_TYPE, MIR_NULL_STAMP);
3,051✔
2794
}
3,051✔
2795

2796
void mir_build_alias_signal(mir_unit_t *mu, mir_value_t signal,
5,570✔
2797
                            mir_value_t locus)
2798
{
2799
   mir_build_2(mu, MIR_OP_ALIAS_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
5,570✔
2800
               signal, locus);
2801

2802
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must have signal type");
5,570✔
2803
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
5,570✔
2804
              "locus argument must have debug locus type");
2805
}
5,570✔
2806

2807
void mir_build_map_signal(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
7,104✔
2808
                          mir_value_t count)
2809
{
2810
   mir_build_3(mu, MIR_OP_MAP_SIGNAL, MIR_NULL_TYPE, MIR_NULL_STAMP,
7,104✔
2811
               src, dst, count);
2812

2813
   MIR_ASSERT(mir_is_signal(mu, src),
7,104✔
2814
              "src argument to map signal is not a signal");
2815
   MIR_ASSERT(mir_is_signal(mu, dst),
7,104✔
2816
              "dst argument to map signal is not a signal");
2817
   MIR_ASSERT(mir_is_offset(mu, count),
7,104✔
2818
              "count argument to map signal is not offset type");
2819
}
7,104✔
2820

2821
void mir_build_map_const(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
252✔
2822
                         mir_value_t count)
2823
{
2824
   mir_build_3(mu, MIR_OP_MAP_CONST, MIR_NULL_TYPE, MIR_NULL_STAMP,
252✔
2825
               src, dst, count);
2826

2827
   MIR_ASSERT(mir_is_signal(mu, dst),
252✔
2828
              "dst argument to map const is not a signal");
2829
   MIR_ASSERT(mir_is_offset(mu, count),
252✔
2830
              "count argument to map const is not offset type");
2831
}
252✔
2832

2833
void mir_build_map_implicit(mir_unit_t *mu, mir_value_t src, mir_value_t dst,
84✔
2834
                            mir_value_t count)
2835
{
2836
   mir_build_3(mu, MIR_OP_MAP_IMPLICIT, MIR_NULL_TYPE, MIR_NULL_STAMP,
84✔
2837
               src, dst, count);
2838

2839
   MIR_ASSERT(mir_is_signal(mu, src),
84✔
2840
              "src argument to map implicit is not a signal");
2841
   MIR_ASSERT(mir_is_signal(mu, dst),
84✔
2842
              "dst argument to map implicit is not a signal");
2843
   MIR_ASSERT(mir_is_offset(mu, count),
84✔
2844
              "count argument type to map implicit is not offset");
2845
}
84✔
2846

2847
mir_value_t mir_build_cmp_trigger(mir_unit_t *mu, mir_value_t left,
62✔
2848
                                  mir_value_t right)
2849
{
2850
   mir_type_t type = mir_trigger_type(mu);
62✔
2851
   mir_value_t result = mir_build_2(mu, MIR_OP_CMP_TRIGGER, type,
62✔
2852
                                    MIR_NULL_STAMP, left, right);
62✔
2853

2854
   MIR_ASSERT(mir_is_signal(mu, left),
62✔
2855
              "cmp trigger left argument must be signal");
2856
   MIR_ASSERT(mir_is_integral(mu, right),
62✔
2857
              "cmp trigger right argument must be integer");
2858

2859
   return result;
62✔
2860
}
2861

2862
mir_value_t mir_build_function_trigger(mir_unit_t *mu, ident_t name,
288✔
2863
                                       const mir_value_t *args, unsigned nargs)
2864
{
2865
   mir_type_t type = mir_trigger_type(mu);
288✔
2866
   node_data_t *n = mir_add_node(mu, MIR_OP_FUNCTION_TRIGGER, type,
576✔
2867
                                 MIR_NULL_STAMP, nargs + 1);
288✔
2868

2869
   mir_set_arg(mu, n, 0, mir_add_linkage(mu, name));
288✔
2870

2871
   for (int i = 0; i < nargs; i++)
760✔
2872
      mir_set_arg(mu, n, i + 1, args[i]);
472✔
2873

2874
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
288✔
2875
}
2876

2877
mir_value_t mir_build_or_trigger(mir_unit_t *mu, mir_value_t left,
45✔
2878
                                 mir_value_t right)
2879
{
2880
   mir_type_t type = mir_trigger_type(mu);
45✔
2881
   mir_value_t result = mir_build_2(mu, MIR_OP_OR_TRIGGER, type,
45✔
2882
                                    MIR_NULL_STAMP, left, right);
45✔
2883

2884
   MIR_ASSERT(mir_is(mu, left, MIR_TYPE_TRIGGER),
45✔
2885
              "or trigger left argument must be trigger");
2886
   MIR_ASSERT(mir_is(mu, right, MIR_TYPE_TRIGGER),
45✔
2887
              "or trigger right argument must be trigger");
2888

2889
   return result;
45✔
2890
}
2891

2892
void mir_build_add_trigger(mir_unit_t *mu, mir_value_t trigger)
501✔
2893
{
2894
   mir_build_1(mu, MIR_OP_ADD_TRIGGER, MIR_NULL_TYPE, MIR_NULL_STAMP, trigger);
501✔
2895

2896
   MIR_ASSERT(mir_is(mu, trigger, MIR_TYPE_TRIGGER),
501✔
2897
              "add trigger argument must be trigger");
2898
}
501✔
2899

2900
mir_value_t mir_build_link_package(mir_unit_t *mu, ident_t name)
14,329✔
2901
{
2902
   mir_value_t link = mir_add_linkage(mu, name);
14,329✔
2903
   mir_type_t type = mir_context_type(mu, name);
14,329✔
2904

2905
   mir_value_t result = mir_build_1(mu, MIR_OP_LINK_PACKAGE, type,
14,329✔
2906
                                    MIR_NULL_STAMP, link);
14,329✔
2907

2908
   MIR_ASSERT(name != mu->name, "cannot link the current unit");
14,329✔
2909

2910
   return result;
14,329✔
2911
}
2912

2913
mir_value_t mir_build_link_var(mir_unit_t *mu, ident_t unit,
5,811✔
2914
                               mir_value_t context, ident_t name,
2915
                               mir_type_t type)
2916
{
2917
   mir_type_t pointer = mir_get_var_pointer(mu, type);
5,811✔
2918
   mir_value_t link = mir_add_linkage(mu, unit);
5,811✔
2919
   mir_value_t var = mir_add_extvar(mu, name);
5,811✔
2920
   mir_value_t result = mir_build_3(mu, MIR_OP_LINK_VAR, pointer,
5,811✔
2921
                                    MIR_NULL_STAMP, link, context, var);
5,811✔
2922

2923
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
5,811✔
2924
              "first argument to link var must be context");
2925

2926
   return result;
5,811✔
2927
}
2928

2929
void mir_build_bind_foreign(mir_unit_t *mu, mir_value_t spec,
1,294✔
2930
                            mir_value_t length, mir_value_t locus)
2931
{
2932
   if (mir_is_null(locus))
1,294✔
2933
      mir_build_2(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
232✔
2934
                  spec, length);
2935
   else
2936
      mir_build_3(mu, MIR_OP_BIND_FOREIGN, MIR_NULL_TYPE, MIR_NULL_STAMP,
1,062✔
2937
                  spec, length, locus);
2938

2939
   MIR_ASSERT(mir_is(mu, spec, MIR_TYPE_POINTER),
1,294✔
2940
              "spec argument to bind foreign must be a pointer");
2941
   MIR_ASSERT(mir_is_offset(mu, length),
1,294✔
2942
              "legnth argument to bind foreign must be offset");
2943
   MIR_ASSERT(mir_is_null(locus) || mir_is(mu, locus, MIR_TYPE_LOCUS),
1,294✔
2944
              "locus argument to bind foreign value must be a debug locus");
2945
}
1,294✔
2946

2947
mir_value_t mir_build_bind_external(mir_unit_t *mu, mir_value_t locus,
261✔
2948
                                    ident_t scope, mir_type_t type,
2949
                                    mir_stamp_t stamp)
2950
{
2951
   mir_type_t pointer = mir_get_var_pointer(mu, type);
261✔
2952
   mir_value_t link = mir_add_linkage(mu, scope);
261✔
2953
   mir_value_t result = mir_build_2(mu, MIR_OP_BIND_EXTERNAL, pointer, stamp,
261✔
2954
                                    locus, link);
2955

2956
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
261✔
2957
              "bind external argument must be locus");
2958

2959
   return result;
261✔
2960
}
2961

2962
mir_value_t mir_build_context_upref(mir_unit_t *mu, int hops)
15,961✔
2963
{
2964
   mir_type_t type = MIR_NULL_TYPE;
15,961✔
2965
   if (hops == 0)
15,961✔
2966
      type = mir_self_type(mu);
3,641✔
2967
   else {
2968
      mir_shape_t *s = mu->parent;
12,320✔
2969
      for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
12,698✔
2970

2971
      if (s != NULL) type = s->type;
12,320✔
2972
   }
2973

2974
   mir_value_t result = mir_build_1(mu, MIR_OP_CONTEXT_UPREF, type,
15,961✔
2975
                                    MIR_NULL_STAMP, mir_enum(hops));
15,961✔
2976

2977
   MIR_ASSERT(hops >= 0, "invalid hop count");
15,961✔
2978
   MIR_ASSERT(!mir_is_null(type), "hop count is greater than depth");
15,961✔
2979

2980
   return result;
15,961✔
2981
}
2982

2983
mir_value_t mir_build_var_upref(mir_unit_t *mu, int hops, int nth)
63,596✔
2984
{
2985
   mir_type_t type = MIR_NULL_TYPE;
63,596✔
2986
   mir_value_t link = MIR_NULL_VALUE;
63,596✔
2987

2988
   mir_shape_t *s = mu->parent;
63,596✔
2989
   for (int i = 1; s != NULL && i < hops; i++, s = s->parent);
78,113✔
2990

2991
   if (s != NULL && nth >= 0 && nth < s->num_slots) {
63,596✔
2992
      type = s->slots[nth].pointer;
63,596✔
2993
      link = mir_add_linkage(mu, s->name);
63,596✔
2994
   }
2995

2996
   mir_value_t result = mir_build_3(mu, MIR_OP_VAR_UPREF, type, MIR_NULL_STAMP,
63,596✔
2997
                                    mir_enum(hops), link, mir_enum(nth));
2998

2999
   MIR_ASSERT(hops > 0, "invalid hop count");
63,596✔
3000
   MIR_ASSERT(!mir_is_null(type), "invalid variable reference");
63,596✔
3001

3002
   return result;
63,596✔
3003
}
3004

3005
void mir_build_sched_event(mir_unit_t *mu, mir_value_t signal,
8,084✔
3006
                           mir_value_t count)
3007
{
3008
   mir_build_2(mu, MIR_OP_SCHED_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
8,084✔
3009
               signal, count);
3010

3011
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
8,084✔
3012
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
8,084✔
3013
}
8,084✔
3014

3015
void mir_build_clear_event(mir_unit_t *mu, mir_value_t signal,
702✔
3016
                           mir_value_t count)
3017
{
3018
   mir_build_2(mu, MIR_OP_CLEAR_EVENT, MIR_NULL_TYPE, MIR_NULL_STAMP,
702✔
3019
               signal, count);
3020

3021
   MIR_ASSERT(mir_is_signal(mu, signal), "argument must be signal");
702✔
3022
   MIR_ASSERT(mir_is_offset(mu, count), "count argument must be offset");
702✔
3023
}
702✔
3024

3025
mir_value_t mir_build_reflect_value(mir_unit_t *mu, mir_value_t value,
64✔
3026
                                    mir_value_t context, mir_value_t locus,
3027
                                    mir_value_t bounds)
3028
{
3029
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
64✔
3030

3031
   mir_value_t result;
64✔
3032
   if (mir_is_null(bounds))
64✔
3033
      result = mir_build_3(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
56✔
3034
                           value, context, locus);
3035
   else
3036
      result = mir_build_4(mu, MIR_OP_REFLECT_VALUE, type, MIR_NULL_STAMP,
8✔
3037
                           value, context, locus, bounds);
3038

3039
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
64✔
3040
              "invalid reflect value context argument");
3041
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
64✔
3042
              "locus argument to reflect value must be a debug locus");
3043

3044
   return result;
64✔
3045
}
3046

3047
mir_value_t mir_build_reflect_subtype(mir_unit_t *mu, mir_value_t context,
56✔
3048
                                      mir_value_t locus, mir_value_t bounds)
3049
{
3050
   mir_type_t type = mir_access_type(mu, mir_opaque_type(mu));
56✔
3051

3052
   mir_value_t result;
56✔
3053
   if (mir_is_null(bounds))
56✔
3054
      result = mir_build_2(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
56✔
3055
                           context, locus);
3056
   else
UNCOV
3057
      result = mir_build_3(mu, MIR_OP_REFLECT_SUBTYPE, type, MIR_NULL_STAMP,
×
3058
                           context, locus, bounds);
3059

3060
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
56✔
3061
              "invalid reflect subtype context argument");
3062
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
56✔
3063
              "locus argument to reflect subtype must be a debug locus");
3064

3065
   return result;
56✔
3066
}
3067

3068
void mir_build_assert(mir_unit_t *mu, mir_value_t value, mir_value_t message,
18,716✔
3069
                      mir_value_t length, mir_value_t severity,
3070
                      mir_value_t locus, mir_value_t hint_left,
3071
                      mir_value_t hint_right)
3072
{
3073
   int64_t value_const;
18,716✔
3074
   if (mir_get_const(mu, value, &value_const) && value_const != 0) {
18,716✔
UNCOV
3075
      mir_comment(mu, "Always true assertion");
×
UNCOV
3076
      return;
×
3077
   }
3078

3079
   if (mir_is_null(hint_left))
18,716✔
3080
      mir_build_5(mu, MIR_OP_ASSERT, MIR_NULL_TYPE, MIR_NULL_STAMP,
10,802✔
3081
                  value, severity, message, length, locus);
3082
   else {
3083
      node_data_t *n = mir_add_node(mu, MIR_OP_ASSERT, MIR_NULL_TYPE,
15,828✔
3084
                                     MIR_NULL_STAMP, 7);
7,914✔
3085
      mir_set_arg(mu, n, 0, value);
7,914✔
3086
      mir_set_arg(mu, n, 1, severity);
7,914✔
3087
      mir_set_arg(mu, n, 2, message);
7,914✔
3088
      mir_set_arg(mu, n, 3, length);
7,914✔
3089
      mir_set_arg(mu, n, 4, locus);
7,914✔
3090
      mir_set_arg(mu, n, 5, hint_left);
7,914✔
3091
      mir_set_arg(mu, n, 6, hint_right);
7,914✔
3092

3093
      MIR_ASSERT(mir_is_scalar(mu, hint_left), "left hint must be scalar");
7,914✔
3094
      MIR_ASSERT(mir_is_scalar(mu, hint_right), "right hint must be scalar");
7,914✔
3095
   }
3096

3097
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
18,716✔
3098
   MIR_ASSERT(mir_is_null(message) || mir_is(mu, message, MIR_TYPE_POINTER),
18,716✔
3099
              "message parameter to assert is not a pointer");
3100
   MIR_ASSERT(mir_is_bool(mu, value), "value parameter to assert is not bool");
18,716✔
3101
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
18,716✔
3102
              "locus argument to report must be a debug locus");
3103
}
3104

3105
void mir_build_report(mir_unit_t *mu, mir_value_t message, mir_value_t length,
2,771✔
3106
                      mir_value_t severity, mir_value_t locus)
3107
{
3108
   mir_build_4(mu, MIR_OP_REPORT, MIR_NULL_TYPE, MIR_NULL_STAMP,
2,771✔
3109
               severity, message, length, locus);
3110

3111
   MIR_ASSERT(mir_is(mu, message, MIR_TYPE_POINTER),
2,771✔
3112
              "message parameter to report is not a pointer");
3113
   MIR_ASSERT(mir_is_offset(mu, length), "length argument must be offset type");
2,771✔
3114
   MIR_ASSERT(mir_is(mu, locus, MIR_TYPE_LOCUS),
2,771✔
3115
              "locus argument to report must be a debug locus");
3116
}
2,771✔
3117

3118
mir_value_t mir_build_instance_name(mir_unit_t *mu, mir_value_t kind)
1,018✔
3119
{
3120
   mir_type_t type = mir_string_type(mu);
1,018✔
3121
   mir_value_t result = mir_build_1(mu, MIR_OP_INSTANCE_NAME, type,
1,018✔
3122
                                    MIR_NULL_STAMP, kind);
1,018✔
3123

3124
   MIR_ASSERT(mir_is_offset(mu, kind),
1,018✔
3125
              "kind argument to instance name must be offset");
3126

3127
   return result;
1,018✔
3128
}
3129

3130
void mir_build_enter_state(mir_unit_t *mu, mir_value_t state,
1,040✔
3131
                           mir_value_t strong)
3132
{
3133
   if (mir_is_null(strong))
1,040✔
3134
      mir_build_1(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP, state);
1,016✔
3135
   else
3136
      mir_build_2(mu, MIR_OP_ENTER_STATE, MIR_NULL_TYPE, MIR_NULL_STAMP,
24✔
3137
                  state, strong);
3138

3139
   MIR_ASSERT(mir_is_integral(mu, state), "state must have integer type");
1,040✔
3140
   MIR_ASSERT(mir_is_null(strong)
1,040✔
3141
              || mir_check_type(mu, strong, mir_bool_type(mu)),
3142
                "strong argument not is not boolean");
3143
}
1,040✔
3144

3145
mir_value_t mir_build_closure(mir_unit_t *mu, ident_t func, mir_value_t context,
6,409✔
3146
                              mir_type_t atype, mir_type_t rtype)
3147
{
3148
   mir_type_t ctype = mir_closure_type(mu, atype, rtype);
6,409✔
3149
   mir_value_t link = mir_add_linkage(mu, func);
6,409✔
3150

3151
   mir_value_t result = mir_build_2(mu, MIR_OP_CLOSURE, ctype, MIR_NULL_STAMP,
6,409✔
3152
                                    link, context);
3153

3154
   MIR_ASSERT(mir_is(mu, context, MIR_TYPE_CONTEXT),
6,409✔
3155
              "invalid closure context argument");
3156

3157
   return result;
6,409✔
3158
}
3159

3160
mir_value_t mir_build_resolution_wrapper(mir_unit_t *mu, mir_type_t type,
5,902✔
3161
                                         mir_value_t closure, mir_value_t nlits)
3162
{
3163
   mir_type_t rtype = mir_resolution_type(mu, type);
5,902✔
3164
   mir_value_t result = mir_build_2(mu, MIR_OP_RESOLUTION_WRAPPER, rtype,
5,902✔
3165
                                    MIR_NULL_STAMP, closure, nlits);
5,902✔
3166

3167
   MIR_ASSERT(mir_is(mu, closure, MIR_TYPE_CLOSURE),
5,902✔
3168
              "first argument to resolution wrapper must be closure");
3169

3170
   return result;
5,902✔
3171
}
3172

3173
mir_value_t mir_build_locus(mir_unit_t *mu, object_t *obj)
101,784✔
3174
{
3175
   node_data_t *n = mir_add_node(mu, MIR_OP_LOCUS, mir_locus_type(mu),
101,784✔
3176
                                  MIR_NULL_STAMP, 0);
101,784✔
3177
   n->locus = obj;
101,784✔
3178

3179
   return (mir_value_t){ .tag = MIR_TAG_NODE, .id = mir_node_id(mu, n) };
101,784✔
3180
}
3181

3182
mir_value_t mir_build_cast(mir_unit_t *mu, mir_type_t type, mir_value_t value)
76,540✔
3183
{
3184
   mir_type_t from = mir_get_type(mu, value);
76,540✔
3185
   if (mir_equals(from, type))
76,540✔
3186
      return value;
76,540✔
3187

3188
   const mir_class_t class = mir_get_class(mu, type);
75,533✔
3189
   const bool integral = (class == MIR_TYPE_OFFSET || class == MIR_TYPE_INT);
75,533✔
3190

3191
   int64_t cval;
75,533✔
3192
   if (integral && mir_get_const(mu, value, &cval))
75,533✔
3193
      return mir_const(mu, type, cval);
524✔
3194

3195
   if (class == MIR_TYPE_VEC2 || class == MIR_TYPE_VEC4) {
75,009✔
3196
      node_data_t *n = mir_node_data(mu, value);
1,101✔
3197
      if (n->op == MIR_OP_CONST_VEC) {
1,101✔
3198
         const uint64_t bbits = (class == MIR_TYPE_VEC2 ? 0 : n->bits[1]);
757✔
3199
         return mir_const_vec(mu, type, n->bits[0], bbits);
757✔
3200
      }
3201
   }
3202
   else if (integral && mir_is_vector(mu, value)) {
73,908✔
3203
      node_data_t *n = mir_node_data(mu, value);
313✔
3204
      if (n->op == MIR_OP_CONST_VEC) {
313✔
3205
         MIR_ASSERT(n->bits[1] == 0, "X value in integral cast");
309✔
3206
         return mir_const(mu, type, n->bits[0]);
309✔
3207
      }
3208
   }
3209

3210
   mir_stamp_t stamp = mir_stamp_cast(mu, type, mir_get_stamp(mu, value));
73,943✔
3211

3212
   mir_value_t result = mir_build_1(mu, MIR_OP_CAST, type, stamp, value);
73,943✔
3213

3214
#ifdef DEBUG
3215
   static const mir_class_t allowed[][2] = {
73,943✔
3216
      { MIR_TYPE_INT,    MIR_TYPE_OFFSET  },
3217
      { MIR_TYPE_OFFSET, MIR_TYPE_INT     },
3218
      { MIR_TYPE_INT,    MIR_TYPE_INT     },
3219
      { MIR_TYPE_INT,    MIR_TYPE_REAL    },
3220
      { MIR_TYPE_REAL,   MIR_TYPE_INT     },
3221
      { MIR_TYPE_REAL,   MIR_TYPE_REAL    },
3222
      { MIR_TYPE_ACCESS, MIR_TYPE_ACCESS  },
3223
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC2    },
3224
      { MIR_TYPE_VEC2,   MIR_TYPE_VEC4    },
3225
      { MIR_TYPE_VEC2,   MIR_TYPE_VEC2    },
3226
      { MIR_TYPE_VEC4,   MIR_TYPE_VEC4    },
3227
      { MIR_TYPE_VEC2,   MIR_TYPE_INT     },
3228
      { MIR_TYPE_VEC2,   MIR_TYPE_OFFSET  },
3229
   };
3230

3231
   if (value.tag == MIR_TAG_CONST)
73,943✔
3232
      return result;
71✔
3233

3234
   const mir_class_t from_k = mir_get_class(mu, from);
73,872✔
3235

3236
   for (size_t i = 0; i < ARRAY_LEN(allowed); i++) {
133,376✔
3237
      if (from_k == allowed[i][0] && class == allowed[i][1])
133,376✔
3238
         return result;
73,872✔
3239
   }
3240

UNCOV
3241
   MIR_ASSERT(false, "invalid type conversion in cast");
×
3242
#else
3243
   return result;
3244
#endif
3245
}
3246

UNCOV
3247
void mir_build_debug_out(mir_unit_t *mu, mir_value_t value)
×
3248
{
UNCOV
3249
   mir_build_1(mu, MIR_OP_DEBUG_OUT, MIR_NULL_TYPE, MIR_NULL_STAMP, value);
×
3250

UNCOV
3251
   MIR_ASSERT(mir_is_integral(mu, value), "argument must be integral");
×
3252
}
×
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